PageSourceSearch

https://carauto.app/vendor/three/three.core.js

js carauto.app collected 2026-10-02 01:13:36 UTC 1,427,497 bytes, 59,732 lines download raw bytes

1/**
2 * @license
3 * Copyright 2010-2026 Three.js Authors
4 * SPDX-License-Identifier: MIT
5 */
6const REVISION = '184';
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
vendor: 28,453 bytes, lines 77-1718
77
78 */
79const PCFSoftShadowMap = 2;
80
81/**
82 * Filters shadow maps using the Variance Shadow Map (VSM) algorithm.
83 * When using VSMShadowMap all shadow receivers will also cast shadows.
84 *
85 * @type {number}
86 * @constant
87 */
88const VSMShadowMap = 3;
89
90/**
91 * Only front faces are rendered.
92 *
93 * @type {number}
94 * @constant
95 */
96const FrontSide = 0;
97
98/**
99 * Only back faces are rendered.
100 *
101 * @type {number}
102 * @constant
103 */
104const BackSide = 1;
105
106/**
107 * Both front and back faces are rendered.
108 *
109 * @type {number}
110 * @constant
111 */
112const DoubleSide = 2;
113
114/**
115 * No blending is performed which effectively disables
116 * alpha transparency.
117 *
118 * @type {number}
119 * @constant
120 */
121const NoBlending = 0;
122
123/**
124 * The default blending.
125 *
126 * @type {number}
127 * @constant
128 */
129const NormalBlending = 1;
130
131/**
132 * Represents additive blending.
133 *
134 * @type {number}
135 * @constant
136 */
137const AdditiveBlending = 2;
138
139/**
140 * Represents subtractive blending.
141 *
142 * @type {number}
143 * @constant
144 */
145const SubtractiveBlending = 3;
146
147/**
148 * Represents multiply blending.
149 *
150 * @type {number}
151 * @constant
152 */
153const MultiplyBlending = 4;
154
155/**
156 * Represents custom blending.
157 *
158 * @type {number}
159 * @constant
160 */
161const CustomBlending = 5;
162
163/**
164 * Represents material blending.
165 *
166 * @type {number}
167 * @constant
168 */
169const MaterialBlending = 6;
170
171/**
172 * A `source + destination` blending equation.
173 *
174 * @type {number}
175 * @constant
176 */
177const AddEquation = 100;
178
179/**
180 * A `source - destination` blending equation.
181 *
182 * @type {number}
183 * @constant
184 */
185const SubtractEquation = 101;
186
187/**
188 * A `destination - source` blending equation.
189 *
190 * @type {number}
191 * @constant
192 */
193const ReverseSubtractEquation = 102;
194
195/**
196 * A blend equation that uses the minimum of source and destination.
197 *
198 * @type {number}
199 * @constant
200 */
201const MinEquation = 103;
202
203/**
204 * A blend equation that uses the maximum of source and destination.
205 *
206 * @type {number}
207 * @constant
208 */
209const MaxEquation = 104;
210
211/**
212 * Multiplies all colors by `0`.
213 *
214 * @type {number}
215 * @constant
216 */
217const ZeroFactor = 200;
218
219/**
220 * Multiplies all colors by `1`.
221 *
222 * @type {number}
223 * @constant
224 */
225const OneFactor = 201;
226
227/**
228 * Multiplies all colors by the source colors.
229 *
230 * @type {number}
231 * @constant
232 */
233const SrcColorFactor = 202;
234
235/**
236 * Multiplies all colors by `1` minus each source color.
237 *
238 * @type {number}
239 * @constant
240 */
241const OneMinusSrcColorFactor = 203;
242
243/**
244 * Multiplies all colors by the source alpha value.
245 *
246 * @type {number}
247 * @constant
248 */
249const SrcAlphaFactor = 204;
250
251/**
252 * Multiplies all colors by 1 minus the source alpha value.
253 *
254 * @type {number}
255 * @constant
256 */
257const OneMinusSrcAlphaFactor = 205;
258
259/**
260 * Multiplies all colors by the destination alpha value.
261 *
262 * @type {number}
263 * @constant
264 */
265const DstAlphaFactor = 206;
266
267/**
268 * Multiplies all colors by `1` minus the destination alpha value.
269 *
270 * @type {number}
271 * @constant
272 */
273const OneMinusDstAlphaFactor = 207;
274
275/**
276 * Multiplies all colors by the destination color.
277 *
278 * @type {number}
279 * @constant
280 */
281const DstColorFactor = 208;
282
283/**
284 * Multiplies all colors by `1` minus each destination color.
285 *
286 * @type {number}
287 * @constant
288 */
289const OneMinusDstColorFactor = 209;
290
291/**
292 * Multiplies the RGB colors by the smaller of either the source alpha
293 * value or the value of `1` minus the destination alpha value. The alpha
294 * value is multiplied by `1`.
295 *
296 * @type {number}
297 * @constant
298 */
299const SrcAlphaSaturateFactor = 210;
300
301/**
302 * Multiplies all colors by a constant color.
303 *
304 * @type {number}
305 * @constant
306 */
307const ConstantColorFactor = 211;
308
309/**
310 * Multiplies all colors by `1` minus a constant color.
311 *
312 * @type {number}
313 * @constant
314 */
315const OneMinusConstantColorFactor = 212;
316
317/**
318 * Multiplies all colors by a constant alpha value.
319 *
320 * @type {number}
321 * @constant
322 */
323const ConstantAlphaFactor = 213;
324
325/**
326 * Multiplies all colors by 1 minus a constant alpha value.
327 *
328 * @type {number}
329 * @constant
330 */
331const OneMinusConstantAlphaFactor = 214;
332
333/**
334 * Never pass.
335 *
336 * @type {number}
337 * @constant
338 */
339const NeverDepth = 0;
340
341/**
342 * Always pass.
343 *
344 * @type {number}
345 * @constant
346 */
347const AlwaysDepth = 1;
348
349/**
350 * Pass if the incoming value is less than the depth buffer value.
351 *
352 * @type {number}
353 * @constant
354 */
355const LessDepth = 2;
356
357/**
358 * Pass if the incoming value is less than or equal to the depth buffer value.
359 *
360 * @type {number}
361 * @constant
362 */
363const LessEqualDepth = 3;
364
365/**
366 * Pass if the incoming value equals the depth buffer value.
367 *
368 * @type {number}
369 * @constant
370 */
371const EqualDepth = 4;
372
373/**
374 * Pass if the incoming value is greater than or equal to the depth buffer value.
375 *
376 * @type {number}
377 * @constant
378 */
379const GreaterEqualDepth = 5;
380
381/**
382 * Pass if the incoming value is greater than the depth buffer value.
383 *
384 * @type {number}
385 * @constant
386 */
387const GreaterDepth = 6;
388
389/**
390 * Pass if the incoming value is not equal to the depth buffer value.
391 *
392 * @type {number}
393 * @constant
394 */
395const NotEqualDepth = 7;
396
397/**
398 * Multiplies the environment map color with the surface color.
399 *
400 * @type {number}
401 * @constant
402 */
403const MultiplyOperation = 0;
404
405/**
406 * Uses reflectivity to blend between the two colors.
407 *
408 * @type {number}
409 * @constant
410 */
411const MixOperation = 1;
412
413/**
414 * Adds the two colors.
415 *
416 * @type {number}
417 * @constant
418 */
419const AddOperation = 2;
420
421/**
422 * No tone mapping is applied.
423 *
424 * @type {number}
425 * @constant
426 */
427const NoToneMapping = 0;
428
429/**
430 * Linear tone mapping.
431 *
432 * @type {number}
433 * @constant
434 */
435const LinearToneMapping = 1;
436
437/**
438 * Reinhard tone mapping.
439 *
440 * @type {number}
441 * @constant
442 */
443const ReinhardToneMapping = 2;
444
445/**
446 * Cineon tone mapping.
447 *
448 * @type {number}
449 * @constant
450 */
451const CineonToneMapping = 3;
452
453/**
454 * ACES Filmic tone mapping.
455 *
456 * @type {number}
457 * @constant
458 */
459const ACESFilmicToneMapping = 4;
460
461/**
462 * Custom tone mapping.
463 *
464 * Expects a custom implementation by modifying shader code of the material's fragment shader.
465 *
466 * @type {number}
467 * @constant
468 */
469const CustomToneMapping = 5;
470
471/**
472 * AgX tone mapping.
473 *
474 * @type {number}
475 * @constant
476 */
477const AgXToneMapping = 6;
478
479/**
480 * Neutral tone mapping.
481 *
482 * Implementation based on the Khronos 3D Commerce Group standard tone mapping.
483 *
484 * @type {number}
485 * @constant
486 */
487const NeutralToneMapping = 7;
488
489/**
490 * The skinned mesh shares the same world space as the skeleton.
491 *
492 * @type {string}
493 * @constant
494 */
495const AttachedBindMode = 'attached';
496
497/**
498 * The skinned mesh does not share the same world space as the skeleton.
499 * This is useful when a skeleton is shared across multiple skinned meshes.
500 *
501 * @type {string}
502 * @constant
503 */
504const DetachedBindMode = 'detached';
505
506/**
507 * Maps textures using the geometry's UV coordinates.
508 *
509 * @type {number}
510 * @constant
511 */
512const UVMapping = 300;
513
514/**
515 * Reflection mapping for cube textures.
516 *
517 * @type {number}
518 * @constant
519 */
520const CubeReflectionMapping = 301;
521
522/**
523 * Refraction mapping for cube textures.
524 *
525 * @type {number}
526 * @constant
527 */
528const CubeRefractionMapping = 302;
529
530/**
531 * Reflection mapping for equirectangular textures.
532 *
533 * @type {number}
534 * @constant
535 */
536const EquirectangularReflectionMapping = 303;
537
538/**
539 * Refraction mapping for equirectangular textures.
540 *
541 * @type {number}
542 * @constant
543 */
544const EquirectangularRefractionMapping = 304;
545
546/**
547 * Reflection mapping for PMREM textures.
548 *
549 * @type {number}
550 * @constant
551 */
552const CubeUVReflectionMapping = 306;
553
554/**
555 * The texture will simply repeat to infinity.
556 *
557 * @type {number}
558 * @constant
559 */
560const RepeatWrapping = 1000;
561
562/**
563 * The last pixel of the texture stretches to the edge of the mesh.
564 *
565 * @type {number}
566 * @constant
567 */
568const ClampToEdgeWrapping = 1001;
569
570/**
571 * The texture will repeats to infinity, mirroring on each repeat.
572 *
573 * @type {number}
574 * @constant
575 */
576const MirroredRepeatWrapping = 1002;
577
578/**
579 * Returns the value of the texture element that is nearest (in Manhattan distance)
580 * to the specified texture coordinates.
581 *
582 * @type {number}
583 * @constant
584 */
585const NearestFilter = 1003;
586
587/**
588 * Chooses the mipmap that most closely matches the size of the pixel being textured
589 * and uses the `NearestFilter` criterion (the texel nearest to the center of the pixel)
590 * to produce a texture value.
591 *
592 * @type {number}
593 * @constant
594 */
595const NearestMipmapNearestFilter = 1004;
596const NearestMipMapNearestFilter = 1004; // legacy
597
598/**
599 * Chooses the two mipmaps that most closely match the size of the pixel being textured and
600 * uses the `NearestFilter` criterion to produce a texture value from each mipmap.
601 * The final texture value is a weighted average of those two values.
602 *
603 * @type {number}
604 * @constant
605 */
606const NearestMipmapLinearFilter = 1005;
607const NearestMipMapLinearFilter = 1005; // legacy
608
609/**
610 * Returns the weighted average of the four texture elements that are closest to the specified
611 * texture coordinates, and can include items wrapped or repeated from other parts of a texture,
612 * depending on the values of `wrapS` and `wrapT`, and on the exact mapping.
613 *
614 * @type {number}
615 * @constant
616 */
617const LinearFilter = 1006;
618
619/**
620 * Chooses the mipmap that most closely matches the size of the pixel being textured and uses
621 * the `LinearFilter` criterion (a weighted average of the four texels that are closest to the
622 * center of the pixel) to produce a texture value.
623 *
624 * @type {number}
625 * @constant
626 */
627const LinearMipmapNearestFilter = 1007;
628const LinearMipMapNearestFilter = 1007; // legacy
629
630/**
631 * Chooses the two mipmaps that most closely match the size of the pixel being textured and uses
632 * the `LinearFilter` criterion to produce a texture value from each mipmap. The final texture value
633 * is a weighted average of those two values.
634 *
635 * @type {number}
636 * @constant
637 */
638const LinearMipmapLinearFilter = 1008;
639const LinearMipMapLinearFilter = 1008; // legacy
640
641/**
642 * An unsigned byte data type for textures.
643 *
644 * @type {number}
645 * @constant
646 */
647const UnsignedByteType = 1009;
648
649/**
650 * A byte data type for textures.
651 *
652 * @type {number}
653 * @constant
654 */
655const ByteType = 1010;
656
657/**
658 * A short data type for textures.
659 *
660 * @type {number}
661 * @constant
662 */
663const ShortType = 1011;
664
665/**
666 * An unsigned short data type for textures.
667 *
668 * @type {number}
669 * @constant
670 */
671const UnsignedShortType = 1012;
672
673/**
674 * An int data type for textures.
675 *
676 * @type {number}
677 * @constant
678 */
679const IntType = 1013;
680
681/**
682 * An unsigned int data type for textures.
683 *
684 * @type {number}
685 * @constant
686 */
687const UnsignedIntType = 1014;
688
689/**
690 * A float data type for textures.
691 *
692 * @type {number}
693 * @constant
694 */
695const FloatType = 1015;
696
697/**
698 * A half float data type for textures.
699 *
700 * @type {number}
701 * @constant
702 */
703const HalfFloatType = 1016;
704
705/**
706 * An unsigned short 4_4_4_4 (packed) data type for textures.
707 *
708 * @type {number}
709 * @constant
710 */
711const UnsignedShort4444Type = 1017;
712
713/**
714 * An unsigned short 5_5_5_1 (packed) data type for textures.
715 *
716 * @type {number}
717 * @constant
718 */
719const UnsignedShort5551Type = 1018;
720
721/**
722 * An unsigned int 24_8 data type for textures.
723 *
724 * @type {number}
725 * @constant
726 */
727const UnsignedInt248Type = 1020;
728
729/**
730 * An unsigned int 5_9_9_9 (packed) data type for textures.
731 *
732 * @type {number}
733 * @constant
734 */
735const UnsignedInt5999Type = 35902;
736
737/**
738 * An unsigned int 10_11_11 (packed) data type for textures.
739 *
740 * @type {number}
741 * @constant
742 */
743const UnsignedInt101111Type = 35899;
744
745/**
746 * Discards the red, green and blue components and reads just the alpha component.
747 *
748 * @type {number}
749 * @constant
750 */
751const AlphaFormat = 1021;
752
753/**
754 * Discards the alpha component and reads the red, green and blue component.
755 *
756 * @type {number}
757 * @constant
758 */
759const RGBFormat = 1022;
760
761/**
762 * Reads the red, green, blue and alpha components.
763 *
764 * @type {number}
765 * @constant
766 */
767const RGBAFormat = 1023;
768
769/**
770 * Reads each element as a single depth value, converts it to floating point, and clamps to the range `[0,1]`.
771 *
772 * @type {number}
773 * @constant
774 */
775const DepthFormat = 1026;
776
777/**
778 * Reads each element is a pair of depth and stencil values. The depth component of the pair is interpreted as
779 * in `DepthFormat`. The stencil component is interpreted based on the depth + stencil internal format.
780 *
781 * @type {number}
782 * @constant
783 */
784const DepthStencilFormat = 1027;
785
786/**
787 * Discards the green, blue and alpha components and reads just the red component.
788 *
789 * @type {number}
790 * @constant
791 */
792const RedFormat = 1028;
793
794/**
795 * Discards the green, blue and alpha components and reads just the red component. The texels are read as integers instead of floating point.
796 *
797 * @type {number}
798 * @constant
799 */
800const RedIntegerFormat = 1029;
801
802/**
803 * Discards the alpha, and blue components and reads the red, and green components.
804 *
805 * @type {number}
806 * @constant
807 */
808const RGFormat = 1030;
809
810/**
811 * Discards the alpha, and blue components and reads the red, and green components. The texels are read as integers instead of floating point.
812 *
813 * @type {number}
814 * @constant
815 */
816const RGIntegerFormat = 1031;
817
818/**
819 * Discards the alpha component and reads the red, green and blue component. The texels are read as integers instead of floating point.
820 *
821 * @type {number}
822 * @constant
823 */
824const RGBIntegerFormat = 1032;
825
826/**
827 * Reads the red, green, blue and alpha components. The texels are read as integers instead of floating point.
828 *
829 * @type {number}
830 * @constant
831 */
832const RGBAIntegerFormat = 1033;
833
834/**
835 * A DXT1-compressed image in an RGB image format.
836 *
837 * @type {number}
838 * @constant
839 */
840const RGB_S3TC_DXT1_Format = 33776;
841
842/**
843 * A DXT1-compressed image in an RGB image format with a simple on/off alpha value.
844 *
845 * @type {number}
846 * @constant
847 */
848const RGBA_S3TC_DXT1_Format = 33777;
849
850/**
851 * A DXT3-compressed image in an RGBA image format. Compared to a 32-bit RGBA texture, it offers 4:1 compression.
852 *
853 * @type {number}
854 * @constant
855 */
856const RGBA_S3TC_DXT3_Format = 33778;
857
858/**
859 * A DXT5-compressed image in an RGBA image format. It also provides a 4:1 compression, but differs to the DXT3
860 * compression in how the alpha compression is done.
861 *
862 * @type {number}
863 * @constant
864 */
865const RGBA_S3TC_DXT5_Format = 33779;
866
867/**
868 * PVRTC RGB compression in 4-bit mode. One block for each 4×4 pixels.
869 *
870 * @type {number}
871 * @constant
872 */
873const RGB_PVRTC_4BPPV1_Format = 35840;
874
875/**
876 * PVRTC RGB compression in 2-bit mode. One block for each 8×4 pixels.
877 *
878 * @type {number}
879 * @constant
880 */
881const RGB_PVRTC_2BPPV1_Format = 35841;
882
883/**
884 * PVRTC RGBA compression in 4-bit mode. One block for each 4×4 pixels.
885 *
886 * @type {number}
887 * @constant
888 */
889const RGBA_PVRTC_4BPPV1_Format = 35842;
890
891/**
892 * PVRTC RGBA compression in 2-bit mode. One block for each 8×4 pixels.
893 *
894 * @type {number}
895 * @constant
896 */
897const RGBA_PVRTC_2BPPV1_Format = 35843;
898
899/**
900 * ETC1 RGB format.
901 *
902 * @type {number}
903 * @constant
904 */
905const RGB_ETC1_Format = 36196;
906
907/**
908 * ETC2 RGB format.
909 *
910 * @type {number}
911 * @constant
912 */
913const RGB_ETC2_Format = 37492;
914
915/**
916 * ETC2 RGBA format.
917 *
918 * @type {number}
919 * @constant
920 */
921const RGBA_ETC2_EAC_Format = 37496;
922
923/**
924 * EAC R11 UNORM format.
925 *
926 * @type {number}
927 * @constant
928 */
929const R11_EAC_Format = 37488; // 0x9270
930
931/**
932 * EAC R11 SNORM format.
933 *
934 * @type {number}
935 * @constant
936 */
937const SIGNED_R11_EAC_Format = 37489; // 0x9271
938
939/**
940 * EAC RG11 UNORM format.
941 *
942 * @type {number}
943 * @constant
944 */
945const RG11_EAC_Format = 37490; // 0x9272
946
947/**
948 * EAC RG11 SNORM format.
949 *
950 * @type {number}
951 * @constant
952 */
953const SIGNED_RG11_EAC_Format = 37491; // 0x9273
954
955/**
956 * ASTC RGBA 4x4 format.
957 *
958 * @type {number}
959 * @constant
960 */
961const RGBA_ASTC_4x4_Format = 37808;
962
963/**
964 * ASTC RGBA 5x4 format.
965 *
966 * @type {number}
967 * @constant
968 */
969const RGBA_ASTC_5x4_Format = 37809;
970
971/**
972 * ASTC RGBA 5x5 format.
973 *
974 * @type {number}
975 * @constant
976 */
977const RGBA_ASTC_5x5_Format = 37810;
978
979/**
980 * ASTC RGBA 6x5 format.
981 *
982 * @type {number}
983 * @constant
984 */
985const RGBA_ASTC_6x5_Format = 37811;
986
987/**
988 * ASTC RGBA 6x6 format.
989 *
990 * @type {number}
991 * @constant
992 */
993const RGBA_ASTC_6x6_Format = 37812;
994
995/**
996 * ASTC RGBA 8x5 format.
997 *
998 * @type {number}
999 * @constant
1000 */
1001const RGBA_ASTC_8x5_Format = 37813;
1002
1003/**
1004 * ASTC RGBA 8x6 format.
1005 *
1006 * @type {number}
1007 * @constant
1008 */
1009const RGBA_ASTC_8x6_Format = 37814;
1010
1011/**
1012 * ASTC RGBA 8x8 format.
1013 *
1014 * @type {number}
1015 * @constant
1016 */
1017const RGBA_ASTC_8x8_Format = 37815;
1018
1019/**
1020 * ASTC RGBA 10x5 format.
1021 *
1022 * @type {number}
1023 * @constant
1024 */
1025const RGBA_ASTC_10x5_Format = 37816;
1026
1027/**
1028 * ASTC RGBA 10x6 format.
1029 *
1030 * @type {number}
1031 * @constant
1032 */
1033const RGBA_ASTC_10x6_Format = 37817;
1034
1035/**
1036 * ASTC RGBA 10x8 format.
1037 *
1038 * @type {number}
1039 * @constant
1040 */
1041const RGBA_ASTC_10x8_Format = 37818;
1042
1043/**
1044 * ASTC RGBA 10x10 format.
1045 *
1046 * @type {number}
1047 * @constant
1048 */
1049const RGBA_ASTC_10x10_Format = 37819;
1050
1051/**
1052 * ASTC RGBA 12x10 format.
1053 *
1054 * @type {number}
1055 * @constant
1056 */
1057const RGBA_ASTC_12x10_Format = 37820;
1058
1059/**
1060 * ASTC RGBA 12x12 format.
1061 *
1062 * @type {number}
1063 * @constant
1064 */
1065const RGBA_ASTC_12x12_Format = 37821;
1066
1067/**
1068 * BPTC RGBA format.
1069 *
1070 * @type {number}
1071 * @constant
1072 */
1073const RGBA_BPTC_Format = 36492;
1074
1075/**
1076 * BPTC Signed RGB format.
1077 *
1078 * @type {number}
1079 * @constant
1080 */
1081const RGB_BPTC_SIGNED_Format = 36494;
1082
1083/**
1084 * BPTC Unsigned RGB format.
1085 *
1086 * @type {number}
1087 * @constant
1088 */
1089const RGB_BPTC_UNSIGNED_Format = 36495;
1090
1091/**
1092 * RGTC1 Red format.
1093 *
1094 * @type {number}
1095 * @constant
1096 */
1097const RED_RGTC1_Format = 36283;
1098
1099/**
1100 * RGTC1 Signed Red format.
1101 *
1102 * @type {number}
1103 * @constant
1104 */
1105const SIGNED_RED_RGTC1_Format = 36284;
1106
1107/**
1108 * RGTC2 Red Green format.
1109 *
1110 * @type {number}
1111 * @constant
1112 */
1113const RED_GREEN_RGTC2_Format = 36285;
1114
1115/**
1116 * RGTC2 Signed Red Green format.
1117 *
1118 * @type {number}
1119 * @constant
1120 */
1121const SIGNED_RED_GREEN_RGTC2_Format = 36286;
1122
1123/**
1124 * Animations are played once.
1125 *
1126 * @type {number}
1127 * @constant
1128 */
1129const LoopOnce = 2200;
1130
1131/**
1132 * Animations are played with a chosen number of repetitions, each time jumping from
1133 * the end of the clip directly to its beginning.
1134 *
1135 * @type {number}
1136 * @constant
1137 */
1138const LoopRepeat = 2201;
1139
1140/**
1141 * Animations are played with a chosen number of repetitions, alternately playing forward
1142 * and backward.
1143 *
1144 * @type {number}
1145 * @constant
1146 */
1147const LoopPingPong = 2202;
1148
1149/**
1150 * Discrete interpolation mode for keyframe tracks.
1151 *
1152 * @type {number}
1153 * @constant
1154 */
1155const InterpolateDiscrete = 2300;
1156
1157/**
1158 * Linear interpolation mode for keyframe tracks.
1159 *
1160 * @type {number}
1161 * @constant
1162 */
1163const InterpolateLinear = 2301;
1164
1165/**
1166 * Smooth interpolation mode for keyframe tracks.
1167 *
1168 * @type {number}
1169 * @constant
1170 */
1171const InterpolateSmooth = 2302;
1172
1173/**
1174 * Bezier interpolation mode for keyframe tracks.
1175 *
1176 * Uses cubic Bezier curves with explicit 2D control points.
1177 * Requires tangent data to be set on the track.
1178 *
1179 * @type {number}
1180 * @constant
1181 */
1182const InterpolateBezier = 2303;
1183
1184/**
1185 * Zero curvature ending for animations.
1186 *
1187 * @type {number}
1188 * @constant
1189 */
1190const ZeroCurvatureEnding = 2400;
1191
1192/**
1193 * Zero slope ending for animations.
1194 *
1195 * @type {number}
1196 * @constant
1197 */
1198const ZeroSlopeEnding = 2401;
1199
1200/**
1201 * Wrap around ending for animations.
1202 *
1203 * @type {number}
1204 * @constant
1205 */
1206const WrapAroundEnding = 2402;
1207
1208/**
1209 * Default animation blend mode.
1210 *
1211 * @type {number}
1212 * @constant
1213 */
1214const NormalAnimationBlendMode = 2500;
1215
1216/**
1217 * Additive animation blend mode. Can be used to layer motions on top of
1218 * each other to build complex performances from smaller re-usable assets.
1219 *
1220 * @type {number}
1221 * @constant
1222 */
1223const AdditiveAnimationBlendMode = 2501;
1224
1225/**
1226 * For every three vertices draw a single triangle.
1227 *
1228 * @type {number}
1229 * @constant
1230 */
1231const TrianglesDrawMode = 0;
1232
1233/**
1234 * For each vertex draw a triangle from the last three vertices.
1235 *
1236 * @type {number}
1237 * @constant
1238 */
1239const TriangleStripDrawMode = 1;
1240
1241/**
1242 * For each vertex draw a triangle from the first vertex and the last two vertices.
1243 *
1244 * @type {number}
1245 * @constant
1246 */
1247const TriangleFanDrawMode = 2;
1248
1249/**
1250 * The depth value is inverted (1.0 - z) for visualization purposes.
1251 *
1252 * @type {number}
1253 * @constant
1254 */
1255const BasicDepthPacking = 3200;
1256
1257/**
1258 * The depth value is packed into 32 bit RGBA.
1259 *
1260 * @type {number}
1261 * @constant
1262 */
1263const RGBADepthPacking = 3201;
1264
1265/**
1266 * The depth value is packed into 24 bit RGB.
1267 *
1268 * @type {number}
1269 * @constant
1270 */
1271const RGBDepthPacking = 3202;
1272
1273/**
1274 * The depth value is packed into 16 bit RG.
1275 *
1276 * @type {number}
1277 * @constant
1278 */
1279const RGDepthPacking = 3203;
1280
1281/**
1282 * Normal information is relative to the underlying surface.
1283 *
1284 * @type {number}
1285 * @constant
1286 */
1287const TangentSpaceNormalMap = 0;
1288
1289/**
1290 * Normal information is relative to the object orientation.
1291 *
1292 * @type {number}
1293 * @constant
1294 */
1295const ObjectSpaceNormalMap = 1;
1296
1297// Color space string identifiers, matching CSS Color Module Level 4 and WebGPU names where available.
1298
1299/**
1300 * No color space.
1301 *
1302 * @type {string}
1303 * @constant
1304 */
1305const NoColorSpace = '';
1306
1307/**
1308 * sRGB color space.
1309 *
1310 * @type {string}
1311 * @constant
1312 */
1313const SRGBColorSpace = 'srgb';
1314
1315/**
1316 * sRGB-linear color space.
1317 *
1318 * @type {string}
1319 * @constant
1320 */
1321const LinearSRGBColorSpace = 'srgb-linear';
1322
1323/**
1324 * Linear transfer function.
1325 *
1326 * @type {string}
1327 * @constant
1328 */
1329const LinearTransfer = 'linear';
1330
1331/**
1332 * sRGB transfer function.
1333 *
1334 * @type {string}
1335 * @constant
1336 */
1337const SRGBTransfer = 'srgb';
1338
1339/**
1340 * No normal map packing.
1341 *
1342 * @type {string}
1343 * @constant
1344 */
1345const NoNormalPacking = '';
1346
1347/**
1348 * Normal RG packing.
1349 *
1350 * @type {string}
1351 * @constant
1352 */
1353const NormalRGPacking = 'rg';
1354
1355/**
1356 * Normal GA packing.
1357 *
1358 * @type {string}
1359 * @constant
1360 */
1361const NormalGAPacking = 'ga';
1362
1363/**
1364 * Sets the stencil buffer value to `0`.
1365 *
1366 * @type {number}
1367 * @constant
1368 */
1369const ZeroStencilOp = 0;
1370
1371/**
1372 * Keeps the current value.
1373 *
1374 * @type {number}
1375 * @constant
1376 */
1377const KeepStencilOp = 7680;
1378
1379/**
1380 * Sets the stencil buffer value to the specified reference value.
1381 *
1382 * @type {number}
1383 * @constant
1384 */
1385const ReplaceStencilOp = 7681;
1386
1387/**
1388 * Increments the current stencil buffer value. Clamps to the maximum representable unsigned value.
1389 *
1390 * @type {number}
1391 * @constant
1392 */
1393const IncrementStencilOp = 7682;
1394
1395/**
1396 * Decrements the current stencil buffer value. Clamps to `0`.
1397 *
1398 * @type {number}
1399 * @constant
1400 */
1401const DecrementStencilOp = 7683;
1402
1403/**
1404 * Increments the current stencil buffer value. Wraps stencil buffer value to zero when incrementing
1405 * the maximum representable unsigned value.
1406 *
1407 * @type {number}
1408 * @constant
1409 */
1410const IncrementWrapStencilOp = 34055;
1411
1412/**
1413 * Decrements the current stencil buffer value. Wraps stencil buffer value to the maximum representable
1414 * unsigned value when decrementing a stencil buffer value of `0`.
1415 *
1416 * @type {number}
1417 * @constant
1418 */
1419const DecrementWrapStencilOp = 34056;
1420
1421/**
1422 * Inverts the current stencil buffer value bitwise.
1423 *
1424 * @type {number}
1425 * @constant
1426 */
1427const InvertStencilOp = 5386;
1428
1429/**
1430 * Will never return true.
1431 *
1432 * @type {number}
1433 * @constant
1434 */
1435const NeverStencilFunc = 512;
1436
1437/**
1438 * Will return true if the stencil reference value is less than the current stencil value.
1439 *
1440 * @type {number}
1441 * @constant
1442 */
1443const LessStencilFunc = 513;
1444
1445/**
1446 * Will return true if the stencil reference value is equal to the current stencil value.
1447 *
1448 * @type {number}
1449 * @constant
1450 */
1451const EqualStencilFunc = 514;
1452
1453/**
1454 * Will return true if the stencil reference value is less than or equal to the current stencil value.
1455 *
1456 * @type {number}
1457 * @constant
1458 */
1459const LessEqualStencilFunc = 515;
1460
1461/**
1462 * Will return true if the stencil reference value is greater than the current stencil value.
1463 *
1464 * @type {number}
1465 * @constant
1466 */
1467const GreaterStencilFunc = 516;
1468
1469/**
1470 * Will return true if the stencil reference value is not equal to the current stencil value.
1471 *
1472 * @type {number}
1473 * @constant
1474 */
1475const NotEqualStencilFunc = 517;
1476
1477/**
1478 * Will return true if the stencil reference value is greater than or equal to the current stencil value.
1479 *
1480 * @type {number}
1481 * @constant
1482 */
1483const GreaterEqualStencilFunc = 518;
1484
1485/**
1486 * Will always return true.
1487 *
1488 * @type {number}
1489 * @constant
1490 */
1491const AlwaysStencilFunc = 519;
1492
1493/**
1494 * Never pass.
1495 *
1496 * @type {number}
1497 * @constant
1498 */
1499const NeverCompare = 512;
1500
1501/**
1502 * Pass if the incoming value is less than the texture value.
1503 *
1504 * @type {number}
1505 * @constant
1506 */
1507const LessCompare = 513;
1508
1509/**
1510 * Pass if the incoming value equals the texture value.
1511 *
1512 * @type {number}
1513 * @constant
1514 */
1515const EqualCompare = 514;
1516
1517/**
1518 * Pass if the incoming value is less than or equal to the texture value.
1519 *
1520 * @type {number}
1521 * @constant
1522 */
1523const LessEqualCompare = 515;
1524
1525/**
1526 * Pass if the incoming value is greater than the texture value.
1527 *
1528 * @type {number}
1529 * @constant
1530 */
1531const GreaterCompare = 516;
1532
1533/**
1534 * Pass if the incoming value is not equal to the texture value.
1535 *
1536 * @type {number}
1537 * @constant
1538 */
1539const NotEqualCompare = 517;
1540
1541/**
1542 * Pass if the incoming value is greater than or equal to the texture value.
1543 *
1544 * @type {number}
1545 * @constant
1546 */
1547const GreaterEqualCompare = 518;
1548
1549/**
1550 * Always pass.
1551 *
1552 * @type {number}
1553 * @constant
1554 */
1555const AlwaysCompare = 519;
1556
1557/**
1558 * The contents are intended to be specified once by the application, and used many
1559 * times as the source for drawing and image specification commands.
1560 *
1561 * @type {number}
1562 * @constant
1563 */
1564const StaticDrawUsage = 35044;
1565
1566/**
1567 * The contents are intended to be respecified repeatedly by the application, and
1568 * used many times as the source for drawing and image specification commands.
1569 *
1570 * @type {number}
1571 * @constant
1572 */
1573const DynamicDrawUsage = 35048;
1574
1575/**
1576 * The contents are intended to be specified once by the application, and used at most
1577 * a few times as the source for drawing and image specification commands.
1578 *
1579 * @type {number}
1580 * @constant
1581 */
1582const StreamDrawUsage = 35040;
1583
1584/**
1585 * The contents are intended to be specified once by reading data from the 3D API, and queried
1586 * many times by the application.
1587 *
1588 * @type {number}
1589 * @constant
1590 */
1591const StaticReadUsage = 35045;
1592
1593/**
1594 * The contents are intended to be respecified repeatedly by reading data from the 3D API, and queried
1595 * many times by the application.
1596 *
1597 * @type {number}
1598 * @constant
1599 */
1600const DynamicReadUsage = 35049;
1601
1602/**
1603 * The contents are intended to be specified once by reading data from the 3D API, and queried at most
1604 * a few times by the application
1605 *
1606 * @type {number}
1607 * @constant
1608 */
1609const StreamReadUsage = 35041;
1610
1611/**
1612 * The contents are intended to be specified once by reading data from the 3D API, and used many times as
1613 * the source for WebGL drawing and image specification commands.
1614 *
1615 * @type {number}
1616 * @constant
1617 */
1618const StaticCopyUsage = 35046;
1619
1620/**
1621 * The contents are intended to be respecified repeatedly by reading data from the 3D API, and used many times
1622 * as the source for WebGL drawing and image specification commands.
1623 *
1624 * @type {number}
1625 * @constant
1626 */
1627const DynamicCopyUsage = 35050;
1628
1629/**
1630 * The contents are intended to be specified once by reading data from the 3D API, and used at most a few times
1631 * as the source for WebGL drawing and image specification commands.
1632 *
1633 * @type {number}
1634 * @constant
1635 */
1636const StreamCopyUsage = 35042;
1637
1638/**
1639 * GLSL 1 shader code.
1640 *
1641 * @type {string}
1642 * @constant
1643 */
1644const GLSL1 = '100';
1645
1646/**
1647 * GLSL 3 shader code.
1648 *
1649 * @type {string}
1650 * @constant
1651 */
1652const GLSL3 = '300 es';
1653
1654/**
1655 * WebGL coordinate system.
1656 *
1657 * @type {number}
1658 * @constant
1659 */
1660const WebGLCoordinateSystem = 2000;
1661
1662/**
1663 * WebGPU coordinate system.
1664 *
1665 * @type {number}
1666 * @constant
1667 */
1668const WebGPUCoordinateSystem = 2001;
1669
1670/**
1671 * Represents the different timestamp query types.
1672 *
1673 * @type {ConstantsTimestampQuery}
1674 * @constant
1675 */
1676const TimestampQuery = {
1677	COMPUTE: 'compute',
1678	RENDER: 'render'
1679};
1680
1681/**
1682 * Represents mouse buttons and interaction types in context of controls.
1683 *
1684 * @type {ConstantsInterpolationSamplingType}
1685 * @constant
1686 */
1687const InterpolationSamplingType = {
1688	PERSPECTIVE: 'perspective',
1689	LINEAR: 'linear',
1690	FLAT: 'flat'
1691};
1692
1693/**
1694 * Represents the different interpolation sampling modes.
1695 *
1696 * @type {ConstantsInterpolationSamplingMode}
1697 * @constant
1698 */
1699const InterpolationSamplingMode = {
1700	NORMAL: 'normal',
1701	CENTROID: 'centroid',
1702	SAMPLE: 'sample',
1703	FIRST: 'first',
1704	EITHER: 'either'
1705};
1706
1707/**
1708 * Compatibility flags for features that may not be supported across all platforms.
1709 *
1710 * @type {Object}
1711 * @constant
1712 */
1713const Compatibility = {
1714	TEXTURE_COMPARE: 'depthTextureCompare'
1715};
1716
1717/**
1718 * 
1718This type represents mouse buttons and interaction types in context of controls.
1719 *
1720 * @typedef {Object} ConstantsMouse
1721 * @property {number} MIDDLE - The left mouse button.
1722 * @property {number} LEFT - The middle mouse button.
1723 * @property {number} RIGHT - The right mouse button.
1724 * @property {number} ROTATE - A rotate interaction.
1725 * @property {number} DOLLY - A dolly interaction.
1726 * @property {number} PAN - A pan interaction.
1727 **/
1728
1729/**
1730 * This type represents touch interaction types in context of controls.
1731 *
1732 * @typedef {Object} ConstantsTouch
1733 * @property {number} ROTATE - A rotate interaction.
1734 * @property {number} PAN - A pan interaction.
1735 * @property {number} DOLLY_PAN - The dolly-pan interaction.
1736 * @property {number} DOLLY_ROTATE - A dolly-rotate interaction.
1737 **/
1738
1739/**
1740 * This type represents the different timestamp query types.
1741 *
1742 * @typedef {Object} ConstantsTimestampQuery
1743 * @property {string} COMPUTE - A `compute` timestamp query.
1744 * @property {string} RENDER - A `render` timestamp query.
1745 **/
1746
1747/**
1748 * Represents the different interpolation sampling types.
1749 *
1750 * @typedef {Object} ConstantsInterpolationSamplingType
1751 * @property {string} PERSPECTIVE - Perspective-correct interpolation.
1752 * @property {string} LINEAR - Linear interpolation.
1753 * @property {string} FLAT - Flat interpolation.
1754 */
1755
1756/**
1757 * Represents the different interpolation sampling modes.
1758 *
1759 * @typedef {Object} ConstantsInterpolationSamplingMode
1760 * @property {string} NORMAL - Normal sampling mode.
1761 * @property {string} CENTROID - Centroid sampling mode.
1762 * @property {string} SAMPLE - Sample-specific sampling mode.
1763 * @property {string} FIRST - Flat interpolation using the first vertex.
1764 * @property {string} EITHER - Flat interpolation using either vertex
vendor: 21,397 bytes, lines 1764-2561
1764.
1765 */
1766
1767/**
1768 * Checks if an array contains values that require Uint32 representation.
1769 *
1770 * This function determines whether the array contains any values >= 65535,
1771 * which would require a Uint32Array rather than a Uint16Array for proper storage.
1772 * The function iterates from the end of the array, assuming larger values are
1773 * typically located at the end.
1774 *
1775 * @private
1776 * @param {Array<number>} array - The array to check.
1777 * @return {boolean} True if the array contains values >= 65535, false otherwise.
1778 */
1779function arrayNeedsUint32( array ) {
1780
1781	// assumes larger values usually on last
1782
1783	for ( let i = array.length - 1; i >= 0; -- i ) {
1784
1785		if ( array[ i ] >= 65535 ) return true; // account for PRIMITIVE_RESTART_FIXED_INDEX, #24565
1786
1787	}
1788
1789	return false;
1790
1791}
1792
1793/**
1794 * Map of typed array constructor names to their constructors.
1795 * This mapping enables dynamic creation of typed arrays based on string type names.
1796 *
1797 * @private
1798 * @constant
1799 * @type {Object<string, TypedArrayConstructor>}
1800 */
1801const TYPED_ARRAYS = {
1802	Int8Array: Int8Array,
1803	Uint8Array: Uint8Array,
1804	Uint8ClampedArray: Uint8ClampedArray,
1805	Int16Array: Int16Array,
1806	Uint16Array: Uint16Array,
1807	Int32Array: Int32Array,
1808	Uint32Array: Uint32Array,
1809	Float32Array: Float32Array,
1810	Float64Array: Float64Array
1811};
1812
1813/**
1814 * Creates a typed array of the specified type from the given buffer.
1815 *
1816 * @private
1817 * @param {string} type - The name of the typed array type (e.g., 'Float32Array', 'Uint16Array').
1818 * @param {ArrayBuffer} buffer - The buffer to create the typed array from.
1819 * @return {TypedArray} A new typed array of the specified type.
1820 */
1821function getTypedArray( type, buffer ) {
1822
1823	return new TYPED_ARRAYS[ type ]( buffer );
1824
1825}
1826
1827/**
1828 * Returns `true` if the given object is a typed array.
1829 *
1830 * @param {any} array - The object to check.
1831 * @return {boolean} Whether the given object is a typed array.
1832 */
1833function isTypedArray( array ) {
1834
1835	return ArrayBuffer.isView( array ) && ! ( array instanceof DataView );
1836
1837}
1838
1839/**
1840 * Creates an XHTML element with the specified tag name.
1841 *
1842 * This function uses the XHTML namespace to create DOM elements,
1843 * ensuring proper element creation in XML-based contexts.
1844 *
1845 * @private
1846 * @param {string} name - The tag name of the element to create (e.g., 'canvas', 'div').
1847 * @return {HTMLElement} The created XHTML element.
1848 */
1849function createElementNS( name ) {
1850
1851	return document.createElementNS( 'http://www.w3.org/1999/xhtml', name );
1852
1853}
1854
1855/**
1856 * Creates a canvas element configured for block display.
1857 *
1858 * This is a convenience function that creates a canvas element with
1859 * display style set to 'block', which is commonly used in three.js
1860 * rendering contexts to avoid inline element spacing issues.
1861 *
1862 * @return {HTMLCanvasElement} A canvas element with display set to 'block'.
1863 */
1864function createCanvasElement() {
1865
1866	const canvas = createElementNS( 'canvas' );
1867	canvas.style.display = 'block';
1868	return canvas;
1869
1870}
1871
1872/**
1873 * Internal cache for tracking warning messages to prevent duplicate warnings.
1874 *
1875 * @private
1876 * @type {Object<string, boolean>}
1877 */
1878const _cache = {};
1879
1880/**
1881 * Custom console function handler for intercepting log, warn, and error calls.
1882 *
1883 * @private
1884 * @type {Function|null}
1885 */
1886let _setConsoleFunction = null;
1887
1888/**
1889 * Sets a custom function to handle console output.
1890 *
1891 * This allows external code to intercept and handle console.log, console.warn,
1892 * and console.error calls made by three.js, which is useful for custom logging,
1893 * testing, or debugging workflows.
1894 *
1895 * @param {Function} fn - The function to handle console output. Should accept
1896 *                        (type, message, ...params) where type is 'log', 'warn', or 'error'.
1897 */
1898function setConsoleFunction( fn ) {
1899
1900	_setConsoleFunction = fn;
1901
1902}
1903
1904/**
1905 * Gets the currently set custom console function.
1906 *
1907 * @return {Function|null} The custom console function, or null if not set.
1908 */
1909function getConsoleFunction() {
1910
1911	return _setConsoleFunction;
1912
1913}
1914
1915/**
1916 * Logs an informational message with the 'THREE.' prefix.
1917 *
1918 * If a custom console function is set via setConsoleFunction(), it will be used
1919 * instead of the native console.log. The first parameter is treated as the
1920 * method name and is automatically prefixed with 'THREE.'.
1921 *
1922 * @param {...any} params - The message components. The first param is used as
1923 *                          the method name and prefixed with 'THREE.'.
1924 */
1925function log( ...params ) {
1926
1927	const message = 'THREE.' + params.shift();
1928
1929	if ( _setConsoleFunction ) {
1930
1931		_setConsoleFunction( 'log', message, ...params );
1932
1933	} else {
1934
1935		console.log( message, ...params );
1936
1937	}
1938
1939}
1940
1941/**
1942 * Enhances log/warn/error messages related to TSL.
1943 *
1944 * @param {Array<any>} params - The original message parameters.
1945 * @returns {Array<any>} The filtered and enhanced message parameters.
1946 */
1947function enhanceLogMessage( params ) {
1948
1949	const message = params[ 0 ];
1950
1951	if ( typeof message === 'string' && message.startsWith( 'TSL:' ) ) {
1952
1953		const stackTrace = params[ 1 ];
1954
1955		if ( stackTrace && stackTrace.isStackTrace ) {
1956
1957			params[ 0 ] += ' ' + stackTrace.getLocation();
1958
1959		} else {
1960
1961			params[ 1 ] = 'Stack trace not available. Enable "THREE.Node.captureStackTrace" to capture stack traces.';
1962
1963		}
1964
1965	}
1966
1967	return params;
1968
1969}
1970
1971/**
1972 * Logs a warning message with the 'THREE.' prefix.
1973 *
1974 * If a custom console function is set via setConsoleFunction(), it will be used
1975 * instead of the native console.warn. The first parameter is treated as the
1976 * method name and is automatically prefixed with 'THREE.'.
1977 *
1978 * @param {...any} params - The message components. The first param is used as
1979 *                          the method name and prefixed with 'THREE.'.
1980 */
1981function warn( ...params ) {
1982
1983	params = enhanceLogMessage( params );
1984
1985	const message = 'THREE.' + params.shift();
1986
1987	if ( _setConsoleFunction ) {
1988
1989		_setConsoleFunction( 'warn', message, ...params );
1990
1991	} else {
1992
1993		const stackTrace = params[ 0 ];
1994
1995		if ( stackTrace && stackTrace.isStackTrace ) {
1996
1997			console.warn( stackTrace.getError( message ) );
1998
1999		} else {
2000
2001			console.warn( message, ...params );
2002
2003		}
2004
2005	}
2006
2007}
2008
2009/**
2010 * Logs an error message with the 'THREE.' prefix.
2011 *
2012 * If a custom console function is set via setConsoleFunction(), it will be used
2013 * instead of the native console.error. The first parameter is treated as the
2014 * method name and is automatically prefixed with 'THREE.'.
2015 *
2016 * @param {...any} params - The message components. The first param is used as
2017 *                          the method name and prefixed with 'THREE.'.
2018 */
2019function error( ...params ) {
2020
2021	params = enhanceLogMessage( params );
2022
2023	const message = 'THREE.' + params.shift();
2024
2025	if ( _setConsoleFunction ) {
2026
2027		_setConsoleFunction( 'error', message, ...params );
2028
2029	} else {
2030
2031		const stackTrace = params[ 0 ];
2032
2033		if ( stackTrace && stackTrace.isStackTrace ) {
2034
2035			console.error( stackTrace.getError( message ) );
2036
2037		} else {
2038
2039			console.error( message, ...params );
2040
2041		}
2042
2043	}
2044
2045}
2046
2047/**
2048 * Logs a warning message only once, preventing duplicate warnings.
2049 *
2050 * This function maintains an internal cache of warning messages and will only
2051 * output each unique warning message once. Useful for warnings that may be
2052 * triggered repeatedly but should only be shown to the user once.
2053 *
2054 * @param {...any} params - The warning message components.
2055 */
2056function warnOnce( ...params ) {
2057
2058	const message = params.join( ' ' );
2059
2060	if ( message in _cache ) return;
2061
2062	_cache[ message ] = true;
2063
2064	warn( ...params );
2065
2066}
2067
2068/**
2069 * Yields execution to the main thread to allow rendering and other tasks.
2070 * Uses scheduler.yield() when available (Chrome 115+), falls back to requestAnimationFrame.
2071 *
2072 * @return {Promise<void>}
2073 */
2074function yieldToMain() {
2075
2076	if ( typeof self !== 'undefined' && typeof self.scheduler !== 'undefined' && typeof self.scheduler.yield !== 'undefined' ) {
2077
2078		return self.scheduler.yield();
2079
2080	}
2081
2082	return new Promise( resolve => {
2083
2084		requestAnimationFrame( resolve );
2085
2086	} );
2087
2088}
2089
2090/**
2091 * Asynchronously probes for WebGL sync object completion.
2092 *
2093 * This function creates a promise that resolves when the WebGL sync object
2094 * signals completion or rejects if the sync operation fails. It uses polling
2095 * at the specified interval to check the sync status without blocking the
2096 * main thread. This is useful for GPU-CPU synchronization in WebGL contexts.
2097 *
2098 * @private
2099 * @param {WebGL2RenderingContext} gl - The WebGL rendering context.
2100 * @param {WebGLSync} sync - The WebGL sync object to wait for.
2101 * @param {number} interval - The polling interval in milliseconds.
2102 * @return {Promise<void>} A promise that resolves when the sync completes or rejects if it fails.
2103 */
2104function probeAsync( gl, sync, interval ) {
2105
2106	return new Promise( function ( resolve, reject ) {
2107
2108		function probe() {
2109
2110			switch ( gl.clientWaitSync( sync, gl.SYNC_FLUSH_COMMANDS_BIT, 0 ) ) {
2111
2112				case gl.WAIT_FAILED:
2113					reject();
2114					break;
2115
2116				case gl.TIMEOUT_EXPIRED:
2117					setTimeout( probe, interval );
2118					break;
2119
2120				default:
2121					resolve();
2122
2123			}
2124
2125		}
2126
2127		setTimeout( probe, interval );
2128
2129	} );
2130
2131}
2132
2133/**
2134 * Used to select the correct depth functions
2135 * when reversed depth buffer is used.
2136 *
2137 * @private
2138 * @type {Object}
2139 */
2140const ReversedDepthFuncs = {
2141	[ NeverDepth ]: AlwaysDepth,
2142	[ LessDepth ]: GreaterDepth,
2143	[ EqualDepth ]: NotEqualDepth,
2144	[ LessEqualDepth ]: GreaterEqualDepth,
2145
2146	[ AlwaysDepth ]: NeverDepth,
2147	[ GreaterDepth ]: LessDepth,
2148	[ NotEqualDepth ]: EqualDepth,
2149	[ GreaterEqualDepth ]: LessEqualDepth,
2150};
2151
2152/**
2153 * This modules allows to dispatch event objects on custom JavaScript objects.
2154 *
2155 * Main repository: [eventdispatcher.js](https://github.com/mrdoob/eventdispatcher.js/)
2156 *
2157 * Code Example:
2158 * ```js
2159 * class Car extends EventDispatcher {
2160 * 	start() {
2161 *		this.dispatchEvent( { type: 'start', message: 'vroom vroom!' } );
2162 *	}
2163 *};
2164 *
2165 * // Using events with the custom object
2166 * const car = new Car();
2167 * car.addEventListener( 'start', function ( event ) {
2168 * 	alert( event.message );
2169 * } );
2170 *
2171 * car.start();
2172 * ```
2173 */
2174class EventDispatcher {
2175
2176	/**
2177	 * Adds the given event listener to the given event type.
2178	 *
2179	 * @param {string} type - The type of event to listen to.
2180	 * @param {Function} listener - The function that gets called when the event is fired.
2181	 */
2182	addEventListener( type, listener ) {
2183
2184		if ( this._listeners === undefined ) this._listeners = {};
2185
2186		const listeners = this._listeners;
2187
2188		if ( listeners[ type ] === undefined ) {
2189
2190			listeners[ type ] = [];
2191
2192		}
2193
2194		if ( listeners[ type ].indexOf( listener ) === -1 ) {
2195
2196			listeners[ type ].push( listener );
2197
2198		}
2199
2200	}
2201
2202	/**
2203	 * Returns `true` if the given event listener has been added to the given event type.
2204	 *
2205	 * @param {string} type - The type of event.
2206	 * @param {Function} listener - The listener to check.
2207	 * @return {boolean} Whether the given event listener has been added to the given event type.
2208	 */
2209	hasEventListener( type, listener ) {
2210
2211		const listeners = this._listeners;
2212
2213		if ( listeners === undefined ) return false;
2214
2215		return listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== -1;
2216
2217	}
2218
2219	/**
2220	 * Removes the given event listener from the given event type.
2221	 *
2222	 * @param {string} type - The type of event.
2223	 * @param {Function} listener - The listener to remove.
2224	 */
2225	removeEventListener( type, listener ) {
2226
2227		const listeners = this._listeners;
2228
2229		if ( listeners === undefined ) return;
2230
2231		const listenerArray = listeners[ type ];
2232
2233		if ( listenerArray !== undefined ) {
2234
2235			const index = listenerArray.indexOf( listener );
2236
2237			if ( index !== -1 ) {
2238
2239				listenerArray.splice( index, 1 );
2240
2241			}
2242
2243		}
2244
2245	}
2246
2247	/**
2248	 * Dispatches an event object.
2249	 *
2250	 * @param {Object} event - The event that gets fired.
2251	 */
2252	dispatchEvent( event ) {
2253
2254		const listeners = this._listeners;
2255
2256		if ( listeners === undefined ) return;
2257
2258		const listenerArray = listeners[ event.type ];
2259
2260		if ( listenerArray !== undefined ) {
2261
2262			event.target = this;
2263
2264			// Make a copy, in case listeners are removed while iterating.
2265			const array = listenerArray.slice( 0 );
2266
2267			for ( let i = 0, l = array.length; i < l; i ++ ) {
2268
2269				array[ i ].call( this, event );
2270
2271			}
2272
2273			event.target = null;
2274
2275		}
2276
2277	}
2278
2279}
2280
2281const _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' ];
2282
2283let _seed = 1234567;
2284
2285
2286const DEG2RAD = Math.PI / 180;
2287const RAD2DEG = 180 / Math.PI;
2288
2289/**
2290 * Generate a [UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier)
2291 * (universally unique identifier).
2292 *
2293 * @return {string} The UUID.
2294 */
2295function generateUUID() {
2296
2297	// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136
2298
2299	const d0 = Math.random() * 0xffffffff | 0;
2300	const d1 = Math.random() * 0xffffffff | 0;
2301	const d2 = Math.random() * 0xffffffff | 0;
2302	const d3 = Math.random() * 0xffffffff | 0;
2303	const uuid = _lut[ d0 & 0xff ] + _lut[ d0 >> 8 & 0xff ] + _lut[ d0 >> 16 & 0xff ] + _lut[ d0 >> 24 & 0xff ] + '-' +
2304			_lut[ d1 & 0xff ] + _lut[ d1 >> 8 & 0xff ] + '-' + _lut[ d1 >> 16 & 0x0f | 0x40 ] + _lut[ d1 >> 24 & 0xff ] + '-' +
2305			_lut[ d2 & 0x3f | 0x80 ] + _lut[ d2 >> 8 & 0xff ] + '-' + _lut[ d2 >> 16 & 0xff ] + _lut[ d2 >> 24 & 0xff ] +
2306			_lut[ d3 & 0xff ] + _lut[ d3 >> 8 & 0xff ] + _lut[ d3 >> 16 & 0xff ] + _lut[ d3 >> 24 & 0xff ];
2307
2308	// .toLowerCase() here flattens concatenated strings to save heap memory space.
2309	return uuid.toLowerCase();
2310
2311}
2312
2313/**
2314 * Clamps the given value between min and max.
2315 *
2316 * @param {number} value - The value to clamp.
2317 * @param {number} min - The min value.
2318 * @param {number} max - The max value.
2319 * @return {number} The clamped value.
2320 */
2321function clamp( value, min, max ) {
2322
2323	return Math.max( min, Math.min( max, value ) );
2324
2325}
2326
2327/**
2328 * Computes the Euclidean modulo of the given parameters that
2329 * is `( ( n % m ) + m ) % m`.
2330 *
2331 * @param {number} n - The first parameter.
2332 * @param {number} m - The second parameter.
2333 * @return {number} The Euclidean modulo.
2334 */
2335function euclideanModulo( n, m ) {
2336
2337	// https://en.wikipedia.org/wiki/Modulo_operation
2338
2339	return ( ( n % m ) + m ) % m;
2340
2341}
2342
2343/**
2344 * Performs a linear mapping from range `<a1, a2>` to range `<b1, b2>`
2345 * for the given value. `a2` must be greater than `a1`.
2346 *
2347 * @param {number} x - The value to be mapped.
2348 * @param {number} a1 - Minimum value for range A.
2349 * @param {number} a2 - Maximum value for range A.
2350 * @param {number} b1 - Minimum value for range B.
2351 * @param {number} b2 - Maximum value for range B.
2352 * @return {number} The mapped value.
2353 */
2354function mapLinear( x, a1, a2, b1, b2 ) {
2355
2356	return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 );
2357
2358}
2359
2360/**
2361 * Returns the percentage in the closed interval `[0, 1]` of the given value
2362 * between the start and end point.
2363 *
2364 * @param {number} x - The start point
2365 * @param {number} y - The end point.
2366 * @param {number} value - A value between start and end.
2367 * @return {number} The interpolation factor.
2368 */
2369function inverseLerp( x, y, value ) {
2370
2371	// https://www.gamedev.net/tutorials/programming/general-and-gameplay-programming/inverse-lerp-a-super-useful-yet-often-overlooked-function-r5230/
2372
2373	if ( x !== y ) {
2374
2375		return ( value - x ) / ( y - x );
2376
2377	} else {
2378
2379		return 0;
2380
2381	}
2382
2383}
2384
2385/**
2386 * Returns a value linearly interpolated from two known points based on the given interval -
2387 * `t = 0` will return `x` and `t = 1` will return `y`.
2388 *
2389 * @param {number} x - The start point
2390 * @param {number} y - The end point.
2391 * @param {number} t - The interpolation factor in the closed interval `[0, 1]`.
2392 * @return {number} The interpolated value.
2393 */
2394function lerp( x, y, t ) {
2395
2396	return ( 1 - t ) * x + t * y;
2397
2398}
2399
2400/**
2401 * Smoothly interpolate a number from `x` to `y` in  a spring-like manner using a delta
2402 * time to maintain frame rate independent movement. For details, see
2403 * [Frame rate independent damping using lerp](http://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/).
2404 *
2405 * @param {number} x - The current point.
2406 * @param {number} y - The target point.
2407 * @param {number} lambda - A higher lambda value will make the movement more sudden,
2408 * and a lower value will make the movement more gradual.
2409 * @param {number} dt - Delta time in seconds.
2410 * @return {number} The interpolated value.
2411 */
2412function damp( x, y, lambda, dt ) {
2413
2414	return lerp( x, y, 1 - Math.exp( - lambda * dt ) );
2415
2416}
2417
2418/**
2419 * Returns a value that alternates between `0` and the given `length` parameter.
2420 *
2421 * @param {number} x - The value to pingpong.
2422 * @param {number} [length=1] - The positive value the function will pingpong to.
2423 * @return {number} The alternated value.
2424 */
2425function pingpong( x, length = 1 ) {
2426
2427	// https://www.desmos.com/calculator/vcsjnyz7x4
2428
2429	return length - Math.abs( euclideanModulo( x, length * 2 ) - length );
2430
2431}
2432
2433/**
2434 * Returns a value in the range `[0,1]` that represents the percentage that `x` has
2435 * moved between `min` and `max`, but smoothed or slowed down the closer `x` is to
2436 * the `min` and `max`.
2437 *
2438 * See [Smoothstep](http://en.wikipedia.org/wiki/Smoothstep) for more details.
2439 *
2440 * @param {number} x - The value to evaluate based on its position between `min` and `max`.
2441 * @param {number} min - The min value. Any `x` value below `min` will be `0`. `min` must be lower than `max`.
2442 * @param {number} max - The max value. Any `x` value above `max` will be `1`. `max` must be greater than `min`.
2443 * @return {number} The alternated value.
2444 */
2445function smoothstep( x, min, max ) {
2446
2447	if ( x <= min ) return 0;
2448	if ( x >= max ) return 1;
2449
2450	x = ( x - min ) / ( max - min );
2451
2452	return x * x * ( 3 - 2 * x );
2453
2454}
2455
2456/**
2457 * A [variation on smoothstep](https://en.wikipedia.org/wiki/Smoothstep#Variations)
2458 * that has zero 1st and 2nd order derivatives at `x=0` and `x=1`.
2459 *
2460 * @param {number} x - The value to evaluate based on its position between `min` and `max`.
2461 * @param {number} min - The min value. Any `x` value below `min` will be `0`. `min` must be lower than `max`.
2462 * @param {number} max - The max value. Any `x` value above `max` will be `1`. `max` must be greater than `min`.
2463 * @return {number} The alternated value.
2464 */
2465function smootherstep( x, min, max ) {
2466
2467	if ( x <= min ) return 0;
2468	if ( x >= max ) return 1;
2469
2470	x = ( x - min ) / ( max - min );
2471
2472	return x * x * x * ( x * ( x * 6 - 15 ) + 10 );
2473
2474}
2475
2476/**
2477 * Returns a random integer from `<low, high>` interval.
2478 *
2479 * @param {number} low - The lower value boundary.
2480 * @param {number} high - The upper value boundary
2481 * @return {number} A random integer.
2482 */
2483function randInt( low, high ) {
2484
2485	return low + Math.floor( Math.random() * ( high - low + 1 ) );
2486
2487}
2488
2489/**
2490 * Returns a random float from `<low, high>` interval.
2491 *
2492 * @param {number} low - The lower value boundary.
2493 * @param {number} high - The upper value boundary
2494 * @return {number} A random float.
2495 */
2496function randFloat( low, high ) {
2497
2498	return low + Math.random() * ( high - low );
2499
2500}
2501
2502/**
2503 * Returns a random integer from `<-range/2, range/2>` interval.
2504 *
2505 * @param {number} range - Defines the value range.
2506 * @return {number} A random float.
2507 */
2508function randFloatSpread( range ) {
2509
2510	return range * ( 0.5 - Math.random() );
2511
2512}
2513
2514/**
2515 * Returns a deterministic pseudo-random float in the interval `[0, 1]`.
2516 *
2517 * @param {number} [s] - The integer seed.
2518 * @return {number} A random float.
2519 */
2520function seededRandom( s ) {
2521
2522	if ( s !== undefined ) _seed = s;
2523
2524	// Mulberry32 generator
2525
2526	let t = _seed += 0x6D2B79F5;
2527
2528	t = Math.imul( t ^ t >>> 15, t | 1 );
2529
2530	t ^= t + Math.imul( t ^ t >>> 7, t | 61 );
2531
2532	return ( ( t ^ t >>> 14 ) >>> 0 ) / 4294967296;
2533
2534}
2535
2536/**
2537 * Converts degrees to radians.
2538 *
2539 * @param {number} degrees - A value in degrees.
2540 * @return {number} The converted value in radians.
2541 */
2542function degToRad( degrees ) {
2543
2544	return degrees * DEG2RAD;
2545
2546}
2547
2548/**
2549 * Converts radians to degrees.
2550 *
2551 * @param {number} radians - A value in radians.
2552 * @return {number} The converted value in degrees.
2553 */
2554function radToDeg( radians ) {
2555
2556	return radians * RAD2DEG;
2557
2558}
2559
2560/**
2561 * Returns `true` if the given 
2561number is a power of two.
2562 *
2563 * @param {number} value - The value to check.
2564 * @return {boolean} Whether the given number is a power of two or not.
2565 */
2566function isPowerOfTwo( value ) {
2567
2568	return ( value & ( value - 1 ) ) === 0 && value !== 0;
2569
2570}
2571
2572/**
2573 * Returns the smallest power of two that is greater than or equal to the given number.
2574 *
2575 * @param {number} value - The value to find a POT for. Must be greater than `0`.
2576 * @return {number} The smallest power of two that is greater than or equal to the given number.
2577 */
2578function ceilPowerOfTwo( value ) {
2579
2580	return Math.pow( 2, Math.ceil( Math.log( value ) / Math.LN2 ) );
2581
2582}
2583
2584/**
2585 * Returns the largest power of two that is less than or equal to the given number.
2586 *
2587 * @param {number} value - The value to find a POT for. Must be greater than `0`.
2588 * @return {number} The largest power of two that is less than or equal to the given number.
2589 */
2590function floorPowerOfTwo( value ) {
2591
2592	return Math.pow( 2, Math.floor( Math.log( value ) / Math.LN2 ) );
2593
2594}
2595
2596/**
2597 * Sets the given quaternion from the [Intrinsic Proper Euler Angles](https://en.wikipedia.org/wiki/Euler_angles)
2598 * defined by the given angles and order.
2599 *
2600 * Rotations are applied to the axes in the order specified by order:
2601 * rotation by angle `a` is applied first, then by angle `b`, then by angle `c`.
2602 *
2603 * @param {Quaternion} q - The quaternion to set.
2604 * @param {number} a - The rotation applied to the first axis, in radians.
2605 * @param {number} b - The rotation applied to the second axis, in radians.
2606 * @param {number} c - The rotation applied to the third axis, in radians.
2607 * @param {('XYX'|'XZX'|'YXY'|'YZY'|'ZXZ'|'ZYZ')} order - A string specifying the axes order.
2608 */
2609function setQuaternionFromProperEuler( q, a, b, c, order ) {
2610
2611	const cos = Math.cos;
2612	const sin = Math.sin;
2613
2614	const c2 = cos( b / 2 );
2615	const s2 = sin( b / 2 );
2616
2617	const c13 = cos( ( a + c ) / 2 );
2618	const s13 = sin( ( a + c ) / 2 );
2619
2620	const c1_3 = cos( ( a - c ) / 2 );
2621	const s1_3 = sin( ( a - c ) / 2 );
2622
2623	const c3_1 = cos( ( c - a ) / 2 );
2624	const s3_1 = sin( ( c - a ) / 2 );
2625
2626	switch ( order ) {
2627
2628		case 'XYX':
2629			q.set( c2 * s13, s2 * c1_3, s2 * s1_3, c2 * c13 );
2630			break;
2631
2632		case 'YZY':
2633			q.set( s2 * s1_3, c2 * s13, s2 * c1_3, c2 * c13 );
2634			break;
2635
2636		case 'ZXZ':
2637			q.set( s2 * c1_3, s2 * s1_3, c2 * s13, c2 * c13 );
2638			break;
2639
2640		case 'XZX':
2641			q.set( c2 * s13, s2 * s3_1, s2 * c3_1, c2 * c13 );
2642			break;
2643
2644		case 'YXY':
2645			q.set( s2 * c3_1, c2 * s13, s2 * s3_1, c2 * c13 );
2646			break;
2647
2648		case 'ZYZ':
2649			q.set( s2 * s3_1, s2 * c3_1, c2 * s13, c2 * c13 );
2650			break;
2651
2652		default:
2653			warn( 'MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: ' + order );
2654
2655	}
2656
2657}
2658
2659/**
2660 * Denormalizes the given value according to the given typed array.
2661 *
2662 * @param {number} value - The value to denormalize.
2663 * @param {TypedArray} array - The typed array that defines the data type of the value.
2664 * @return {number} The denormalize (float) value in the range `[0,1]`.
2665 */
2666function denormalize( value, array ) {
2667
2668	switch ( array.constructor ) {
2669
2670		case Float32Array:
2671
2672			return value;
2673
2674		case Uint32Array:
2675
2676			return value / 4294967295.0;
2677
2678		case Uint16Array:
2679
2680			return value / 65535.0;
2681
2682		case Uint8Array:
2683
2684			return value / 255.0;
2685
2686		case Int32Array:
2687
2688			return Math.max( value / 2147483647.0, -1 );
2689
2690		case Int16Array:
2691
2692			return Math.max( value / 32767.0, -1 );
2693
2694		case Int8Array:
2695
2696			return Math.max( value / 127.0, -1 );
2697
2698		default:
2699
2700			throw new Error( 'Invalid component type.' );
2701
2702	}
2703
2704}
2705
2706/**
2707 * Normalizes the given value according to the given typed array.
2708 *
2709 * @param {number} value - The float value in the range `[0,1]` to normalize.
2710 * @param {TypedArray} array - The typed array that defines the data type of the value.
2711 * @return {number} The normalize value.
2712 */
2713function normalize( value, array ) {
2714
2715	switch ( array.constructor ) {
2716
2717		case Float32Array:
2718
2719			return value;
2720
2721		case Uint32Array:
2722
2723			return Math.round( value * 4294967295.0 );
2724
2725		case Uint16Array:
2726
2727			return Math.round( value * 65535.0 );
2728
2729		case Uint8Array:
2730
2731			return Math.round( value * 255.0 );
2732
2733		case Int32Array:
2734
2735			return Math.round( value * 2147483647.0 );
2736
2737		case Int16Array:
2738
2739			return Math.round( value * 32767.0 );
2740
2741		case Int8Array:
2742
2743			return Math.round( value * 127.0 );
2744
2745		default:
2746
2747			throw new Error( 'Invalid component type.' );
2748
2749	}
2750
2751}
2752
2753/**
2754 * @class
2755 * @classdesc A collection of math utility functions.
2756 * @hideconstructor
2757 */
2758const MathUtils = {
2759	DEG2RAD: DEG2RAD,
2760	RAD2DEG: RAD2DEG,
2761	/**
2762	 * Generate a [UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier)
2763	 * (universally unique identifier).
2764	 *
2765	 * @static
2766	 * @method
2767	 * @return {string} The UUID.
2768	 */
2769	generateUUID: generateUUID,
2770	/**
2771	 * Clamps the given value between min and max.
2772	 *
2773	 * @static
2774	 * @method
2775	 * @param {number} value - The value to clamp.
2776	 * @param {number} min - The min value.
2777	 * @param {number} max - The max value.
2778	 * @return {number} The clamped value.
2779	 */
2780	clamp: clamp,
2781	/**
2782	 * Computes the Euclidean modulo of the given parameters that
2783	 * is `( ( n % m ) + m ) % m`.
2784	 *
2785	 * @static
2786	 * @method
2787	 * @param {number} n - The first parameter.
2788	 * @param {number} m - The second parameter.
2789	 * @return {number} The Euclidean modulo.
2790	 */
2791	euclideanModulo: euclideanModulo,
2792	/**
2793	 * Performs a linear mapping from range `<a1, a2>` to range `<b1, b2>`
2794	 * for the given value.
2795	 *
2796	 * @static
2797	 * @method
2798	 * @param {number} x - The value to be mapped.
2799	 * @param {number} a1 - Minimum value for range A.
2800	 * @param {number} a2 - Maximum value for range A.
2801	 * @param {number} b1 - Minimum value for range B.
2802	 * @param {number} b2 - Maximum value for range B.
2803	 * @return {number} The mapped value.
2804	 */
2805	mapLinear: mapLinear,
2806	/**
2807	 * Returns the percentage in the closed interval `[0, 1]` of the given value
2808	 * between the start and end point.
2809	 *
2810	 * @static
2811	 * @method
2812	 * @param {number} x - The start point
2813	 * @param {number} y - The end point.
2814	 * @param {number} value - A value between start and end.
2815	 * @return {number} The interpolation factor.
2816	 */
2817	inverseLerp: inverseLerp,
2818	/**
2819	 * Returns a value linearly interpolated from two known points based on the given interval -
2820	 * `t = 0` will return `x` and `t = 1` will return `y`.
2821	 *
2822	 * @static
2823	 * @method
2824	 * @param {number} x - The start point
2825	 * @param {number} y - The end point.
2826	 * @param {number} t - The interpolation factor in the closed interval `[0, 1]`.
2827	 * @return {number} The interpolated value.
2828	 */
2829	lerp: lerp,
2830	/**
2831	 * Smoothly interpolate a number from `x` to `y` in  a spring-like manner using a delta
2832	 * time to maintain frame rate independent movement. For details, see
2833	 * [Frame rate independent damping using lerp](http://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/).
2834	 *
2835	 * @static
2836	 * @method
2837	 * @param {number} x - The current point.
2838	 * @param {number} y - The target point.
2839	 * @param {number} lambda - A higher lambda value will make the movement more sudden,
2840	 * and a lower value will make the movement more gradual.
2841	 * @param {number} dt - Delta time in seconds.
2842	 * @return {number} The interpolated value.
2843	 */
2844	damp: damp,
2845	/**
2846	 * Returns a value that alternates between `0` and the given `length` parameter.
2847	 *
2848	 * @static
2849	 * @method
2850	 * @param {number} x - The value to pingpong.
2851	 * @param {number} [length=1] - The positive value the function will pingpong to.
2852	 * @return {number} The alternated value.
2853	 */
2854	pingpong: pingpong,
2855	/**
2856	 * Returns a value in the range `[0,1]` that represents the percentage that `x` has
2857	 * moved between `min` and `max`, but smoothed or slowed down the closer `x` is to
2858	 * the `min` and `max`.
2859	 *
2860	 * See [Smoothstep](http://en.wikipedia.org/wiki/Smoothstep) for more details.
2861	 *
2862	 * @static
2863	 * @method
2864	 * @param {number} x - The value to evaluate based on its position between min and max.
2865	 * @param {number} min - The min value. Any x value below min will be `0`.
2866	 * @param {number} max - The max value. Any x value above max will be `1`.
2867	 * @return {number} The alternated value.
2868	 */
2869	smoothstep: smoothstep,
2870	/**
2871	 * A [variation on smoothstep](https://en.wikipedia.org/wiki/Smoothstep#Variations)
2872	 * that has zero 1st and 2nd order derivatives at x=0 and x=1.
2873	 *
2874	 * @static
2875	 * @method
2876	 * @param {number} x - The value to evaluate based on its position between min and max.
2877	 * @param {number} min - The min value. Any x value below min will be `0`.
2878	 * @param {number} max - The max value. Any x value above max will be `1`.
2879	 * @return {number} The alternated value.
2880	 */
2881	smootherstep: smootherstep,
2882	/**
2883	 * Returns a random integer from `<low, high>` interval.
2884	 *
2885	 * @static
2886	 * @method
2887	 * @param {number} low - The lower value boundary.
2888	 * @param {number} high - The upper value boundary
2889	 * @return {number} A random integer.
2890	 */
2891	randInt: randInt,
2892	/**
2893	 * Returns a random float from `<low, high>` interval.
2894	 *
2895	 * @static
2896	 * @method
2897	 * @param {number} low - The lower value boundary.
2898	 * @param {number} high - The upper value boundary
2899	 * @return {number} A random float.
2900	 */
2901	randFloat: randFloat,
2902	/**
2903	 * Returns a random integer from `<-range/2, range/2>` interval.
2904	 *
2905	 * @static
2906	 * @method
2907	 * @param {number} range - Defines the value range.
2908	 * @return {number} A random float.
2909	 */
2910	randFloatSpread: randFloatSpread,
2911	/**
2912	 * Returns a deterministic pseudo-random float in the interval `[0, 1]`.
2913	 *
2914	 * @static
2915	 * @method
2916	 * @param {number} [s] - The integer seed.
2917	 * @return {number} A random float.
2918	 */
2919	seededRandom: seededRandom,
2920	/**
2921	 * Converts degrees to radians.
2922	 *
2923	 * @static
2924	 * @method
2925	 * @param {number} degrees - A value in degrees.
2926	 * @return {number} The converted value in radians.
2927	 */
2928	degToRad: degToRad,
2929	/**
2930	 * Converts radians to degrees.
2931	 *
2932	 * @static
2933	 * @method
2934	 * @param {number} radians - A value in radians.
2935	 * @return {number} The converted value in degrees.
2936	 */
2937	radToDeg: radToDeg,
2938	/**
2939	 * Returns `true` if the given number is a power of two.
2940	 *
2941	 * @static
2942	 * @method
2943	 * @param {number} value - The value to check.
2944	 * @return {boolean} Whether the given number is a power of two or not.
2945	 */
2946	isPowerOfTwo: isPowerOfTwo,
2947	/**
2948	 * Returns the smallest power of two that is greater than or equal to the given number.
2949	 *
2950	 * @static
2951	 * @method
2952	 * @param {number} value - The value to find a POT for.
2953	 * @return {number} The smallest power of two that is greater than or equal to the given number.
2954	 */
2955	ceilPowerOfTwo: ceilPowerOfTwo,
2956	/**
2957	 * Returns the largest power of two that is less than or equal to the given number.
2958	 *
2959	 * @static
2960	 * @method
2961	 * @param {number} value - The value to find a POT for.
2962	 * @return {number} The largest power of two that is less than or equal to the given number.
2963	 */
2964	floorPowerOfTwo: floorPowerOfTwo,
2965	/**
2966	 * Sets the given quaternion from the [Intrinsic Proper Euler Angles](https://en.wikipedia.org/wiki/Euler_angles)
2967	 * defined by the given angles and order.
2968	 *
2969	 * Rotations are applied to the axes in the order specified by order:
2970	 * rotation by angle `a` is applied first, then by angle `b`, then by angle `c`.
2971	 *
2972	 * @static
2973	 * @method
2974	 * @param {Quaternion} q - The quaternion to set.
2975	 * @param {number} a - The rotation applied to the first axis, in radians.
2976	 * @param {number} b - The rotation applied to the second axis, in radians.
2977	 * @param {number} c - The rotation applied to the third axis, in radians.
2978	 * @param {('XYX'|'XZX'|'YXY'|'YZY'|'ZXZ'|'ZYZ')} order - A string specifying the axes order.
2979	 */
2980	setQuaternionFromProperEuler: setQuaternionFromProperEuler,
2981	/**
2982	 * Normalizes the given value according to the given typed array.
2983	 *
2984	 * @static
2985	 * @method
2986	 * @param {number} value - The float value in the range `[0,1]` to normalize.
2987	 * @param {TypedArray} array - The typed array that defines the data type of the value.
2988	 * @return {number} The normalize value.
2989	 */
2990	normalize: normalize,
2991	/**
2992	 * Denormalizes the given value according to the given typed array.
2993	 *
2994	 * @static
2995	 * @method
2996	 * @param {number} value - The value to denormalize.
2997	 * @param {TypedArray} array - The typed array that defines the data type of the value.
2998	 * @return {number} The denormalize (float) value in the range `[0,1]`.
2999	 */
3000	denormalize: denormalize
3001};
3002
3003/**
3004 * Class representing a 2D vector. A 2D vector is an ordered pair of numbers
3005 * (labeled x and y), which can be used to represent a number of things, such as:
3006 *
3007 * - A point in 2D space (i.e. a position on a plane).
3008 * - A direction and length across a plane. In three.js the length will
3009 * always be the Euclidean distance(straight-line distance) from `(0, 0)` to `(x, y)`
3010 * and the direction is also measured from `(0, 0)` towards `(x, y)`.
3011 * - Any arbitrary ordered pair of numbers.
3012 *
3013 * There are other things a 2D vector can be used to represent, such as
3014 * momentum vectors, complex numbers and so on, however these are the most
3015 * common uses in three.js.
3016 *
3017 * Iterating through a vector instance will yield its components `(x, y)` in
3018 * the corresponding order.
3019 * ```js
3020 * const a = new THREE.Vector2( 0, 1 );
3021 *
3022 * //no arguments; will be initialised to (0, 0)
3023 * const b = new THREE.Vector2( );
3024 *
3025 * const d = a.distanceTo( b );
3026 * ```
3027 */
3028class Vector2 {
3029
3030	static {
3031
3032		/**
3033		 * This flag can be used for type testing.
3034		 *
3035		 * @type {boolean}
3036		 * @readonly
3037		 * @default true
3038		 */
3039		Vector2.prototype.isVector2 = true;
3040
3041	}
3042
3043	/**
3044	 * Constructs a new 2D vector.
3045	 *
3046	 * @param {number} [x=0] - The x value of this vector.
3047	 * @param {number} [y=0] - The y value of this vector.
3048	 */
3049	constructor( x = 0, y = 0 ) {
3050
3051		/**
3052		 * The x value of this vector.
3053		 *
3054		 * @type {number}
3055		 */
3056		this.x = x;
3057
3058		/**
3059		 * The y value of this vector.
3060		 *
3061		 * @type {number}
3062		 */
3063		this.y = y;
3064
3065	}
3066
3067	/**
3068	 * Alias for {@link Vector2#x}.
3069	 *
3070	 * @type {number}
3071	 */
3072	get width() {
3073
3074		return this.x;
3075
3076	}
3077
3078	set width( value ) {
3079
3080		this.x = value;
3081
3082	}
3083
3084	/**
3085	 * Alias for {@link Vector2#y}.
3086	 *
3087	 * @type {number}
3088	 */
3089	get height() {
3090
3091		return this.y;
3092
3093	}
3094
3095	set height( value ) {
3096
3097		this.y = value;
3098
3099	}
3100
3101	/**
3102	 * Sets the vector components.
3103	 *
3104	 * @param {number} x - The value of the x component.
3105	 * @param {number} y - The value of the y component.
3106	 * @return {Vector2} A reference to this vector.
3107	 */
3108	set( x, y ) {
3109
3110		this.x = x;
3111		this.y = y;
3112
3113		return this;
3114
3115	}
3116
3117	/**
3118	 * Sets the vector components to the same value.
3119	 *
3120	 * @param {number} scalar - The value to set for all vector components.
3121	 * @return {Vector2} A reference to this vector.
3122	 */
3123	setScalar( scalar ) {
3124
3125		this.x = scalar;
3126		this.y = scalar;
3127
3128		return this;
3129
3130	}
3131
3132	/**
3133	 * Sets the vector's x component to the given value
3134	 *
3135	 * @param {number} x - The value to set.
3136	 * @return {Vector2} A reference to this vector.
3137	 */
3138	setX( x ) {
3139
3140		this.x = x;
3141
3142		return this;
3143
3144	}
3145
3146	/**
3147	 * Sets the vector's y component to the given value
3148	 *
3149	 * @param {number} y - The value to set.
3150	 * @return {Vector2} A reference to this vector.
3151	 */
3152	setY( y ) {
3153
3154		this.y = y;
3155
3156		return this;
3157
3158	}
3159
3160	/**
3161	 * Allows to set a vector component with an index.
3162	 *
3163	 * @param {number} index - The component index. `0` equals to x, `1` equals to y.
3164	 * @param {number} value - The value to set.
3165	 * @return {Vector2} A reference to this vector.
3166	 */
3167	setComponent( index, value ) {
3168
3169		switch ( index ) {
3170
3171			case 0: this.x = value; break;
3172			case 1: this.y = value; break;
3173			default: throw new Error( 'index is out of range: ' + index );
3174
3175		}
3176
3177		return this;
3178
3179	}
3180
3181	/**
3182	 * Returns the value of the vector component which matches the given index.
3183	 *
3184	 * @param {number} index - The component index. `0` equals to x, `1` equals to y.
3185	 * @return {number} A vector component value.
3186	 */
3187	getComponent( index ) {
3188
3189		switch ( index ) {
3190
3191			case 0: return this.x;
3192			case 1: return this.y;
3193			default: throw new Error( '
vendor: 17,739 bytes, lines 3193-3996
3193index is out of range: ' + index );
3194
3195		}
3196
3197	}
3198
3199	/**
3200	 * Returns a new vector with copied values from this instance.
3201	 *
3202	 * @return {Vector2} A clone of this instance.
3203	 */
3204	clone() {
3205
3206		return new this.constructor( this.x, this.y );
3207
3208	}
3209
3210	/**
3211	 * Copies the values of the given vector to this instance.
3212	 *
3213	 * @param {Vector2} v - The vector to copy.
3214	 * @return {Vector2} A reference to this vector.
3215	 */
3216	copy( v ) {
3217
3218		this.x = v.x;
3219		this.y = v.y;
3220
3221		return this;
3222
3223	}
3224
3225	/**
3226	 * Adds the given vector to this instance.
3227	 *
3228	 * @param {Vector2} v - The vector to add.
3229	 * @return {Vector2} A reference to this vector.
3230	 */
3231	add( v ) {
3232
3233		this.x += v.x;
3234		this.y += v.y;
3235
3236		return this;
3237
3238	}
3239
3240	/**
3241	 * Adds the given scalar value to all components of this instance.
3242	 *
3243	 * @param {number} s - The scalar to add.
3244	 * @return {Vector2} A reference to this vector.
3245	 */
3246	addScalar( s ) {
3247
3248		this.x += s;
3249		this.y += s;
3250
3251		return this;
3252
3253	}
3254
3255	/**
3256	 * Adds the given vectors and stores the result in this instance.
3257	 *
3258	 * @param {Vector2} a - The first vector.
3259	 * @param {Vector2} b - The second vector.
3260	 * @return {Vector2} A reference to this vector.
3261	 */
3262	addVectors( a, b ) {
3263
3264		this.x = a.x + b.x;
3265		this.y = a.y + b.y;
3266
3267		return this;
3268
3269	}
3270
3271	/**
3272	 * Adds the given vector scaled by the given factor to this instance.
3273	 *
3274	 * @param {Vector2} v - The vector.
3275	 * @param {number} s - The factor that scales `v`.
3276	 * @return {Vector2} A reference to this vector.
3277	 */
3278	addScaledVector( v, s ) {
3279
3280		this.x += v.x * s;
3281		this.y += v.y * s;
3282
3283		return this;
3284
3285	}
3286
3287	/**
3288	 * Subtracts the given vector from this instance.
3289	 *
3290	 * @param {Vector2} v - The vector to subtract.
3291	 * @return {Vector2} A reference to this vector.
3292	 */
3293	sub( v ) {
3294
3295		this.x -= v.x;
3296		this.y -= v.y;
3297
3298		return this;
3299
3300	}
3301
3302	/**
3303	 * Subtracts the given scalar value from all components of this instance.
3304	 *
3305	 * @param {number} s - The scalar to subtract.
3306	 * @return {Vector2} A reference to this vector.
3307	 */
3308	subScalar( s ) {
3309
3310		this.x -= s;
3311		this.y -= s;
3312
3313		return this;
3314
3315	}
3316
3317	/**
3318	 * Subtracts the given vectors and stores the result in this instance.
3319	 *
3320	 * @param {Vector2} a - The first vector.
3321	 * @param {Vector2} b - The second vector.
3322	 * @return {Vector2} A reference to this vector.
3323	 */
3324	subVectors( a, b ) {
3325
3326		this.x = a.x - b.x;
3327		this.y = a.y - b.y;
3328
3329		return this;
3330
3331	}
3332
3333	/**
3334	 * Multiplies the given vector with this instance.
3335	 *
3336	 * @param {Vector2} v - The vector to multiply.
3337	 * @return {Vector2} A reference to this vector.
3338	 */
3339	multiply( v ) {
3340
3341		this.x *= v.x;
3342		this.y *= v.y;
3343
3344		return this;
3345
3346	}
3347
3348	/**
3349	 * Multiplies the given scalar value with all components of this instance.
3350	 *
3351	 * @param {number} scalar - The scalar to multiply.
3352	 * @return {Vector2} A reference to this vector.
3353	 */
3354	multiplyScalar( scalar ) {
3355
3356		this.x *= scalar;
3357		this.y *= scalar;
3358
3359		return this;
3360
3361	}
3362
3363	/**
3364	 * Divides this instance by the given vector.
3365	 *
3366	 * @param {Vector2} v - The vector to divide.
3367	 * @return {Vector2} A reference to this vector.
3368	 */
3369	divide( v ) {
3370
3371		this.x /= v.x;
3372		this.y /= v.y;
3373
3374		return this;
3375
3376	}
3377
3378	/**
3379	 * Divides this vector by the given scalar.
3380	 *
3381	 * @param {number} scalar - The scalar to divide.
3382	 * @return {Vector2} A reference to this vector.
3383	 */
3384	divideScalar( scalar ) {
3385
3386		return this.multiplyScalar( 1 / scalar );
3387
3388	}
3389
3390	/**
3391	 * Multiplies this vector (with an implicit 1 as the 3rd component) by
3392	 * the given 3x3 matrix.
3393	 *
3394	 * @param {Matrix3} m - The matrix to apply.
3395	 * @return {Vector2} A reference to this vector.
3396	 */
3397	applyMatrix3( m ) {
3398
3399		const x = this.x, y = this.y;
3400		const e = m.elements;
3401
3402		this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ];
3403		this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ];
3404
3405		return this;
3406
3407	}
3408
3409	/**
3410	 * If this vector's x or y value is greater than the given vector's x or y
3411	 * value, replace that value with the corresponding min value.
3412	 *
3413	 * @param {Vector2} v - The vector.
3414	 * @return {Vector2} A reference to this vector.
3415	 */
3416	min( v ) {
3417
3418		this.x = Math.min( this.x, v.x );
3419		this.y = Math.min( this.y, v.y );
3420
3421		return this;
3422
3423	}
3424
3425	/**
3426	 * If this vector's x or y value is less than the given vector's x or y
3427	 * value, replace that value with the corresponding max value.
3428	 *
3429	 * @param {Vector2} v - The vector.
3430	 * @return {Vector2} A reference to this vector.
3431	 */
3432	max( v ) {
3433
3434		this.x = Math.max( this.x, v.x );
3435		this.y = Math.max( this.y, v.y );
3436
3437		return this;
3438
3439	}
3440
3441	/**
3442	 * If this vector's x or y value is greater than the max vector's x or y
3443	 * value, it is replaced by the corresponding value.
3444	 * If this vector's x or y value is less than the min vector's x or y value,
3445	 * it is replaced by the corresponding value.
3446	 *
3447	 * @param {Vector2} min - The minimum x and y values.
3448	 * @param {Vector2} max - The maximum x and y values in the desired range.
3449	 * @return {Vector2} A reference to this vector.
3450	 */
3451	clamp( min, max ) {
3452
3453		// assumes min < max, componentwise
3454
3455		this.x = clamp( this.x, min.x, max.x );
3456		this.y = clamp( this.y, min.y, max.y );
3457
3458		return this;
3459
3460	}
3461
3462	/**
3463	 * If this vector's x or y values are greater than the max value, they are
3464	 * replaced by the max value.
3465	 * If this vector's x or y values are less than the min value, they are
3466	 * replaced by the min value.
3467	 *
3468	 * @param {number} minVal - The minimum value the components will be clamped to.
3469	 * @param {number} maxVal - The maximum value the components will be clamped to.
3470	 * @return {Vector2} A reference to this vector.
3471	 */
3472	clampScalar( minVal, maxVal ) {
3473
3474		this.x = clamp( this.x, minVal, maxVal );
3475		this.y = clamp( this.y, minVal, maxVal );
3476
3477		return this;
3478
3479	}
3480
3481	/**
3482	 * If this vector's length is greater than the max value, it is replaced by
3483	 * the max value.
3484	 * If this vector's length is less than the min value, it is replaced by the
3485	 * min value.
3486	 *
3487	 * @param {number} min - The minimum value the vector length will be clamped to.
3488	 * @param {number} max - The maximum value the vector length will be clamped to.
3489	 * @return {Vector2} A reference to this vector.
3490	 */
3491	clampLength( min, max ) {
3492
3493		const length = this.length();
3494
3495		return this.divideScalar( length || 1 ).multiplyScalar( clamp( length, min, max ) );
3496
3497	}
3498
3499	/**
3500	 * The components of this vector are rounded down to the nearest integer value.
3501	 *
3502	 * @return {Vector2} A reference to this vector.
3503	 */
3504	floor() {
3505
3506		this.x = Math.floor( this.x );
3507		this.y = Math.floor( this.y );
3508
3509		return this;
3510
3511	}
3512
3513	/**
3514	 * The components of this vector are rounded up to the nearest integer value.
3515	 *
3516	 * @return {Vector2} A reference to this vector.
3517	 */
3518	ceil() {
3519
3520		this.x = Math.ceil( this.x );
3521		this.y = Math.ceil( this.y );
3522
3523		return this;
3524
3525	}
3526
3527	/**
3528	 * The components of this vector are rounded to the nearest integer value
3529	 *
3530	 * @return {Vector2} A reference to this vector.
3531	 */
3532	round() {
3533
3534		this.x = Math.round( this.x );
3535		this.y = Math.round( this.y );
3536
3537		return this;
3538
3539	}
3540
3541	/**
3542	 * The components of this vector are rounded towards zero (up if negative,
3543	 * down if positive) to an integer value.
3544	 *
3545	 * @return {Vector2} A reference to this vector.
3546	 */
3547	roundToZero() {
3548
3549		this.x = Math.trunc( this.x );
3550		this.y = Math.trunc( this.y );
3551
3552		return this;
3553
3554	}
3555
3556	/**
3557	 * Inverts this vector - i.e. sets x = -x and y = -y.
3558	 *
3559	 * @return {Vector2} A reference to this vector.
3560	 */
3561	negate() {
3562
3563		this.x = - this.x;
3564		this.y = - this.y;
3565
3566		return this;
3567
3568	}
3569
3570	/**
3571	 * Calculates the dot product of the given vector with this instance.
3572	 *
3573	 * @param {Vector2} v - The vector to compute the dot product with.
3574	 * @return {number} The result of the dot product.
3575	 */
3576	dot( v ) {
3577
3578		return this.x * v.x + this.y * v.y;
3579
3580	}
3581
3582	/**
3583	 * Calculates the cross product of the given vector with this instance.
3584	 *
3585	 * @param {Vector2} v - The vector to compute the cross product with.
3586	 * @return {number} The result of the cross product.
3587	 */
3588	cross( v ) {
3589
3590		return this.x * v.y - this.y * v.x;
3591
3592	}
3593
3594	/**
3595	 * Computes the square of the Euclidean length (straight-line length) from
3596	 * (0, 0) to (x, y). If you are comparing the lengths of vectors, you should
3597	 * compare the length squared instead as it is slightly more efficient to calculate.
3598	 *
3599	 * @return {number} The square length of this vector.
3600	 */
3601	lengthSq() {
3602
3603		return this.x * this.x + this.y * this.y;
3604
3605	}
3606
3607	/**
3608	 * Computes the  Euclidean length (straight-line length) from (0, 0) to (x, y).
3609	 *
3610	 * @return {number} The length of this vector.
3611	 */
3612	length() {
3613
3614		return Math.sqrt( this.x * this.x + this.y * this.y );
3615
3616	}
3617
3618	/**
3619	 * Computes the Manhattan length of this vector.
3620	 *
3621	 * @return {number} The length of this vector.
3622	 */
3623	manhattanLength() {
3624
3625		return Math.abs( this.x ) + Math.abs( this.y );
3626
3627	}
3628
3629	/**
3630	 * Converts this vector to a unit vector - that is, sets it equal to a vector
3631	 * with the same direction as this one, but with a vector length of `1`.
3632	 *
3633	 * @return {Vector2} A reference to this vector.
3634	 */
3635	normalize() {
3636
3637		return this.divideScalar( this.length() || 1 );
3638
3639	}
3640
3641	/**
3642	 * Computes the angle in radians of this vector with respect to the positive x-axis.
3643	 *
3644	 * @return {number} The angle in radians.
3645	 */
3646	angle() {
3647
3648		const angle = Math.atan2( - this.y, - this.x ) + Math.PI;
3649
3650		return angle;
3651
3652	}
3653
3654	/**
3655	 * Returns the angle between the given vector and this instance in radians.
3656	 *
3657	 * @param {Vector2} v - The vector to compute the angle with.
3658	 * @return {number} The angle in radians.
3659	 */
3660	angleTo( v ) {
3661
3662		const denominator = Math.sqrt( this.lengthSq() * v.lengthSq() );
3663
3664		if ( denominator === 0 ) return Math.PI / 2;
3665
3666		const theta = this.dot( v ) / denominator;
3667
3668		// clamp, to handle numerical problems
3669
3670		return Math.acos( clamp( theta, -1, 1 ) );
3671
3672	}
3673
3674	/**
3675	 * Computes the distance from the given vector to this instance.
3676	 *
3677	 * @param {Vector2} v - The vector to compute the distance to.
3678	 * @return {number} The distance.
3679	 */
3680	distanceTo( v ) {
3681
3682		return Math.sqrt( this.distanceToSquared( v ) );
3683
3684	}
3685
3686	/**
3687	 * Computes the squared distance from the given vector to this instance.
3688	 * If you are just comparing the distance with another distance, you should compare
3689	 * the distance squared instead as it is slightly more efficient to calculate.
3690	 *
3691	 * @param {Vector2} v - The vector to compute the squared distance to.
3692	 * @return {number} The squared distance.
3693	 */
3694	distanceToSquared( v ) {
3695
3696		const dx = this.x - v.x, dy = this.y - v.y;
3697		return dx * dx + dy * dy;
3698
3699	}
3700
3701	/**
3702	 * Computes the Manhattan distance from the given vector to this instance.
3703	 *
3704	 * @param {Vector2} v - The vector to compute the Manhattan distance to.
3705	 * @return {number} The Manhattan distance.
3706	 */
3707	manhattanDistanceTo( v ) {
3708
3709		return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y );
3710
3711	}
3712
3713	/**
3714	 * Sets this vector to a vector with the same direction as this one, but
3715	 * with the specified length.
3716	 *
3717	 * @param {number} length - The new length of this vector.
3718	 * @return {Vector2} A reference to this vector.
3719	 */
3720	setLength( length ) {
3721
3722		return this.normalize().multiplyScalar( length );
3723
3724	}
3725
3726	/**
3727	 * Linearly interpolates between the given vector and this instance, where
3728	 * alpha is the percent distance along the line - alpha = 0 will be this
3729	 * vector, and alpha = 1 will be the given one.
3730	 *
3731	 * @param {Vector2} v - The vector to interpolate towards.
3732	 * @param {number} alpha - The interpolation factor, typically in the closed interval `[0, 1]`.
3733	 * @return {Vector2} A reference to this vector.
3734	 */
3735	lerp( v, alpha ) {
3736
3737		this.x += ( v.x - this.x ) * alpha;
3738		this.y += ( v.y - this.y ) * alpha;
3739
3740		return this;
3741
3742	}
3743
3744	/**
3745	 * Linearly interpolates between the given vectors, where alpha is the percent
3746	 * distance along the line - alpha = 0 will be first vector, and alpha = 1 will
3747	 * be the second one. The result is stored in this instance.
3748	 *
3749	 * @param {Vector2} v1 - The first vector.
3750	 * @param {Vector2} v2 - The second vector.
3751	 * @param {number} alpha - The interpolation factor, typically in the closed interval `[0, 1]`.
3752	 * @return {Vector2} A reference to this vector.
3753	 */
3754	lerpVectors( v1, v2, alpha ) {
3755
3756		this.x = v1.x + ( v2.x - v1.x ) * alpha;
3757		this.y = v1.y + ( v2.y - v1.y ) * alpha;
3758
3759		return this;
3760
3761	}
3762
3763	/**
3764	 * Returns `true` if this vector is equal with the given one.
3765	 *
3766	 * @param {Vector2} v - The vector to test for equality.
3767	 * @return {boolean} Whether this vector is equal with the given one.
3768	 */
3769	equals( v ) {
3770
3771		return ( ( v.x === this.x ) && ( v.y === this.y ) );
3772
3773	}
3774
3775	/**
3776	 * Sets this vector's x value to be `array[ offset ]` and y
3777	 * value to be `array[ offset + 1 ]`.
3778	 *
3779	 * @param {Array<number>} array - An array holding the vector component values.
3780	 * @param {number} [offset=0] - The offset into the array.
3781	 * @return {Vector2} A reference to this vector.
3782	 */
3783	fromArray( array, offset = 0 ) {
3784
3785		this.x = array[ offset ];
3786		this.y = array[ offset + 1 ];
3787
3788		return this;
3789
3790	}
3791
3792	/**
3793	 * Writes the components of this vector to the given array. If no array is provided,
3794	 * the method returns a new instance.
3795	 *
3796	 * @param {Array<number>} [array=[]] - The target array holding the vector components.
3797	 * @param {number} [offset=0] - Index of the first element in the array.
3798	 * @return {Array<number>} The vector components.
3799	 */
3800	toArray( array = [], offset = 0 ) {
3801
3802		array[ offset ] = this.x;
3803		array[ offset + 1 ] = this.y;
3804
3805		return array;
3806
3807	}
3808
3809	/**
3810	 * Sets the components of this vector from the given buffer attribute.
3811	 *
3812	 * @param {BufferAttribute} attribute - The buffer attribute holding vector data.
3813	 * @param {number} index - The index into the attribute.
3814	 * @return {Vector2} A reference to this vector.
3815	 */
3816	fromBufferAttribute( attribute, index ) {
3817
3818		this.x = attribute.getX( index );
3819		this.y = attribute.getY( index );
3820
3821		return this;
3822
3823	}
3824
3825	/**
3826	 * Rotates this vector around the given center by the given angle.
3827	 *
3828	 * @param {Vector2} center - The point around which to rotate.
3829	 * @param {number} angle - The angle to rotate, in radians.
3830	 * @return {Vector2} A reference to this vector.
3831	 */
3832	rotateAround( center, angle ) {
3833
3834		const c = Math.cos( angle ), s = Math.sin( angle );
3835
3836		const x = this.x - center.x;
3837		const y = this.y - center.y;
3838
3839		this.x = x * c - y * s + center.x;
3840		this.y = x * s + y * c + center.y;
3841
3842		return this;
3843
3844	}
3845
3846	/**
3847	 * Sets each component of this vector to a pseudo-random value between `0` and
3848	 * `1`, excluding `1`.
3849	 *
3850	 * @return {Vector2} A reference to this vector.
3851	 */
3852	random() {
3853
3854		this.x = Math.random();
3855		this.y = Math.random();
3856
3857		return this;
3858
3859	}
3860
3861	*[ Symbol.iterator ]() {
3862
3863		yield this.x;
3864		yield this.y;
3865
3866	}
3867
3868}
3869
3870/**
3871 * Class for representing a Quaternion. Quaternions are used in three.js to represent rotations.
3872 *
3873 * Iterating through a vector instance will yield its components `(x, y, z, w)` in
3874 * the corresponding order.
3875 *
3876 * Note that three.js expects Quaternions to be normalized.
3877 * ```js
3878 * const quaternion = new THREE.Quaternion();
3879 * quaternion.setFromAxisAngle( new THREE.Vector3( 0, 1, 0 ), Math.PI / 2 );
3880 *
3881 * const vector = new THREE.Vector3( 1, 0, 0 );
3882 * vector.applyQuaternion( quaternion );
3883 * ```
3884 */
3885class Quaternion {
3886
3887	/**
3888	 * Constructs a new quaternion.
3889	 *
3890	 * @param {number} [x=0] - The x value of this quaternion.
3891	 * @param {number} [y=0] - The y value of this quaternion.
3892	 * @param {number} [z=0] - The z value of this quaternion.
3893	 * @param {number} [w=1] - The w value of this quaternion.
3894	 */
3895	constructor( x = 0, y = 0, z = 0, w = 1 ) {
3896
3897		/**
3898		 * This flag can be used for type testing.
3899		 *
3900		 * @type {boolean}
3901		 * @readonly
3902		 * @default true
3903		 */
3904		this.isQuaternion = true;
3905
3906		this._x = x;
3907		this._y = y;
3908		this._z = z;
3909		this._w = w;
3910
3911	}
3912
3913	/**
3914	 * Interpolates between two quaternions via SLERP. This implementation assumes the
3915	 * quaternion data are managed in flat arrays.
3916	 *
3917	 * @param {Array<number>} dst - The destination array.
3918	 * @param {number} dstOffset - An offset into the destination array.
3919	 * @param {Array<number>} src0 - The source array of the first quaternion.
3920	 * @param {number} srcOffset0 - An offset into the first source array.
3921	 * @param {Array<number>} src1 -  The source array of the second quaternion.
3922	 * @param {number} srcOffset1 - An offset into the second source array.
3923	 * @param {number} t - The interpolation factor. A value in the range `[0,1]` will interpolate. A value outside the range `[0,1]` will extrapolate.
3924	 * @see {@link Quaternion#slerp}
3925	 */
3926	static slerpFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) {
3927
3928		let x0 = src0[ srcOffset0 + 0 ],
3929			y0 = src0[ srcOffset0 + 1 ],
3930			z0 = src0[ srcOffset0 + 2 ],
3931			w0 = src0[ srcOffset0 + 3 ];
3932
3933		let x1 = src1[ srcOffset1 + 0 ],
3934			y1 = src1[ srcOffset1 + 1 ],
3935			z1 = src1[ srcOffset1 + 2 ],
3936			w1 = src1[ srcOffset1 + 3 ];
3937
3938		if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) {
3939
3940			let dot = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1;
3941
3942			if ( dot < 0 ) {
3943
3944				x1 = - x1;
3945				y1 = - y1;
3946				z1 = - z1;
3947				w1 = - w1;
3948
3949				dot = - dot;
3950
3951			}
3952
3953			let s = 1 - t;
3954
3955			if ( dot < 0.9995 ) {
3956
3957				// slerp
3958
3959				const theta = Math.acos( dot );
3960				const sin = Math.sin( theta );
3961
3962				s = Math.sin( s * theta ) / sin;
3963				t = Math.sin( t * theta ) / sin;
3964
3965				x0 = x0 * s + x1 * t;
3966				y0 = y0 * s + y1 * t;
3967				z0 = z0 * s + z1 * t;
3968				w0 = w0 * s + w1 * t;
3969
3970			} else {
3971
3972				// for small angles, lerp then normalize
3973
3974				x0 = x0 * s + x1 * t;
3975				y0 = y0 * s + y1 * t;
3976				z0 = z0 * s + z1 * t;
3977				w0 = w0 * s + w1 * t;
3978
3979				const f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 );
3980
3981				x0 *= f;
3982				y0 *= f;
3983				z0 *= f;
3984				w0 *= f;
3985
3986			}
3987
3988		}
3989
3990		dst[ dstOffset ] = x0;
3991		dst[ dstOffset + 1 ] = y0;
3992		dst[ dstOffset + 2 ] = z0;
3993		dst[ dstOffset + 3 ] = w0;
3994
3995	}
3996
vendor: 14,213 bytes, lines 3997-4637
3997	/**
3998	 * Multiplies two quaternions. This implementation assumes the quaternion data are managed
3999	 * in flat arrays.
4000	 *
4001	 * @param {Array<number>} dst - The destination array.
4002	 * @param {number} dstOffset - An offset into the destination array.
4003	 * @param {Array<number>} src0 - The source array of the first quaternion.
4004	 * @param {number} srcOffset0 - An offset into the first source array.
4005	 * @param {Array<number>} src1 -  The source array of the second quaternion.
4006	 * @param {number} srcOffset1 - An offset into the second source array.
4007	 * @return {Array<number>} The destination array.
4008	 * @see {@link Quaternion#multiplyQuaternions}.
4009	 */
4010	static multiplyQuaternionsFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1 ) {
4011
4012		const x0 = src0[ srcOffset0 ];
4013		const y0 = src0[ srcOffset0 + 1 ];
4014		const z0 = src0[ srcOffset0 + 2 ];
4015		const w0 = src0[ srcOffset0 + 3 ];
4016
4017		const x1 = src1[ srcOffset1 ];
4018		const y1 = src1[ srcOffset1 + 1 ];
4019		const z1 = src1[ srcOffset1 + 2 ];
4020		const w1 = src1[ srcOffset1 + 3 ];
4021
4022		dst[ dstOffset ] = x0 * w1 + w0 * x1 + y0 * z1 - z0 * y1;
4023		dst[ dstOffset + 1 ] = y0 * w1 + w0 * y1 + z0 * x1 - x0 * z1;
4024		dst[ dstOffset + 2 ] = z0 * w1 + w0 * z1 + x0 * y1 - y0 * x1;
4025		dst[ dstOffset + 3 ] = w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1;
4026
4027		return dst;
4028
4029	}
4030
4031	/**
4032	 * The x value of this quaternion.
4033	 *
4034	 * @type {number}
4035	 * @default 0
4036	 */
4037	get x() {
4038
4039		return this._x;
4040
4041	}
4042
4043	set x( value ) {
4044
4045		this._x = value;
4046		this._onChangeCallback();
4047
4048	}
4049
4050	/**
4051	 * The y value of this quaternion.
4052	 *
4053	 * @type {number}
4054	 * @default 0
4055	 */
4056	get y() {
4057
4058		return this._y;
4059
4060	}
4061
4062	set y( value ) {
4063
4064		this._y = value;
4065		this._onChangeCallback();
4066
4067	}
4068
4069	/**
4070	 * The z value of this quaternion.
4071	 *
4072	 * @type {number}
4073	 * @default 0
4074	 */
4075	get z() {
4076
4077		return this._z;
4078
4079	}
4080
4081	set z( value ) {
4082
4083		this._z = value;
4084		this._onChangeCallback();
4085
4086	}
4087
4088	/**
4089	 * The w value of this quaternion.
4090	 *
4091	 * @type {number}
4092	 * @default 1
4093	 */
4094	get w() {
4095
4096		return this._w;
4097
4098	}
4099
4100	set w( value ) {
4101
4102		this._w = value;
4103		this._onChangeCallback();
4104
4105	}
4106
4107	/**
4108	 * Sets the quaternion components.
4109	 *
4110	 * @param {number} x - The x value of this quaternion.
4111	 * @param {number} y - The y value of this quaternion.
4112	 * @param {number} z - The z value of this quaternion.
4113	 * @param {number} w - The w value of this quaternion.
4114	 * @return {Quaternion} A reference to this quaternion.
4115	 */
4116	set( x, y, z, w ) {
4117
4118		this._x = x;
4119		this._y = y;
4120		this._z = z;
4121		this._w = w;
4122
4123		this._onChangeCallback();
4124
4125		return this;
4126
4127	}
4128
4129	/**
4130	 * Returns a new quaternion with copied values from this instance.
4131	 *
4132	 * @return {Quaternion} A clone of this instance.
4133	 */
4134	clone() {
4135
4136		return new this.constructor( this._x, this._y, this._z, this._w );
4137
4138	}
4139
4140	/**
4141	 * Copies the values of the given quaternion to this instance.
4142	 *
4143	 * @param {Quaternion} quaternion - The quaternion to copy.
4144	 * @return {Quaternion} A reference to this quaternion.
4145	 */
4146	copy( quaternion ) {
4147
4148		this._x = quaternion.x;
4149		this._y = quaternion.y;
4150		this._z = quaternion.z;
4151		this._w = quaternion.w;
4152
4153		this._onChangeCallback();
4154
4155		return this;
4156
4157	}
4158
4159	/**
4160	 * Sets this quaternion from the rotation specified by the given
4161	 * Euler angles.
4162	 *
4163	 * @param {Euler} euler - The Euler angles.
4164	 * @param {boolean} [update=true] - Whether the internal `onChange` callback should be executed or not.
4165	 * @return {Quaternion} A reference to this quaternion.
4166	 */
4167	setFromEuler( euler, update = true ) {
4168
4169		const x = euler._x, y = euler._y, z = euler._z, order = euler._order;
4170
4171		// http://www.mathworks.com/matlabcentral/fileexchange/
4172		// 	20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/
4173		//	content/SpinCalc.m
4174
4175		const cos = Math.cos;
4176		const sin = Math.sin;
4177
4178		const c1 = cos( x / 2 );
4179		const c2 = cos( y / 2 );
4180		const c3 = cos( z / 2 );
4181
4182		const s1 = sin( x / 2 );
4183		const s2 = sin( y / 2 );
4184		const s3 = sin( z / 2 );
4185
4186		switch ( order ) {
4187
4188			case 'XYZ':
4189				this._x = s1 * c2 * c3 + c1 * s2 * s3;
4190				this._y = c1 * s2 * c3 - s1 * c2 * s3;
4191				this._z = c1 * c2 * s3 + s1 * s2 * c3;
4192				this._w = c1 * c2 * c3 - s1 * s2 * s3;
4193				break;
4194
4195			case 'YXZ':
4196				this._x = s1 * c2 * c3 + c1 * s2 * s3;
4197				this._y = c1 * s2 * c3 - s1 * c2 * s3;
4198				this._z = c1 * c2 * s3 - s1 * s2 * c3;
4199				this._w = c1 * c2 * c3 + s1 * s2 * s3;
4200				break;
4201
4202			case 'ZXY':
4203				this._x = s1 * c2 * c3 - c1 * s2 * s3;
4204				this._y = c1 * s2 * c3 + s1 * c2 * s3;
4205				this._z = c1 * c2 * s3 + s1 * s2 * c3;
4206				this._w = c1 * c2 * c3 - s1 * s2 * s3;
4207				break;
4208
4209			case 'ZYX':
4210				this._x = s1 * c2 * c3 - c1 * s2 * s3;
4211				this._y = c1 * s2 * c3 + s1 * c2 * s3;
4212				this._z = c1 * c2 * s3 - s1 * s2 * c3;
4213				this._w = c1 * c2 * c3 + s1 * s2 * s3;
4214				break;
4215
4216			case 'YZX':
4217				this._x = s1 * c2 * c3 + c1 * s2 * s3;
4218				this._y = c1 * s2 * c3 + s1 * c2 * s3;
4219				this._z = c1 * c2 * s3 - s1 * s2 * c3;
4220				this._w = c1 * c2 * c3 - s1 * s2 * s3;
4221				break;
4222
4223			case 'XZY':
4224				this._x = s1 * c2 * c3 - c1 * s2 * s3;
4225				this._y = c1 * s2 * c3 - s1 * c2 * s3;
4226				this._z = c1 * c2 * s3 + s1 * s2 * c3;
4227				this._w = c1 * c2 * c3 + s1 * s2 * s3;
4228				break;
4229
4230			default:
4231				warn( 'Quaternion: .setFromEuler() encountered an unknown order: ' + order );
4232
4233		}
4234
4235		if ( update === true ) this._onChangeCallback();
4236
4237		return this;
4238
4239	}
4240
4241	/**
4242	 * Sets this quaternion from the given axis and angle.
4243	 *
4244	 * @param {Vector3} axis - The normalized axis.
4245	 * @param {number} angle - The angle in radians.
4246	 * @return {Quaternion} A reference to this quaternion.
4247	 */
4248	setFromAxisAngle( axis, angle ) {
4249
4250		// http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm
4251
4252		const halfAngle = angle / 2, s = Math.sin( halfAngle );
4253
4254		this._x = axis.x * s;
4255		this._y = axis.y * s;
4256		this._z = axis.z * s;
4257		this._w = Math.cos( halfAngle );
4258
4259		this._onChangeCallback();
4260
4261		return this;
4262
4263	}
4264
4265	/**
4266	 * Sets this quaternion from the given rotation matrix.
4267	 *
4268	 * @param {Matrix4} m - A 4x4 matrix of which the upper 3x3 of matrix is a pure rotation matrix (i.e. unscaled).
4269	 * @return {Quaternion} A reference to this quaternion.
4270	 */
4271	setFromRotationMatrix( m ) {
4272
4273		// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
4274
4275		// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
4276
4277		const te = m.elements,
4278
4279			m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
4280			m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
4281			m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ],
4282
4283			trace = m11 + m22 + m33;
4284
4285		if ( trace > 0 ) {
4286
4287			const s = 0.5 / Math.sqrt( trace + 1.0 );
4288
4289			this._w = 0.25 / s;
4290			this._x = ( m32 - m23 ) * s;
4291			this._y = ( m13 - m31 ) * s;
4292			this._z = ( m21 - m12 ) * s;
4293
4294		} else if ( m11 > m22 && m11 > m33 ) {
4295
4296			const s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 );
4297
4298			this._w = ( m32 - m23 ) / s;
4299			this._x = 0.25 * s;
4300			this._y = ( m12 + m21 ) / s;
4301			this._z = ( m13 + m31 ) / s;
4302
4303		} else if ( m22 > m33 ) {
4304
4305			const s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 );
4306
4307			this._w = ( m13 - m31 ) / s;
4308			this._x = ( m12 + m21 ) / s;
4309			this._y = 0.25 * s;
4310			this._z = ( m23 + m32 ) / s;
4311
4312		} else {
4313
4314			const s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 );
4315
4316			this._w = ( m21 - m12 ) / s;
4317			this._x = ( m13 + m31 ) / s;
4318			this._y = ( m23 + m32 ) / s;
4319			this._z = 0.25 * s;
4320
4321		}
4322
4323		this._onChangeCallback();
4324
4325		return this;
4326
4327	}
4328
4329	/**
4330	 * Sets this quaternion to the rotation required to rotate the direction vector
4331	 * `vFrom` to the direction vector `vTo`.
4332	 *
4333	 * @param {Vector3} vFrom - The first (normalized) direction vector.
4334	 * @param {Vector3} vTo - The second (normalized) direction vector.
4335	 * @return {Quaternion} A reference to this quaternion.
4336	 */
4337	setFromUnitVectors( vFrom, vTo ) {
4338
4339		// assumes direction vectors vFrom and vTo are normalized
4340
4341		let r = vFrom.dot( vTo ) + 1;
4342
4343		if ( r < 1e-8 ) { // the epsilon value has been discussed in #31286
4344
4345			// vFrom and vTo point in opposite directions
4346
4347			r = 0;
4348
4349			if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) {
4350
4351				this._x = - vFrom.y;
4352				this._y = vFrom.x;
4353				this._z = 0;
4354				this._w = r;
4355
4356			} else {
4357
4358				this._x = 0;
4359				this._y = - vFrom.z;
4360				this._z = vFrom.y;
4361				this._w = r;
4362
4363			}
4364
4365		} else {
4366
4367			// crossVectors( vFrom, vTo ); // inlined to avoid cyclic dependency on Vector3
4368
4369			this._x = vFrom.y * vTo.z - vFrom.z * vTo.y;
4370			this._y = vFrom.z * vTo.x - vFrom.x * vTo.z;
4371			this._z = vFrom.x * vTo.y - vFrom.y * vTo.x;
4372			this._w = r;
4373
4374		}
4375
4376		return this.normalize();
4377
4378	}
4379
4380	/**
4381	 * Returns the angle between this quaternion and the given one in radians.
4382	 *
4383	 * @param {Quaternion} q - The quaternion to compute the angle with.
4384	 * @return {number} The angle in radians.
4385	 */
4386	angleTo( q ) {
4387
4388		return 2 * Math.acos( Math.abs( clamp( this.dot( q ), -1, 1 ) ) );
4389
4390	}
4391
4392	/**
4393	 * Rotates this quaternion by a given angular step to the given quaternion.
4394	 * The method ensures that the final quaternion will not overshoot `q`.
4395	 *
4396	 * @param {Quaternion} q - The target quaternion.
4397	 * @param {number} step - The angular step in radians.
4398	 * @return {Quaternion} A reference to this quaternion.
4399	 */
4400	rotateTowards( q, step ) {
4401
4402		const angle = this.angleTo( q );
4403
4404		if ( angle === 0 ) return this;
4405
4406		const t = Math.min( 1, step / angle );
4407
4408		this.slerp( q, t );
4409
4410		return this;
4411
4412	}
4413
4414	/**
4415	 * Sets this quaternion to the identity quaternion; that is, to the
4416	 * quaternion that represents "no rotation".
4417	 *
4418	 * @return {Quaternion} A reference to this quaternion.
4419	 */
4420	identity() {
4421
4422		return this.set( 0, 0, 0, 1 );
4423
4424	}
4425
4426	/**
4427	 * Inverts this quaternion via {@link Quaternion#conjugate}. The
4428	 * quaternion is assumed to have unit length.
4429	 *
4430	 * @return {Quaternion} A reference to this quaternion.
4431	 */
4432	invert() {
4433
4434		return this.conjugate();
4435
4436	}
4437
4438	/**
4439	 * Returns the rotational conjugate of this quaternion. The conjugate of a
4440	 * quaternion represents the same rotation in the opposite direction about
4441	 * the rotational axis.
4442	 *
4443	 * @return {Quaternion} A reference to this quaternion.
4444	 */
4445	conjugate() {
4446
4447		this._x *= -1;
4448		this._y *= -1;
4449		this._z *= -1;
4450
4451		this._onChangeCallback();
4452
4453		return this;
4454
4455	}
4456
4457	/**
4458	 * Calculates the dot product of this quaternion and the given one.
4459	 *
4460	 * @param {Quaternion} v - The quaternion to compute the dot product with.
4461	 * @return {number} The result of the dot product.
4462	 */
4463	dot( v ) {
4464
4465		return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w;
4466
4467	}
4468
4469	/**
4470	 * Computes the squared Euclidean length (straight-line length) of this quaternion,
4471	 * considered as a 4 dimensional vector. This can be useful if you are comparing the
4472	 * lengths of two quaternions, as this is a slightly more efficient calculation than
4473	 * {@link Quaternion#length}.
4474	 *
4475	 * @return {number} The squared Euclidean length.
4476	 */
4477	lengthSq() {
4478
4479		return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w;
4480
4481	}
4482
4483	/**
4484	 * Computes the Euclidean length (straight-line length) of this quaternion,
4485	 * considered as a 4 dimensional vector.
4486	 *
4487	 * @return {number} The Euclidean length.
4488	 */
4489	length() {
4490
4491		return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w );
4492
4493	}
4494
4495	/**
4496	 * Normalizes this quaternion - that is, calculated the quaternion that performs
4497	 * the same rotation as this one, but has a length equal to `1`.
4498	 *
4499	 * @return {Quaternion} A reference to this quaternion.
4500	 */
4501	normalize() {
4502
4503		let l = this.length();
4504
4505		if ( l === 0 ) {
4506
4507			this._x = 0;
4508			this._y = 0;
4509			this._z = 0;
4510			this._w = 1;
4511
4512		} else {
4513
4514			l = 1 / l;
4515
4516			this._x = this._x * l;
4517			this._y = this._y * l;
4518			this._z = this._z * l;
4519			this._w = this._w * l;
4520
4521		}
4522
4523		this._onChangeCallback();
4524
4525		return this;
4526
4527	}
4528
4529	/**
4530	 * Multiplies this quaternion by the given one.
4531	 *
4532	 * @param {Quaternion} q - The quaternion.
4533	 * @return {Quaternion} A reference to this quaternion.
4534	 */
4535	multiply( q ) {
4536
4537		return this.multiplyQuaternions( this, q );
4538
4539	}
4540
4541	/**
4542	 * Pre-multiplies this quaternion by the given one.
4543	 *
4544	 * @param {Quaternion} q - The quaternion.
4545	 * @return {Quaternion} A reference to this quaternion.
4546	 */
4547	premultiply( q ) {
4548
4549		return this.multiplyQuaternions( q, this );
4550
4551	}
4552
4553	/**
4554	 * Multiplies the given quaternions and stores the result in this instance.
4555	 *
4556	 * @param {Quaternion} a - The first quaternion.
4557	 * @param {Quaternion} b - The second quaternion.
4558	 * @return {Quaternion} A reference to this quaternion.
4559	 */
4560	multiplyQuaternions( a, b ) {
4561
4562		// from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm
4563
4564		const qax = a._x, qay = a._y, qaz = a._z, qaw = a._w;
4565		const qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w;
4566
4567		this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;
4568		this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;
4569		this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;
4570		this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;
4571
4572		this._onChangeCallback();
4573
4574		return this;
4575
4576	}
4577
4578	/**
4579	 * Performs a spherical linear interpolation between this quaternion and the target quaternion.
4580	 *
4581	 * @param {Quaternion} qb - The target quaternion.
4582	 * @param {number} t - The interpolation factor. A value in the range `[0,1]` will interpolate. A value outside the range `[0,1]` will extrapolate.
4583	 * @return {Quaternion} A reference to this quaternion.
4584	 */
4585	slerp( qb, t ) {
4586
4587		let x = qb._x, y = qb._y, z = qb._z, w = qb._w;
4588
4589		let dot = this.dot( qb );
4590
4591		if ( dot < 0 ) {
4592
4593			x = - x;
4594			y = - y;
4595			z = - z;
4596			w = - w;
4597
4598			dot = - dot;
4599
4600		}
4601
4602		let s = 1 - t;
4603
4604		if ( dot < 0.9995 ) {
4605
4606			// slerp
4607
4608			const theta = Math.acos( dot );
4609			const sin = Math.sin( theta );
4610
4611			s = Math.sin( s * theta ) / sin;
4612			t = Math.sin( t * theta ) / sin;
4613
4614			this._x = this._x * s + x * t;
4615			this._y = this._y * s + y * t;
4616			this._z = this._z * s + z * t;
4617			this._w = this._w * s + w * t;
4618
4619			this._onChangeCallback();
4620
4621		} else {
4622
4623			// for small angles, lerp then normalize
4624
4625			this._x = this._x * s + x * t;
4626			this._y = this._y * s + y * t;
4627			this._z = this._z * s + z * t;
4628			this._w = this._w * s + w * t;
4629
4630			this.normalize(); // normalize calls _onChangeCallback()
4631
4632		}
4633
4634		return this;
4635
4636	}
4637
vendor: 6,943 bytes, lines 4638-4948
4638	/**
4639	 * Performs a spherical linear interpolation between the given quaternions
4640	 * and stores the result in this quaternion.
4641	 *
4642	 * @param {Quaternion} qa - The source quaternion.
4643	 * @param {Quaternion} qb - The target quaternion.
4644	 * @param {number} t - The interpolation factor in the closed interval `[0, 1]`.
4645	 * @return {Quaternion} A reference to this quaternion.
4646	 */
4647	slerpQuaternions( qa, qb, t ) {
4648
4649		return this.copy( qa ).slerp( qb, t );
4650
4651	}
4652
4653	/**
4654	 * Sets this quaternion to a uniformly random, normalized quaternion.
4655	 *
4656	 * @return {Quaternion} A reference to this quaternion.
4657	 */
4658	random() {
4659
4660		// Ken Shoemake
4661		// Uniform random rotations
4662		// D. Kirk, editor, Graphics Gems III, pages 124-132. Academic Press, New York, 1992.
4663
4664		const theta1 = 2 * Math.PI * Math.random();
4665		const theta2 = 2 * Math.PI * Math.random();
4666
4667		const x0 = Math.random();
4668		const r1 = Math.sqrt( 1 - x0 );
4669		const r2 = Math.sqrt( x0 );
4670
4671		return this.set(
4672			r1 * Math.sin( theta1 ),
4673			r1 * Math.cos( theta1 ),
4674			r2 * Math.sin( theta2 ),
4675			r2 * Math.cos( theta2 ),
4676		);
4677
4678	}
4679
4680	/**
4681	 * Returns `true` if this quaternion is equal with the given one.
4682	 *
4683	 * @param {Quaternion} quaternion - The quaternion to test for equality.
4684	 * @return {boolean} Whether this quaternion is equal with the given one.
4685	 */
4686	equals( quaternion ) {
4687
4688		return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w );
4689
4690	}
4691
4692	/**
4693	 * Sets this quaternion's components from the given array.
4694	 *
4695	 * @param {Array<number>} array - An array holding the quaternion component values.
4696	 * @param {number} [offset=0] - The offset into the array.
4697	 * @return {Quaternion} A reference to this quaternion.
4698	 */
4699	fromArray( array, offset = 0 ) {
4700
4701		this._x = array[ offset ];
4702		this._y = array[ offset + 1 ];
4703		this._z = array[ offset + 2 ];
4704		this._w = array[ offset + 3 ];
4705
4706		this._onChangeCallback();
4707
4708		return this;
4709
4710	}
4711
4712	/**
4713	 * Writes the components of this quaternion to the given array. If no array is provided,
4714	 * the method returns a new instance.
4715	 *
4716	 * @param {Array<number>} [array=[]] - The target array holding the quaternion components.
4717	 * @param {number} [offset=0] - Index of the first element in the array.
4718	 * @return {Array<number>} The quaternion components.
4719	 */
4720	toArray( array = [], offset = 0 ) {
4721
4722		array[ offset ] = this._x;
4723		array[ offset + 1 ] = this._y;
4724		array[ offset + 2 ] = this._z;
4725		array[ offset + 3 ] = this._w;
4726
4727		return array;
4728
4729	}
4730
4731	/**
4732	 * Sets the components of this quaternion from the given buffer attribute.
4733	 *
4734	 * @param {BufferAttribute} attribute - The buffer attribute holding quaternion data.
4735	 * @param {number} index - The index into the attribute.
4736	 * @return {Quaternion} A reference to this quaternion.
4737	 */
4738	fromBufferAttribute( attribute, index ) {
4739
4740		this._x = attribute.getX( index );
4741		this._y = attribute.getY( index );
4742		this._z = attribute.getZ( index );
4743		this._w = attribute.getW( index );
4744
4745		this._onChangeCallback();
4746
4747		return this;
4748
4749	}
4750
4751	/**
4752	 * This methods defines the serialization result of this class. Returns the
4753	 * numerical elements of this quaternion in an array of format `[x, y, z, w]`.
4754	 *
4755	 * @return {Array<number>} The serialized quaternion.
4756	 */
4757	toJSON() {
4758
4759		return this.toArray();
4760
4761	}
4762
4763	_onChange( callback ) {
4764
4765		this._onChangeCallback = callback;
4766
4767		return this;
4768
4769	}
4770
4771	_onChangeCallback() {}
4772
4773	*[ Symbol.iterator ]() {
4774
4775		yield this._x;
4776		yield this._y;
4777		yield this._z;
4778		yield this._w;
4779
4780	}
4781
4782}
4783
4784/**
4785 * Class representing a 3D vector. A 3D vector is an ordered triplet of numbers
4786 * (labeled x, y and z), which can be used to represent a number of things, such as:
4787 *
4788 * - A point in 3D space.
4789 * - A direction and length in 3D space. In three.js the length will
4790 * always be the Euclidean distance(straight-line distance) from `(0, 0, 0)` to `(x, y, z)`
4791 * and the direction is also measured from `(0, 0, 0)` towards `(x, y, z)`.
4792 * - Any arbitrary ordered triplet of numbers.
4793 *
4794 * There are other things a 3D vector can be used to represent, such as
4795 * momentum vectors and so on, however these are the most
4796 * common uses in three.js.
4797 *
4798 * Iterating through a vector instance will yield its components `(x, y, z)` in
4799 * the corresponding order.
4800 * ```js
4801 * const a = new THREE.Vector3( 0, 1, 0 );
4802 *
4803 * //no arguments; will be initialised to (0, 0, 0)
4804 * const b = new THREE.Vector3( );
4805 *
4806 * const d = a.distanceTo( b );
4807 * ```
4808 */
4809class Vector3 {
4810
4811	static {
4812
4813		/**
4814		 * This flag can be used for type testing.
4815		 *
4816		 * @type {boolean}
4817		 * @readonly
4818		 * @default true
4819		 */
4820		Vector3.prototype.isVector3 = true;
4821
4822	}
4823
4824	/**
4825	 * Constructs a new 3D vector.
4826	 *
4827	 * @param {number} [x=0] - The x value of this vector.
4828	 * @param {number} [y=0] - The y value of this vector.
4829	 * @param {number} [z=0] - The z value of this vector.
4830	 */
4831	constructor( x = 0, y = 0, z = 0 ) {
4832
4833		/**
4834		 * The x value of this vector.
4835		 *
4836		 * @type {number}
4837		 */
4838		this.x = x;
4839
4840		/**
4841		 * The y value of this vector.
4842		 *
4843		 * @type {number}
4844		 */
4845		this.y = y;
4846
4847		/**
4848		 * The z value of this vector.
4849		 *
4850		 * @type {number}
4851		 */
4852		this.z = z;
4853
4854	}
4855
4856	/**
4857	 * Sets the vector components.
4858	 *
4859	 * @param {number} x - The value of the x component.
4860	 * @param {number} y - The value of the y component.
4861	 * @param {number} z - The value of the z component.
4862	 * @return {Vector3} A reference to this vector.
4863	 */
4864	set( x, y, z ) {
4865
4866		if ( z === undefined ) z = this.z; // sprite.scale.set(x,y)
4867
4868		this.x = x;
4869		this.y = y;
4870		this.z = z;
4871
4872		return this;
4873
4874	}
4875
4876	/**
4877	 * Sets the vector components to the same value.
4878	 *
4879	 * @param {number} scalar - The value to set for all vector components.
4880	 * @return {Vector3} A reference to this vector.
4881	 */
4882	setScalar( scalar ) {
4883
4884		this.x = scalar;
4885		this.y = scalar;
4886		this.z = scalar;
4887
4888		return this;
4889
4890	}
4891
4892	/**
4893	 * Sets the vector's x component to the given value.
4894	 *
4895	 * @param {number} x - The value to set.
4896	 * @return {Vector3} A reference to this vector.
4897	 */
4898	setX( x ) {
4899
4900		this.x = x;
4901
4902		return this;
4903
4904	}
4905
4906	/**
4907	 * Sets the vector's y component to the given value.
4908	 *
4909	 * @param {number} y - The value to set.
4910	 * @return {Vector3} A reference to this vector.
4911	 */
4912	setY( y ) {
4913
4914		this.y = y;
4915
4916		return this;
4917
4918	}
4919
4920	/**
4921	 * Sets the vector's z component to the given value.
4922	 *
4923	 * @param {number} z - The value to set.
4924	 * @return {Vector3} A reference to this vector.
4925	 */
4926	setZ( z ) {
4927
4928		this.z = z;
4929
4930		return this;
4931
4932	}
4933
4934	/**
4935	 * Allows to set a vector component with an index.
4936	 *
4937	 * @param {number} index - The component index. `0` equals to x, `1` equals to y, `2` equals to z.
4938	 * @param {number} value - The value to set.
4939	 * @return {Vector3} A reference to this vector.
4940	 */
4941	setComponent( index, value ) {
4942
4943		switch ( index ) {
4944
4945			case 0: this.x = value; break;
4946			case 1: this.y = value; break;
4947			case 2: this.z = value; break;
4948			default: throw new Error( '
4948index is out of range: ' + index );
4949
4950		}
4951
4952		return this;
4953
4954	}
4955
4956	/**
4957	 * Returns the value of the vector component which matches the given index.
4958	 *
4959	 * @param {number} index - The component index. `0` equals to x, `1` equals to y, `2` equals to z.
4960	 * @return {number} A vector component value.
4961	 */
4962	getComponent( index ) {
4963
4964		switch ( index ) {
4965
4966			case 0: return this.x;
4967			case 1: return this.y;
4968			case 2: return this.z;
4969			default: throw new Error( '
vendor: 6,725 bytes, lines 4969-5299
4969index is out of range: ' + index );
4970
4971		}
4972
4973	}
4974
4975	/**
4976	 * Returns a new vector with copied values from this instance.
4977	 *
4978	 * @return {Vector3} A clone of this instance.
4979	 */
4980	clone() {
4981
4982		return new this.constructor( this.x, this.y, this.z );
4983
4984	}
4985
4986	/**
4987	 * Copies the values of the given vector to this instance.
4988	 *
4989	 * @param {Vector3} v - The vector to copy.
4990	 * @return {Vector3} A reference to this vector.
4991	 */
4992	copy( v ) {
4993
4994		this.x = v.x;
4995		this.y = v.y;
4996		this.z = v.z;
4997
4998		return this;
4999
5000	}
5001
5002	/**
5003	 * Adds the given vector to this instance.
5004	 *
5005	 * @param {Vector3} v - The vector to add.
5006	 * @return {Vector3} A reference to this vector.
5007	 */
5008	add( v ) {
5009
5010		this.x += v.x;
5011		this.y += v.y;
5012		this.z += v.z;
5013
5014		return this;
5015
5016	}
5017
5018	/**
5019	 * Adds the given scalar value to all components of this instance.
5020	 *
5021	 * @param {number} s - The scalar to add.
5022	 * @return {Vector3} A reference to this vector.
5023	 */
5024	addScalar( s ) {
5025
5026		this.x += s;
5027		this.y += s;
5028		this.z += s;
5029
5030		return this;
5031
5032	}
5033
5034	/**
5035	 * Adds the given vectors and stores the result in this instance.
5036	 *
5037	 * @param {Vector3} a - The first vector.
5038	 * @param {Vector3} b - The second vector.
5039	 * @return {Vector3} A reference to this vector.
5040	 */
5041	addVectors( a, b ) {
5042
5043		this.x = a.x + b.x;
5044		this.y = a.y + b.y;
5045		this.z = a.z + b.z;
5046
5047		return this;
5048
5049	}
5050
5051	/**
5052	 * Adds the given vector scaled by the given factor to this instance.
5053	 *
5054	 * @param {Vector3|Vector4} v - The vector.
5055	 * @param {number} s - The factor that scales `v`.
5056	 * @return {Vector3} A reference to this vector.
5057	 */
5058	addScaledVector( v, s ) {
5059
5060		this.x += v.x * s;
5061		this.y += v.y * s;
5062		this.z += v.z * s;
5063
5064		return this;
5065
5066	}
5067
5068	/**
5069	 * Subtracts the given vector from this instance.
5070	 *
5071	 * @param {Vector3} v - The vector to subtract.
5072	 * @return {Vector3} A reference to this vector.
5073	 */
5074	sub( v ) {
5075
5076		this.x -= v.x;
5077		this.y -= v.y;
5078		this.z -= v.z;
5079
5080		return this;
5081
5082	}
5083
5084	/**
5085	 * Subtracts the given scalar value from all components of this instance.
5086	 *
5087	 * @param {number} s - The scalar to subtract.
5088	 * @return {Vector3} A reference to this vector.
5089	 */
5090	subScalar( s ) {
5091
5092		this.x -= s;
5093		this.y -= s;
5094		this.z -= s;
5095
5096		return this;
5097
5098	}
5099
5100	/**
5101	 * Subtracts the given vectors and stores the result in this instance.
5102	 *
5103	 * @param {Vector3} a - The first vector.
5104	 * @param {Vector3} b - The second vector.
5105	 * @return {Vector3} A reference to this vector.
5106	 */
5107	subVectors( a, b ) {
5108
5109		this.x = a.x - b.x;
5110		this.y = a.y - b.y;
5111		this.z = a.z - b.z;
5112
5113		return this;
5114
5115	}
5116
5117	/**
5118	 * Multiplies the given vector with this instance.
5119	 *
5120	 * @param {Vector3} v - The vector to multiply.
5121	 * @return {Vector3} A reference to this vector.
5122	 */
5123	multiply( v ) {
5124
5125		this.x *= v.x;
5126		this.y *= v.y;
5127		this.z *= v.z;
5128
5129		return this;
5130
5131	}
5132
5133	/**
5134	 * Multiplies the given scalar value with all components of this instance.
5135	 *
5136	 * @param {number} scalar - The scalar to multiply.
5137	 * @return {Vector3} A reference to this vector.
5138	 */
5139	multiplyScalar( scalar ) {
5140
5141		this.x *= scalar;
5142		this.y *= scalar;
5143		this.z *= scalar;
5144
5145		return this;
5146
5147	}
5148
5149	/**
5150	 * Multiplies the given vectors and stores the result in this instance.
5151	 *
5152	 * @param {Vector3} a - The first vector.
5153	 * @param {Vector3} b - The second vector.
5154	 * @return {Vector3} A reference to this vector.
5155	 */
5156	multiplyVectors( a, b ) {
5157
5158		this.x = a.x * b.x;
5159		this.y = a.y * b.y;
5160		this.z = a.z * b.z;
5161
5162		return this;
5163
5164	}
5165
5166	/**
5167	 * Applies the given Euler rotation to this vector.
5168	 *
5169	 * @param {Euler} euler - The Euler angles.
5170	 * @return {Vector3} A reference to this vector.
5171	 */
5172	applyEuler( euler ) {
5173
5174		return this.applyQuaternion( _quaternion$5.setFromEuler( euler ) );
5175
5176	}
5177
5178	/**
5179	 * Applies a rotation specified by an axis and an angle to this vector.
5180	 *
5181	 * @param {Vector3} axis - A normalized vector representing the rotation axis.
5182	 * @param {number} angle - The angle in radians.
5183	 * @return {Vector3} A reference to this vector.
5184	 */
5185	applyAxisAngle( axis, angle ) {
5186
5187		return this.applyQuaternion( _quaternion$5.setFromAxisAngle( axis, angle ) );
5188
5189	}
5190
5191	/**
5192	 * Multiplies this vector with the given 3x3 matrix.
5193	 *
5194	 * @param {Matrix3} m - The 3x3 matrix.
5195	 * @return {Vector3} A reference to this vector.
5196	 */
5197	applyMatrix3( m ) {
5198
5199		const x = this.x, y = this.y, z = this.z;
5200		const e = m.elements;
5201
5202		this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z;
5203		this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z;
5204		this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z;
5205
5206		return this;
5207
5208	}
5209
5210	/**
5211	 * Multiplies this vector by the given normal matrix and normalizes
5212	 * the result.
5213	 *
5214	 * @param {Matrix3} m - The normal matrix.
5215	 * @return {Vector3} A reference to this vector.
5216	 */
5217	applyNormalMatrix( m ) {
5218
5219		return this.applyMatrix3( m ).normalize();
5220
5221	}
5222
5223	/**
5224	 * Multiplies this vector (with an implicit 1 in the 4th dimension) by m, and
5225	 * divides by perspective.
5226	 *
5227	 * @param {Matrix4} m - The matrix to apply.
5228	 * @return {Vector3} A reference to this vector.
5229	 */
5230	applyMatrix4( m ) {
5231
5232		const x = this.x, y = this.y, z = this.z;
5233		const e = m.elements;
5234
5235		const w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] );
5236
5237		this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w;
5238		this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w;
5239		this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w;
5240
5241		return this;
5242
5243	}
5244
5245	/**
5246	 * Applies the given Quaternion to this vector.
5247	 *
5248	 * @param {Quaternion} q - The Quaternion.
5249	 * @return {Vector3} A reference to this vector.
5250	 */
5251	applyQuaternion( q ) {
5252
5253		// quaternion q is assumed to have unit length
5254
5255		const vx = this.x, vy = this.y, vz = this.z;
5256		const qx = q.x, qy = q.y, qz = q.z, qw = q.w;
5257
5258		// t = 2 * cross( q.xyz, v );
5259		const tx = 2 * ( qy * vz - qz * vy );
5260		const ty = 2 * ( qz * vx - qx * vz );
5261		const tz = 2 * ( qx * vy - qy * vx );
5262
5263		// v + q.w * t + cross( q.xyz, t );
5264		this.x = vx + qw * tx + qy * tz - qz * ty;
5265		this.y = vy + qw * ty + qz * tx - qx * tz;
5266		this.z = vz + qw * tz + qx * ty - qy * tx;
5267
5268		return this;
5269
5270	}
5271
5272	/**
5273	 * Projects this vector from world space into the camera's normalized
5274	 * device coordinate (NDC) space.
5275	 *
5276	 * @param {Camera} camera - The camera.
5277	 * @return {Vector3} A reference to this vector.
5278	 */
5279	project( camera ) {
5280
5281		return this.applyMatrix4( camera.matrixWorldInverse ).applyMatrix4( camera.projectionMatrix );
5282
5283	}
5284
5285	/**
5286	 * Unprojects this vector from the camera's normalized device coordinate (NDC)
5287	 * space into world space.
5288	 *
5289	 * @param {Camera} camera - The camera.
5290	 * @return {Vector3} A reference to this vector.
5291	 */
5292	unproject( camera ) {
5293
5294		return this.applyMatrix4( camera.projectionMatrixInverse ).applyMatrix4( camera.matrixWorld );
5295
5296	}
5297
5298	/**
5299	 * Transforms th
5299e direction of this vector by a matrix (the upper left 3 x 3
5300	 * subset of the given 4x4 matrix and then
vendor: 25,414 bytes, lines 5300-6366
5300 normalizes the result.
5301	 *
5302	 * @param {Matrix4} m - The matrix.
5303	 * @return {Vector3} A reference to this vector.
5304	 */
5305	transformDirection( m ) {
5306
5307		// input: THREE.Matrix4 affine matrix
5308		// vector interpreted as a direction
5309
5310		const x = this.x, y = this.y, z = this.z;
5311		const e = m.elements;
5312
5313		this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z;
5314		this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z;
5315		this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z;
5316
5317		return this.normalize();
5318
5319	}
5320
5321	/**
5322	 * Divides this instance by the given vector.
5323	 *
5324	 * @param {Vector3} v - The vector to divide.
5325	 * @return {Vector3} A reference to this vector.
5326	 */
5327	divide( v ) {
5328
5329		this.x /= v.x;
5330		this.y /= v.y;
5331		this.z /= v.z;
5332
5333		return this;
5334
5335	}
5336
5337	/**
5338	 * Divides this vector by the given scalar.
5339	 *
5340	 * @param {number} scalar - The scalar to divide.
5341	 * @return {Vector3} A reference to this vector.
5342	 */
5343	divideScalar( scalar ) {
5344
5345		return this.multiplyScalar( 1 / scalar );
5346
5347	}
5348
5349	/**
5350	 * If this vector's x, y or z value is greater than the given vector's x, y or z
5351	 * value, replace that value with the corresponding min value.
5352	 *
5353	 * @param {Vector3} v - The vector.
5354	 * @return {Vector3} A reference to this vector.
5355	 */
5356	min( v ) {
5357
5358		this.x = Math.min( this.x, v.x );
5359		this.y = Math.min( this.y, v.y );
5360		this.z = Math.min( this.z, v.z );
5361
5362		return this;
5363
5364	}
5365
5366	/**
5367	 * If this vector's x, y or z value is less than the given vector's x, y or z
5368	 * value, replace that value with the corresponding max value.
5369	 *
5370	 * @param {Vector3} v - The vector.
5371	 * @return {Vector3} A reference to this vector.
5372	 */
5373	max( v ) {
5374
5375		this.x = Math.max( this.x, v.x );
5376		this.y = Math.max( this.y, v.y );
5377		this.z = Math.max( this.z, v.z );
5378
5379		return this;
5380
5381	}
5382
5383	/**
5384	 * If this vector's x, y or z value is greater than the max vector's x, y or z
5385	 * value, it is replaced by the corresponding value.
5386	 * If this vector's x, y or z value is less than the min vector's x, y or z value,
5387	 * it is replaced by the corresponding value.
5388	 *
5389	 * @param {Vector3} min - The minimum x, y and z values.
5390	 * @param {Vector3} max - The maximum x, y and z values in the desired range.
5391	 * @return {Vector3} A reference to this vector.
5392	 */
5393	clamp( min, max ) {
5394
5395		// assumes min < max, componentwise
5396
5397		this.x = clamp( this.x, min.x, max.x );
5398		this.y = clamp( this.y, min.y, max.y );
5399		this.z = clamp( this.z, min.z, max.z );
5400
5401		return this;
5402
5403	}
5404
5405	/**
5406	 * If this vector's x, y or z values are greater than the max value, they are
5407	 * replaced by the max value.
5408	 * If this vector's x, y or z values are less than the min value, they are
5409	 * replaced by the min value.
5410	 *
5411	 * @param {number} minVal - The minimum value the components will be clamped to.
5412	 * @param {number} maxVal - The maximum value the components will be clamped to.
5413	 * @return {Vector3} A reference to this vector.
5414	 */
5415	clampScalar( minVal, maxVal ) {
5416
5417		this.x = clamp( this.x, minVal, maxVal );
5418		this.y = clamp( this.y, minVal, maxVal );
5419		this.z = clamp( this.z, minVal, maxVal );
5420
5421		return this;
5422
5423	}
5424
5425	/**
5426	 * If this vector's length is greater than the max value, it is replaced by
5427	 * the max value.
5428	 * If this vector's length is less than the min value, it is replaced by the
5429	 * min value.
5430	 *
5431	 * @param {number} min - The minimum value the vector length will be clamped to.
5432	 * @param {number} max - The maximum value the vector length will be clamped to.
5433	 * @return {Vector3} A reference to this vector.
5434	 */
5435	clampLength( min, max ) {
5436
5437		const length = this.length();
5438
5439		return this.divideScalar( length || 1 ).multiplyScalar( clamp( length, min, max ) );
5440
5441	}
5442
5443	/**
5444	 * The components of this vector are rounded down to the nearest integer value.
5445	 *
5446	 * @return {Vector3} A reference to this vector.
5447	 */
5448	floor() {
5449
5450		this.x = Math.floor( this.x );
5451		this.y = Math.floor( this.y );
5452		this.z = Math.floor( this.z );
5453
5454		return this;
5455
5456	}
5457
5458	/**
5459	 * The components of this vector are rounded up to the nearest integer value.
5460	 *
5461	 * @return {Vector3} A reference to this vector.
5462	 */
5463	ceil() {
5464
5465		this.x = Math.ceil( this.x );
5466		this.y = Math.ceil( this.y );
5467		this.z = Math.ceil( this.z );
5468
5469		return this;
5470
5471	}
5472
5473	/**
5474	 * The components of this vector are rounded to the nearest integer value
5475	 *
5476	 * @return {Vector3} A reference to this vector.
5477	 */
5478	round() {
5479
5480		this.x = Math.round( this.x );
5481		this.y = Math.round( this.y );
5482		this.z = Math.round( this.z );
5483
5484		return this;
5485
5486	}
5487
5488	/**
5489	 * The components of this vector are rounded towards zero (up if negative,
5490	 * down if positive) to an integer value.
5491	 *
5492	 * @return {Vector3} A reference to this vector.
5493	 */
5494	roundToZero() {
5495
5496		this.x = Math.trunc( this.x );
5497		this.y = Math.trunc( this.y );
5498		this.z = Math.trunc( this.z );
5499
5500		return this;
5501
5502	}
5503
5504	/**
5505	 * Inverts this vector - i.e. sets x = -x, y = -y and z = -z.
5506	 *
5507	 * @return {Vector3} A reference to this vector.
5508	 */
5509	negate() {
5510
5511		this.x = - this.x;
5512		this.y = - this.y;
5513		this.z = - this.z;
5514
5515		return this;
5516
5517	}
5518
5519	/**
5520	 * Calculates the dot product of the given vector with this instance.
5521	 *
5522	 * @param {Vector3} v - The vector to compute the dot product with.
5523	 * @return {number} The result of the dot product.
5524	 */
5525	dot( v ) {
5526
5527		return this.x * v.x + this.y * v.y + this.z * v.z;
5528
5529	}
5530
5531	/**
5532	 * Computes the square of the Euclidean length (straight-line length) from
5533	 * (0, 0, 0) to (x, y, z). If you are comparing the lengths of vectors, you should
5534	 * compare the length squared instead as it is slightly more efficient to calculate.
5535	 *
5536	 * @return {number} The square length of this vector.
5537	 */
5538	lengthSq() {
5539
5540		return this.x * this.x + this.y * this.y + this.z * this.z;
5541
5542	}
5543
5544	/**
5545	 * Computes the  Euclidean length (straight-line length) from (0, 0, 0) to (x, y, z).
5546	 *
5547	 * @return {number} The length of this vector.
5548	 */
5549	length() {
5550
5551		return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z );
5552
5553	}
5554
5555	/**
5556	 * Computes the Manhattan length of this vector.
5557	 *
5558	 * @return {number} The length of this vector.
5559	 */
5560	manhattanLength() {
5561
5562		return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z );
5563
5564	}
5565
5566	/**
5567	 * Converts this vector to a unit vector - that is, sets it equal to a vector
5568	 * with the same direction as this one, but with a vector length of `1`.
5569	 *
5570	 * @return {Vector3} A reference to this vector.
5571	 */
5572	normalize() {
5573
5574		return this.divideScalar( this.length() || 1 );
5575
5576	}
5577
5578	/**
5579	 * Sets this vector to a vector with the same direction as this one, but
5580	 * with the specified length.
5581	 *
5582	 * @param {number} length - The new length of this vector.
5583	 * @return {Vector3} A reference to this vector.
5584	 */
5585	setLength( length ) {
5586
5587		return this.normalize().multiplyScalar( length );
5588
5589	}
5590
5591	/**
5592	 * Linearly interpolates between the given vector and this instance, where
5593	 * alpha is the percent distance along the line - alpha = 0 will be this
5594	 * vector, and alpha = 1 will be the given one.
5595	 *
5596	 * @param {Vector3} v - The vector to interpolate towards.
5597	 * @param {number} alpha - The interpolation factor, typically in the closed interval `[0, 1]`.
5598	 * @return {Vector3} A reference to this vector.
5599	 */
5600	lerp( v, alpha ) {
5601
5602		this.x += ( v.x - this.x ) * alpha;
5603		this.y += ( v.y - this.y ) * alpha;
5604		this.z += ( v.z - this.z ) * alpha;
5605
5606		return this;
5607
5608	}
5609
5610	/**
5611	 * Linearly interpolates between the given vectors, where alpha is the percent
5612	 * distance along the line - alpha = 0 will be first vector, and alpha = 1 will
5613	 * be the second one. The result is stored in this instance.
5614	 *
5615	 * @param {Vector3} v1 - The first vector.
5616	 * @param {Vector3} v2 - The second vector.
5617	 * @param {number} alpha - The interpolation factor, typically in the closed interval `[0, 1]`.
5618	 * @return {Vector3} A reference to this vector.
5619	 */
5620	lerpVectors( v1, v2, alpha ) {
5621
5622		this.x = v1.x + ( v2.x - v1.x ) * alpha;
5623		this.y = v1.y + ( v2.y - v1.y ) * alpha;
5624		this.z = v1.z + ( v2.z - v1.z ) * alpha;
5625
5626		return this;
5627
5628	}
5629
5630	/**
5631	 * Calculates the cross product of the given vector with this instance.
5632	 *
5633	 * @param {Vector3} v - The vector to compute the cross product with.
5634	 * @return {Vector3} The result of the cross product.
5635	 */
5636	cross( v ) {
5637
5638		return this.crossVectors( this, v );
5639
5640	}
5641
5642	/**
5643	 * Calculates the cross product of the given vectors and stores the result
5644	 * in this instance.
5645	 *
5646	 * @param {Vector3} a - The first vector.
5647	 * @param {Vector3} b - The second vector.
5648	 * @return {Vector3} A reference to this vector.
5649	 */
5650	crossVectors( a, b ) {
5651
5652		const ax = a.x, ay = a.y, az = a.z;
5653		const bx = b.x, by = b.y, bz = b.z;
5654
5655		this.x = ay * bz - az * by;
5656		this.y = az * bx - ax * bz;
5657		this.z = ax * by - ay * bx;
5658
5659		return this;
5660
5661	}
5662
5663	/**
5664	 * Projects this vector onto the given one.
5665	 *
5666	 * @param {Vector3} v - The vector to project to.
5667	 * @return {Vector3} A reference to this vector.
5668	 */
5669	projectOnVector( v ) {
5670
5671		const denominator = v.lengthSq();
5672
5673		if ( denominator === 0 ) return this.set( 0, 0, 0 );
5674
5675		const scalar = v.dot( this ) / denominator;
5676
5677		return this.copy( v ).multiplyScalar( scalar );
5678
5679	}
5680
5681	/**
5682	 * Projects this vector onto a plane by subtracting this
5683	 * vector projected onto the plane's normal from this vector.
5684	 *
5685	 * @param {Vector3} planeNormal - The plane normal.
5686	 * @return {Vector3} A reference to this vector.
5687	 */
5688	projectOnPlane( planeNormal ) {
5689
5690		_vector$c.copy( this ).projectOnVector( planeNormal );
5691
5692		return this.sub( _vector$c );
5693
5694	}
5695
5696	/**
5697	 * Reflects this vector off a plane orthogonal to the given normal vector.
5698	 *
5699	 * @param {Vector3} normal - The (normalized) normal vector.
5700	 * @return {Vector3} A reference to this vector.
5701	 */
5702	reflect( normal ) {
5703
5704		return this.sub( _vector$c.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) );
5705
5706	}
5707	/**
5708	 * Returns the angle between the given vector and this instance in radians.
5709	 *
5710	 * @param {Vector3} v - The vector to compute the angle with.
5711	 * @return {number} The angle in radians.
5712	 */
5713	angleTo( v ) {
5714
5715		const denominator = Math.sqrt( this.lengthSq() * v.lengthSq() );
5716
5717		if ( denominator === 0 ) return Math.PI / 2;
5718
5719		const theta = this.dot( v ) / denominator;
5720
5721		// clamp, to handle numerical problems
5722
5723		return Math.acos( clamp( theta, -1, 1 ) );
5724
5725	}
5726
5727	/**
5728	 * Computes the distance from the given vector to this instance.
5729	 *
5730	 * @param {Vector3} v - The vector to compute the distance to.
5731	 * @return {number} The distance.
5732	 */
5733	distanceTo( v ) {
5734
5735		return Math.sqrt( this.distanceToSquared( v ) );
5736
5737	}
5738
5739	/**
5740	 * Computes the squared distance from the given vector to this instance.
5741	 * If you are just comparing the distance with another distance, you should compare
5742	 * the distance squared instead as it is slightly more efficient to calculate.
5743	 *
5744	 * @param {Vector3} v - The vector to compute the squared distance to.
5745	 * @return {number} The squared distance.
5746	 */
5747	distanceToSquared( v ) {
5748
5749		const dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z;
5750
5751		return dx * dx + dy * dy + dz * dz;
5752
5753	}
5754
5755	/**
5756	 * Computes the Manhattan distance from the given vector to this instance.
5757	 *
5758	 * @param {Vector3} v - The vector to compute the Manhattan distance to.
5759	 * @return {number} The Manhattan distance.
5760	 */
5761	manhattanDistanceTo( v ) {
5762
5763		return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ) + Math.abs( this.z - v.z );
5764
5765	}
5766
5767	/**
5768	 * Sets the vector components from the given spherical coordinates.
5769	 *
5770	 * @param {Spherical} s - The spherical coordinates.
5771	 * @return {Vector3} A reference to this vector.
5772	 */
5773	setFromSpherical( s ) {
5774
5775		return this.setFromSphericalCoords( s.radius, s.phi, s.theta );
5776
5777	}
5778
5779	/**
5780	 * Sets the vector components from the given spherical coordinates.
5781	 *
5782	 * @param {number} radius - The radius.
5783	 * @param {number} phi - The phi angle in radians.
5784	 * @param {number} theta - The theta angle in radians.
5785	 * @return {Vector3} A reference to this vector.
5786	 */
5787	setFromSphericalCoords( radius, phi, theta ) {
5788
5789		const sinPhiRadius = Math.sin( phi ) * radius;
5790
5791		this.x = sinPhiRadius * Math.sin( theta );
5792		this.y = Math.cos( phi ) * radius;
5793		this.z = sinPhiRadius * Math.cos( theta );
5794
5795		return this;
5796
5797	}
5798
5799	/**
5800	 * Sets the vector components from the given cylindrical coordinates.
5801	 *
5802	 * @param {Cylindrical} c - The cylindrical coordinates.
5803	 * @return {Vector3} A reference to this vector.
5804	 */
5805	setFromCylindrical( c ) {
5806
5807		return this.setFromCylindricalCoords( c.radius, c.theta, c.y );
5808
5809	}
5810
5811	/**
5812	 * Sets the vector components from the given cylindrical coordinates.
5813	 *
5814	 * @param {number} radius - The radius.
5815	 * @param {number} theta - The theta angle in radians.
5816	 * @param {number} y - The y value.
5817	 * @return {Vector3} A reference to this vector.
5818	 */
5819	setFromCylindricalCoords( radius, theta, y ) {
5820
5821		this.x = radius * Math.sin( theta );
5822		this.y = y;
5823		this.z = radius * Math.cos( theta );
5824
5825		return this;
5826
5827	}
5828
5829	/**
5830	 * Sets the vector components to the position elements of the
5831	 * given transformation matrix.
5832	 *
5833	 * @param {Matrix4} m - The 4x4 matrix.
5834	 * @return {Vector3} A reference to this vector.
5835	 */
5836	setFromMatrixPosition( m ) {
5837
5838		const e = m.elements;
5839
5840		this.x = e[ 12 ];
5841		this.y = e[ 13 ];
5842		this.z = e[ 14 ];
5843
5844		return this;
5845
5846	}
5847
5848	/**
5849	 * Sets the vector components to the scale elements of the
5850	 * given transformation matrix.
5851	 *
5852	 * @param {Matrix4} m - The 4x4 matrix.
5853	 * @return {Vector3} A reference to this vector.
5854	 */
5855	setFromMatrixScale( m ) {
5856
5857		const sx = this.setFromMatrixColumn( m, 0 ).length();
5858		const sy = this.setFromMatrixColumn( m, 1 ).length();
5859		const sz = this.setFromMatrixColumn( m, 2 ).length();
5860
5861		this.x = sx;
5862		this.y = sy;
5863		this.z = sz;
5864
5865		return this;
5866
5867	}
5868
5869	/**
5870	 * Sets the vector components from the specified matrix column.
5871	 *
5872	 * @param {Matrix4} m - The 4x4 matrix.
5873	 * @param {number} index - The column index.
5874	 * @return {Vector3} A reference to this vector.
5875	 */
5876	setFromMatrixColumn( m, index ) {
5877
5878		return this.fromArray( m.elements, index * 4 );
5879
5880	}
5881
5882	/**
5883	 * Sets the vector components from the specified matrix column.
5884	 *
5885	 * @param {Matrix3} m - The 3x3 matrix.
5886	 * @param {number} index - The column index.
5887	 * @return {Vector3} A reference to this vector.
5888	 */
5889	setFromMatrix3Column( m, index ) {
5890
5891		return this.fromArray( m.elements, index * 3 );
5892
5893	}
5894
5895	/**
5896	 * Sets the vector components from the given Euler angles.
5897	 *
5898	 * @param {Euler} e - The Euler angles to set.
5899	 * @return {Vector3} A reference to this vector.
5900	 */
5901	setFromEuler( e ) {
5902
5903		this.x = e._x;
5904		this.y = e._y;
5905		this.z = e._z;
5906
5907		return this;
5908
5909	}
5910
5911	/**
5912	 * Sets the vector components from the RGB components of the
5913	 * given color.
5914	 *
5915	 * @param {Color} c - The color to set.
5916	 * @return {Vector3} A reference to this vector.
5917	 */
5918	setFromColor( c ) {
5919
5920		this.x = c.r;
5921		this.y = c.g;
5922		this.z = c.b;
5923
5924		return this;
5925
5926	}
5927
5928	/**
5929	 * Returns `true` if this vector is equal with the given one.
5930	 *
5931	 * @param {Vector3} v - The vector to test for equality.
5932	 * @return {boolean} Whether this vector is equal with the given one.
5933	 */
5934	equals( v ) {
5935
5936		return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) );
5937
5938	}
5939
5940	/**
5941	 * Sets this vector's x value to be `array[ offset ]`, y value to be `array[ offset + 1 ]`
5942	 * and z value to be `array[ offset + 2 ]`.
5943	 *
5944	 * @param {Array<number>} array - An array holding the vector component values.
5945	 * @param {number} [offset=0] - The offset into the array.
5946	 * @return {Vector3} A reference to this vector.
5947	 */
5948	fromArray( array, offset = 0 ) {
5949
5950		this.x = array[ offset ];
5951		this.y = array[ offset + 1 ];
5952		this.z = array[ offset + 2 ];
5953
5954		return this;
5955
5956	}
5957
5958	/**
5959	 * Writes the components of this vector to the given array. If no array is provided,
5960	 * the method returns a new instance.
5961	 *
5962	 * @param {Array<number>} [array=[]] - The target array holding the vector components.
5963	 * @param {number} [offset=0] - Index of the first element in the array.
5964	 * @return {Array<number>} The vector components.
5965	 */
5966	toArray( array = [], offset = 0 ) {
5967
5968		array[ offset ] = this.x;
5969		array[ offset + 1 ] = this.y;
5970		array[ offset + 2 ] = this.z;
5971
5972		return array;
5973
5974	}
5975
5976	/**
5977	 * Sets the components of this vector from the given buffer attribute.
5978	 *
5979	 * @param {BufferAttribute} attribute - The buffer attribute holding vector data.
5980	 * @param {number} index - The index into the attribute.
5981	 * @return {Vector3} A reference to this vector.
5982	 */
5983	fromBufferAttribute( attribute, index ) {
5984
5985		this.x = attribute.getX( index );
5986		this.y = attribute.getY( index );
5987		this.z = attribute.getZ( index );
5988
5989		return this;
5990
5991	}
5992
5993	/**
5994	 * Sets each component of this vector to a pseudo-random value between `0` and
5995	 * `1`, excluding `1`.
5996	 *
5997	 * @return {Vector3} A reference to this vector.
5998	 */
5999	random() {
6000
6001		this.x = Math.random();
6002		this.y = Math.random();
6003		this.z = Math.random();
6004
6005		return this;
6006
6007	}
6008
6009	/**
6010	 * Sets this vector to a uniformly random point on a unit sphere.
6011	 *
6012	 * @return {Vector3} A reference to this vector.
6013	 */
6014	randomDirection() {
6015
6016		// https://mathworld.wolfram.com/SpherePointPicking.html
6017
6018		const theta = Math.random() * Math.PI * 2;
6019		const u = Math.random() * 2 - 1;
6020		const c = Math.sqrt( 1 - u * u );
6021
6022		this.x = c * Math.cos( theta );
6023		this.y = u;
6024		this.z = c * Math.sin( theta );
6025
6026		return this;
6027
6028	}
6029
6030	*[ Symbol.iterator ]() {
6031
6032		yield this.x;
6033		yield this.y;
6034		yield this.z;
6035
6036	}
6037
6038}
6039
6040const _vector$c = /*@__PURE__*/ new Vector3();
6041const _quaternion$5 = /*@__PURE__*/ new Quaternion();
6042
6043/**
6044 * Represents a 3x3 matrix.
6045 *
6046 * A Note on Row-Major and Column-Major Ordering:
6047 *
6048 * The constructor and {@link Matrix3#set} method take arguments in
6049 * [row-major](https://en.wikipedia.org/wiki/Row-_and_column-major_order#Column-major_order)
6050 * order, while internally they are stored in the {@link Matrix3#elements} array in column-major order.
6051 * This means that calling:
6052 * ```js
6053 * const m = new THREE.Matrix();
6054 * m.set( 11, 12, 13,
6055 *        21, 22, 23,
6056 *        31, 32, 33 );
6057 * ```
6058 * will result in the elements array containing:
6059 * ```js
6060 * m.elements = [ 11, 21, 31,
6061 *                12, 22, 32,
6062 *                13, 23, 33 ];
6063 * ```
6064 * and internally all calculations are performed using column-major ordering.
6065 * However, as the actual ordering makes no difference mathematically and
6066 * most people are used to thinking about matrices in row-major order, the
6067 * three.js documentation shows matrices in row-major order. Just bear in
6068 * mind that if you are reading the source code, you'll have to take the
6069 * transpose of any matrices outlined here to make sense of the calculations.
6070 */
6071class Matrix3 {
6072
6073	static {
6074
6075		/**
6076		 * This flag can be used for type testing.
6077		 *
6078		 * @type {boolean}
6079		 * @readonly
6080		 * @default true
6081		 */
6082		Matrix3.prototype.isMatrix3 = true;
6083
6084	}
6085
6086	/**
6087	 * Constructs a new 3x3 matrix. The arguments are supposed to be
6088	 * in row-major order. If no arguments are provided, the constructor
6089	 * initializes the matrix as an identity matrix.
6090	 *
6091	 * @param {number} [n11] - 1-1 matrix element.
6092	 * @param {number} [n12] - 1-2 matrix element.
6093	 * @param {number} [n13] - 1-3 matrix element.
6094	 * @param {number} [n21] - 2-1 matrix element.
6095	 * @param {number} [n22] - 2-2 matrix element.
6096	 * @param {number} [n23] - 2-3 matrix element.
6097	 * @param {number} [n31] - 3-1 matrix element.
6098	 * @param {number} [n32] - 3-2 matrix element.
6099	 * @param {number} [n33] - 3-3 matrix element.
6100	 */
6101	constructor( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) {
6102
6103		/**
6104		 * A column-major list of matrix values.
6105		 *
6106		 * @type {Array<number>}
6107		 */
6108		this.elements = [
6109
6110			1, 0, 0,
6111			0, 1, 0,
6112			0, 0, 1
6113
6114		];
6115
6116		if ( n11 !== undefined ) {
6117
6118			this.set( n11, n12, n13, n21, n22, n23, n31, n32, n33 );
6119
6120		}
6121
6122	}
6123
6124	/**
6125	 * Sets the elements of the matrix.The arguments are supposed to be
6126	 * in row-major order.
6127	 *
6128	 * @param {number} [n11] - 1-1 matrix element.
6129	 * @param {number} [n12] - 1-2 matrix element.
6130	 * @param {number} [n13] - 1-3 matrix element.
6131	 * @param {number} [n21] - 2-1 matrix element.
6132	 * @param {number} [n22] - 2-2 matrix element.
6133	 * @param {number} [n23] - 2-3 matrix element.
6134	 * @param {number} [n31] - 3-1 matrix element.
6135	 * @param {number} [n32] - 3-2 matrix element.
6136	 * @param {number} [n33] - 3-3 matrix element.
6137	 * @return {Matrix3} A reference to this matrix.
6138	 */
6139	set( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) {
6140
6141		const te = this.elements;
6142
6143		te[ 0 ] = n11; te[ 1 ] = n21; te[ 2 ] = n31;
6144		te[ 3 ] = n12; te[ 4 ] = n22; te[ 5 ] = n32;
6145		te[ 6 ] = n13; te[ 7 ] = n23; te[ 8 ] = n33;
6146
6147		return this;
6148
6149	}
6150
6151	/**
6152	 * Sets this matrix to the 3x3 identity matrix.
6153	 *
6154	 * @return {Matrix3} A reference to this matrix.
6155	 */
6156	identity() {
6157
6158		this.set(
6159
6160			1, 0, 0,
6161			0, 1, 0,
6162			0, 0, 1
6163
6164		);
6165
6166		return this;
6167
6168	}
6169
6170	/**
6171	 * Copies the values of the given matrix to this instance.
6172	 *
6173	 * @param {Matrix3} m - The matrix to copy.
6174	 * @return {Matrix3} A reference to this matrix.
6175	 */
6176	copy( m ) {
6177
6178		const te = this.elements;
6179		const me = m.elements;
6180
6181		te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ];
6182		te[ 3 ] = me[ 3 ]; te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ];
6183		te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ]; te[ 8 ] = me[ 8 ];
6184
6185		return this;
6186
6187	}
6188
6189	/**
6190	 * Extracts the basis of this matrix into the three axis vectors provided.
6191	 *
6192	 * @param {Vector3} xAxis - The basis's x axis.
6193	 * @param {Vector3} yAxis - The basis's y axis.
6194	 * @param {Vector3} zAxis - The basis's z axis.
6195	 * @return {Matrix3} A reference to this matrix.
6196	 */
6197	extractBasis( xAxis, yAxis, zAxis ) {
6198
6199		xAxis.setFromMatrix3Column( this, 0 );
6200		yAxis.setFromMatrix3Column( this, 1 );
6201		zAxis.setFromMatrix3Column( this, 2 );
6202
6203		return this;
6204
6205	}
6206
6207	/**
6208	 * Set this matrix to the upper 3x3 matrix of the given 4x4 matrix.
6209	 *
6210	 * @param {Matrix4} m - The 4x4 matrix.
6211	 * @return {Matrix3} A reference to this matrix.
6212	 */
6213	setFromMatrix4( m ) {
6214
6215		const me = m.elements;
6216
6217		this.set(
6218
6219			me[ 0 ], me[ 4 ], me[ 8 ],
6220			me[ 1 ], me[ 5 ], me[ 9 ],
6221			me[ 2 ], me[ 6 ], me[ 10 ]
6222
6223		);
6224
6225		return this;
6226
6227	}
6228
6229	/**
6230	 * Post-multiplies this matrix by the given 3x3 matrix.
6231	 *
6232	 * @param {Matrix3} m - The matrix to multiply with.
6233	 * @return {Matrix3} A reference to this matrix.
6234	 */
6235	multiply( m ) {
6236
6237		return this.multiplyMatrices( this, m );
6238
6239	}
6240
6241	/**
6242	 * Pre-multiplies this matrix by the given 3x3 matrix.
6243	 *
6244	 * @param {Matrix3} m - The matrix to multiply with.
6245	 * @return {Matrix3} A reference to this matrix.
6246	 */
6247	premultiply( m ) {
6248
6249		return this.multiplyMatrices( m, this );
6250
6251	}
6252
6253	/**
6254	 * Multiples the given 3x3 matrices and stores the result
6255	 * in this matrix.
6256	 *
6257	 * @param {Matrix3} a - The first matrix.
6258	 * @param {Matrix3} b - The second matrix.
6259	 * @return {Matrix3} A reference to this matrix.
6260	 */
6261	multiplyMatrices( a, b ) {
6262
6263		const ae = a.elements;
6264		const be = b.elements;
6265		const te = this.elements;
6266
6267		const a11 = ae[ 0 ], a12 = ae[ 3 ], a13 = ae[ 6 ];
6268		const a21 = ae[ 1 ], a22 = ae[ 4 ], a23 = ae[ 7 ];
6269		const a31 = ae[ 2 ], a32 = ae[ 5 ], a33 = ae[ 8 ];
6270
6271		const b11 = be[ 0 ], b12 = be[ 3 ], b13 = be[ 6 ];
6272		const b21 = be[ 1 ], b22 = be[ 4 ], b23 = be[ 7 ];
6273		const b31 = be[ 2 ], b32 = be[ 5 ], b33 = be[ 8 ];
6274
6275		te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31;
6276		te[ 3 ] = a11 * b12 + a12 * b22 + a13 * b32;
6277		te[ 6 ] = a11 * b13 + a12 * b23 + a13 * b33;
6278
6279		te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31;
6280		te[ 4 ] = a21 * b12 + a22 * b22 + a23 * b32;
6281		te[ 7 ] = a21 * b13 + a22 * b23 + a23 * b33;
6282
6283		te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31;
6284		te[ 5 ] = a31 * b12 + a32 * b22 + a33 * b32;
6285		te[ 8 ] = a31 * b13 + a32 * b23 + a33 * b33;
6286
6287		return this;
6288
6289	}
6290
6291	/**
6292	 * Multiplies every component of the matrix by the given scalar.
6293	 *
6294	 * @param {number} s - The scalar.
6295	 * @return {Matrix3} A reference to this matrix.
6296	 */
6297	multiplyScalar( s ) {
6298
6299		const te = this.elements;
6300
6301		te[ 0 ] *= s; te[ 3 ] *= s; te[ 6 ] *= s;
6302		te[ 1 ] *= s; te[ 4 ] *= s; te[ 7 ] *= s;
6303		te[ 2 ] *= s; te[ 5 ] *= s; te[ 8 ] *= s;
6304
6305		return this;
6306
6307	}
6308
6309	/**
6310	 * Computes and returns the determinant of this matrix.
6311	 *
6312	 * @return {number} The determinant.
6313	 */
6314	determinant() {
6315
6316		const te = this.elements;
6317
6318		const a = te[ 0 ], b = te[ 1 ], c = te[ 2 ],
6319			d = te[ 3 ], e = te[ 4 ], f = te[ 5 ],
6320			g = te[ 6 ], h = te[ 7 ], i = te[ 8 ];
6321
6322		return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g;
6323
6324	}
6325
6326	/**
6327	 * Inverts this matrix, using the [analytic method](https://en.wikipedia.org/wiki/Invertible_matrix#Analytic_solution).
6328	 * You can not invert with a determinant of zero. If you attempt this, the method produces
6329	 * a zero matrix instead.
6330	 *
6331	 * @return {Matrix3} A reference to this matrix.
6332	 */
6333	invert() {
6334
6335		const te = this.elements,
6336
6337			n11 = te[ 0 ], n21 = te[ 1 ], n31 = te[ 2 ],
6338			n12 = te[ 3 ], n22 = te[ 4 ], n32 = te[ 5 ],
6339			n13 = te[ 6 ], n23 = te[ 7 ], n33 = te[ 8 ],
6340
6341			t11 = n33 * n22 - n32 * n23,
6342			t12 = n32 * n13 - n33 * n12,
6343			t13 = n23 * n12 - n22 * n13,
6344
6345			det = n11 * t11 + n21 * t12 + n31 * t13;
6346
6347		if ( det === 0 ) return this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0 );
6348
6349		const detInv = 1 / det;
6350
6351		te[ 0 ] = t11 * detInv;
6352		te[ 1 ] = ( n31 * n23 - n33 * n21 ) * detInv;
6353		te[ 2 ] = ( n32 * n21 - n31 * n22 ) * detInv;
6354
6355		te[ 3 ] = t12 * detInv;
6356		te[ 4 ] = ( n33 * n11 - n31 * n13 ) * detInv;
6357		te[ 5 ] = ( n31 * n12 - n32 * n11 ) * detInv;
6358
6359		te[ 6 ] = t13 * detInv;
6360		te[ 7 ] = ( n21 * n13 - n23 * n11 ) * detInv;
6361		te[ 8 ] = ( n22 * n11 - n21 * n12 ) * detInv;
6362
6363		return this;
6364
6365	}
6366
vendor: 16,024 bytes, lines 6367-7092
6367	/**
6368	 * Transposes this matrix in place.
6369	 *
6370	 * @return {Matrix3} A reference to this matrix.
6371	 */
6372	transpose() {
6373
6374		let tmp;
6375		const m = this.elements;
6376
6377		tmp = m[ 1 ]; m[ 1 ] = m[ 3 ]; m[ 3 ] = tmp;
6378		tmp = m[ 2 ]; m[ 2 ] = m[ 6 ]; m[ 6 ] = tmp;
6379		tmp = m[ 5 ]; m[ 5 ] = m[ 7 ]; m[ 7 ] = tmp;
6380
6381		return this;
6382
6383	}
6384
6385	/**
6386	 * Computes the normal matrix which is the inverse transpose of the upper
6387	 * left 3x3 portion of the given 4x4 matrix.
6388	 *
6389	 * @param {Matrix4} matrix4 - The 4x4 matrix.
6390	 * @return {Matrix3} A reference to this matrix.
6391	 */
6392	getNormalMatrix( matrix4 ) {
6393
6394		return this.setFromMatrix4( matrix4 ).invert().transpose();
6395
6396	}
6397
6398	/**
6399	 * Transposes this matrix into the supplied array, and returns itself unchanged.
6400	 *
6401	 * @param {Array<number>} r - An array to store the transposed matrix elements.
6402	 * @return {Matrix3} A reference to this matrix.
6403	 */
6404	transposeIntoArray( r ) {
6405
6406		const m = this.elements;
6407
6408		r[ 0 ] = m[ 0 ];
6409		r[ 1 ] = m[ 3 ];
6410		r[ 2 ] = m[ 6 ];
6411		r[ 3 ] = m[ 1 ];
6412		r[ 4 ] = m[ 4 ];
6413		r[ 5 ] = m[ 7 ];
6414		r[ 6 ] = m[ 2 ];
6415		r[ 7 ] = m[ 5 ];
6416		r[ 8 ] = m[ 8 ];
6417
6418		return this;
6419
6420	}
6421
6422	/**
6423	 * Sets the UV transform matrix from offset, repeat, rotation, and center.
6424	 *
6425	 * @param {number} tx - Offset x.
6426	 * @param {number} ty - Offset y.
6427	 * @param {number} sx - Repeat x.
6428	 * @param {number} sy - Repeat y.
6429	 * @param {number} rotation - Rotation, in radians. Positive values rotate counterclockwise.
6430	 * @param {number} cx - Center x of rotation.
6431	 * @param {number} cy - Center y of rotation
6432	 * @return {Matrix3} A reference to this matrix.
6433	 */
6434	setUvTransform( tx, ty, sx, sy, rotation, cx, cy ) {
6435
6436		const c = Math.cos( rotation );
6437		const s = Math.sin( rotation );
6438
6439		this.set(
6440			sx * c, sx * s, - sx * ( c * cx + s * cy ) + cx + tx,
6441			- sy * s, sy * c, - sy * ( - s * cx + c * cy ) + cy + ty,
6442			0, 0, 1
6443		);
6444
6445		return this;
6446
6447	}
6448
6449	/**
6450	 * Scales this matrix with the given scalar values.
6451	 *
6452	 * @param {number} sx - The amount to scale in the X axis.
6453	 * @param {number} sy - The amount to scale in the Y axis.
6454	 * @return {Matrix3} A reference to this matrix.
6455	 */
6456	scale( sx, sy ) {
6457
6458		this.premultiply( _m3.makeScale( sx, sy ) );
6459
6460		return this;
6461
6462	}
6463
6464	/**
6465	 * Rotates this matrix by the given angle.
6466	 *
6467	 * @param {number} theta - The rotation in radians.
6468	 * @return {Matrix3} A reference to this matrix.
6469	 */
6470	rotate( theta ) {
6471
6472		this.premultiply( _m3.makeRotation( - theta ) );
6473
6474		return this;
6475
6476	}
6477
6478	/**
6479	 * Translates this matrix by the given scalar values.
6480	 *
6481	 * @param {number} tx - The amount to translate in the X axis.
6482	 * @param {number} ty - The amount to translate in the Y axis.
6483	 * @return {Matrix3} A reference to this matrix.
6484	 */
6485	translate( tx, ty ) {
6486
6487		this.premultiply( _m3.makeTranslation( tx, ty ) );
6488
6489		return this;
6490
6491	}
6492
6493	// for 2D Transforms
6494
6495	/**
6496	 * Sets this matrix as a 2D translation transform.
6497	 *
6498	 * @param {number|Vector2} x - The amount to translate in the X axis or alternatively a translation vector.
6499	 * @param {number} y - The amount to translate in the Y axis.
6500	 * @return {Matrix3} A reference to this matrix.
6501	 */
6502	makeTranslation( x, y ) {
6503
6504		if ( x.isVector2 ) {
6505
6506			this.set(
6507
6508				1, 0, x.x,
6509				0, 1, x.y,
6510				0, 0, 1
6511
6512			);
6513
6514		} else {
6515
6516			this.set(
6517
6518				1, 0, x,
6519				0, 1, y,
6520				0, 0, 1
6521
6522			);
6523
6524		}
6525
6526		return this;
6527
6528	}
6529
6530	/**
6531	 * Sets this matrix as a 2D rotational transformation.
6532	 *
6533	 * @param {number} theta - The rotation in radians.
6534	 * @return {Matrix3} A reference to this matrix.
6535	 */
6536	makeRotation( theta ) {
6537
6538		// counterclockwise
6539
6540		const c = Math.cos( theta );
6541		const s = Math.sin( theta );
6542
6543		this.set(
6544
6545			c, - s, 0,
6546			s, c, 0,
6547			0, 0, 1
6548
6549		);
6550
6551		return this;
6552
6553	}
6554
6555	/**
6556	 * Sets this matrix as a 2D scale transform.
6557	 *
6558	 * @param {number} x - The amount to scale in the X axis.
6559	 * @param {number} y - The amount to scale in the Y axis.
6560	 * @return {Matrix3} A reference to this matrix.
6561	 */
6562	makeScale( x, y ) {
6563
6564		this.set(
6565
6566			x, 0, 0,
6567			0, y, 0,
6568			0, 0, 1
6569
6570		);
6571
6572		return this;
6573
6574	}
6575
6576	/**
6577	 * Returns `true` if this matrix is equal with the given one.
6578	 *
6579	 * @param {Matrix3} matrix - The matrix to test for equality.
6580	 * @return {boolean} Whether this matrix is equal with the given one.
6581	 */
6582	equals( matrix ) {
6583
6584		const te = this.elements;
6585		const me = matrix.elements;
6586
6587		for ( let i = 0; i < 9; i ++ ) {
6588
6589			if ( te[ i ] !== me[ i ] ) return false;
6590
6591		}
6592
6593		return true;
6594
6595	}
6596
6597	/**
6598	 * Sets the elements of the matrix from the given array.
6599	 *
6600	 * @param {Array<number>} array - The matrix elements in column-major order.
6601	 * @param {number} [offset=0] - Index of the first element in the array.
6602	 * @return {Matrix3} A reference to this matrix.
6603	 */
6604	fromArray( array, offset = 0 ) {
6605
6606		for ( let i = 0; i < 9; i ++ ) {
6607
6608			this.elements[ i ] = array[ i + offset ];
6609
6610		}
6611
6612		return this;
6613
6614	}
6615
6616	/**
6617	 * Writes the elements of this matrix to the given array. If no array is provided,
6618	 * the method returns a new instance.
6619	 *
6620	 * @param {Array<number>} [array=[]] - The target array holding the matrix elements in column-major order.
6621	 * @param {number} [offset=0] - Index of the first element in the array.
6622	 * @return {Array<number>} The matrix elements in column-major order.
6623	 */
6624	toArray( array = [], offset = 0 ) {
6625
6626		const te = this.elements;
6627
6628		array[ offset ] = te[ 0 ];
6629		array[ offset + 1 ] = te[ 1 ];
6630		array[ offset + 2 ] = te[ 2 ];
6631
6632		array[ offset + 3 ] = te[ 3 ];
6633		array[ offset + 4 ] = te[ 4 ];
6634		array[ offset + 5 ] = te[ 5 ];
6635
6636		array[ offset + 6 ] = te[ 6 ];
6637		array[ offset + 7 ] = te[ 7 ];
6638		array[ offset + 8 ] = te[ 8 ];
6639
6640		return array;
6641
6642	}
6643
6644	/**
6645	 * Returns a matrix with copied values from this instance.
6646	 *
6647	 * @return {Matrix3} A clone of this instance.
6648	 */
6649	clone() {
6650
6651		return new this.constructor().fromArray( this.elements );
6652
6653	}
6654
6655}
6656
6657const _m3 = /*@__PURE__*/ new Matrix3();
6658
6659const LINEAR_REC709_TO_XYZ = /*@__PURE__*/ new Matrix3().set(
6660	0.4123908, 0.3575843, 0.1804808,
6661	0.2126390, 0.7151687, 0.0721923,
6662	0.0193308, 0.1191948, 0.9505322
6663);
6664
6665const XYZ_TO_LINEAR_REC709 = /*@__PURE__*/ new Matrix3().set(
6666	3.2409699, -1.5373832, -0.4986108,
6667	-0.9692436, 1.8759675, 0.0415551,
6668	0.0556301, -0.203977, 1.0569715
6669);
6670
6671function createColorManagement() {
6672
6673	const ColorManagement = {
6674
6675		enabled: true,
6676
6677		workingColorSpace: LinearSRGBColorSpace,
6678
6679		/**
6680		 * Implementations of supported color spaces.
6681		 *
6682		 * Required:
6683		 *	- primaries: chromaticity coordinates [ rx ry gx gy bx by ]
6684		 *	- whitePoint: reference white [ x y ]
6685		 *	- transfer: transfer function (pre-defined)
6686		 *	- toXYZ: Matrix3 RGB to XYZ transform
6687		 *	- fromXYZ: Matrix3 XYZ to RGB transform
6688		 *	- luminanceCoefficients: RGB luminance coefficients
6689		 *
6690		 * Optional:
6691		 *  - outputColorSpaceConfig: { drawingBufferColorSpace: ColorSpace, toneMappingMode: 'extended' | 'standard' }
6692		 *  - workingColorSpaceConfig: { unpackColorSpace: ColorSpace }
6693		 *
6694		 * Reference:
6695		 * - https://www.russellcottrell.com/photo/matrixCalculator.htm
6696		 */
6697		spaces: {},
6698
6699		convert: function ( color, sourceColorSpace, targetColorSpace ) {
6700
6701			if ( this.enabled === false || sourceColorSpace === targetColorSpace || ! sourceColorSpace || ! targetColorSpace ) {
6702
6703				return color;
6704
6705			}
6706
6707			if ( this.spaces[ sourceColorSpace ].transfer === SRGBTransfer ) {
6708
6709				color.r = SRGBToLinear( color.r );
6710				color.g = SRGBToLinear( color.g );
6711				color.b = SRGBToLinear( color.b );
6712
6713			}
6714
6715			if ( this.spaces[ sourceColorSpace ].primaries !== this.spaces[ targetColorSpace ].primaries ) {
6716
6717				color.applyMatrix3( this.spaces[ sourceColorSpace ].toXYZ );
6718				color.applyMatrix3( this.spaces[ targetColorSpace ].fromXYZ );
6719
6720			}
6721
6722			if ( this.spaces[ targetColorSpace ].transfer === SRGBTransfer ) {
6723
6724				color.r = LinearToSRGB( color.r );
6725				color.g = LinearToSRGB( color.g );
6726				color.b = LinearToSRGB( color.b );
6727
6728			}
6729
6730			return color;
6731
6732		},
6733
6734		workingToColorSpace: function ( color, targetColorSpace ) {
6735
6736			return this.convert( color, this.workingColorSpace, targetColorSpace );
6737
6738		},
6739
6740		colorSpaceToWorking: function ( color, sourceColorSpace ) {
6741
6742			return this.convert( color, sourceColorSpace, this.workingColorSpace );
6743
6744		},
6745
6746		getPrimaries: function ( colorSpace ) {
6747
6748			return this.spaces[ colorSpace ].primaries;
6749
6750		},
6751
6752		getTransfer: function ( colorSpace ) {
6753
6754			if ( colorSpace === NoColorSpace ) return LinearTransfer;
6755
6756			return this.spaces[ colorSpace ].transfer;
6757
6758		},
6759
6760		getToneMappingMode: function ( colorSpace ) {
6761
6762			return this.spaces[ colorSpace ].outputColorSpaceConfig.toneMappingMode || 'standard';
6763
6764		},
6765
6766		getLuminanceCoefficients: function ( target, colorSpace = this.workingColorSpace ) {
6767
6768			return target.fromArray( this.spaces[ colorSpace ].luminanceCoefficients );
6769
6770		},
6771
6772		define: function ( colorSpaces ) {
6773
6774			Object.assign( this.spaces, colorSpaces );
6775
6776		},
6777
6778		// Internal APIs
6779
6780		_getMatrix: function ( targetMatrix, sourceColorSpace, targetColorSpace ) {
6781
6782			return targetMatrix
6783				.copy( this.spaces[ sourceColorSpace ].toXYZ )
6784				.multiply( this.spaces[ targetColorSpace ].fromXYZ );
6785
6786		},
6787
6788		_getDrawingBufferColorSpace: function ( colorSpace ) {
6789
6790			return this.spaces[ colorSpace ].outputColorSpaceConfig.drawingBufferColorSpace;
6791
6792		},
6793
6794		_getUnpackColorSpace: function ( colorSpace = this.workingColorSpace ) {
6795
6796			return this.spaces[ colorSpace ].workingColorSpaceConfig.unpackColorSpace;
6797
6798		},
6799
6800		// Deprecated
6801
6802		fromWorkingColorSpace: function ( color, targetColorSpace ) {
6803
6804			warnOnce( 'ColorManagement: .fromWorkingColorSpace() has been renamed to .workingToColorSpace().' ); // @deprecated, r177
6805
6806			return ColorManagement.workingToColorSpace( color, targetColorSpace );
6807
6808		},
6809
6810		toWorkingColorSpace: function ( color, sourceColorSpace ) {
6811
6812			warnOnce( 'ColorManagement: .toWorkingColorSpace() has been renamed to .colorSpaceToWorking().' ); // @deprecated, r177
6813
6814			return ColorManagement.colorSpaceToWorking( color, sourceColorSpace );
6815
6816		},
6817
6818	};
6819
6820	/******************************************************************************
6821	 * sRGB definitions
6822	 */
6823
6824	const REC709_PRIMARIES = [ 0.640, 0.330, 0.300, 0.600, 0.150, 0.060 ];
6825	const REC709_LUMINANCE_COEFFICIENTS = [ 0.2126, 0.7152, 0.0722 ];
6826	const D65 = [ 0.3127, 0.3290 ];
6827
6828	ColorManagement.define( {
6829
6830		[ LinearSRGBColorSpace ]: {
6831			primaries: REC709_PRIMARIES,
6832			whitePoint: D65,
6833			transfer: LinearTransfer,
6834			toXYZ: LINEAR_REC709_TO_XYZ,
6835			fromXYZ: XYZ_TO_LINEAR_REC709,
6836			luminanceCoefficients: REC709_LUMINANCE_COEFFICIENTS,
6837			workingColorSpaceConfig: { unpackColorSpace: SRGBColorSpace },
6838			outputColorSpaceConfig: { drawingBufferColorSpace: SRGBColorSpace }
6839		},
6840
6841		[ SRGBColorSpace ]: {
6842			primaries: REC709_PRIMARIES,
6843			whitePoint: D65,
6844			transfer: SRGBTransfer,
6845			toXYZ: LINEAR_REC709_TO_XYZ,
6846			fromXYZ: XYZ_TO_LINEAR_REC709,
6847			luminanceCoefficients: REC709_LUMINANCE_COEFFICIENTS,
6848			outputColorSpaceConfig: { drawingBufferColorSpace: SRGBColorSpace }
6849		},
6850
6851	} );
6852
6853	return ColorManagement;
6854
6855}
6856
6857const ColorManagement = /*@__PURE__*/ createColorManagement();
6858
6859function SRGBToLinear( c ) {
6860
6861	return ( c < 0.04045 ) ? c * 0.0773993808 : Math.pow( c * 0.9478672986 + 0.0521327014, 2.4 );
6862
6863}
6864
6865function LinearToSRGB( c ) {
6866
6867	return ( c < 0.0031308 ) ? c * 12.92 : 1.055 * ( Math.pow( c, 0.41666 ) ) - 0.055;
6868
6869}
6870
6871let _canvas;
6872
6873/**
6874 * A class containing utility functions for images.
6875 *
6876 * @hideconstructor
6877 */
6878class ImageUtils {
6879
6880	/**
6881	 * Returns a data URI containing a representation of the given image.
6882	 *
6883	 * @param {(HTMLImageElement|HTMLCanvasElement)} image - The image object.
6884	 * @param {string} [type='image/png'] - Indicates the image format.
6885	 * @return {string} The data URI.
6886	 */
6887	static getDataURL( image, type = 'image/png' ) {
6888
6889		if ( /^data:/i.test( image.src ) ) {
6890
6891			return image.src;
6892
6893		}
6894
6895		if ( typeof HTMLCanvasElement === 'undefined' ) {
6896
6897			return image.src;
6898
6899		}
6900
6901		let canvas;
6902
6903		if ( image instanceof HTMLCanvasElement ) {
6904
6905			canvas = image;
6906
6907		} else {
6908
6909			if ( _canvas === undefined ) _canvas = createElementNS( 'canvas' );
6910
6911			_canvas.width = image.width;
6912			_canvas.height = image.height;
6913
6914			const context = _canvas.getContext( '2d' );
6915
6916			if ( image instanceof ImageData ) {
6917
6918				context.putImageData( image, 0, 0 );
6919
6920			} else {
6921
6922				context.drawImage( image, 0, 0, image.width, image.height );
6923
6924			}
6925
6926			canvas = _canvas;
6927
6928		}
6929
6930		return canvas.toDataURL( type );
6931
6932	}
6933
6934	/**
6935	 * Converts the given sRGB image data to linear color space.
6936	 *
6937	 * @param {(HTMLImageElement|HTMLCanvasElement|ImageBitmap|Object)} image - The image object.
6938	 * @return {HTMLCanvasElement|Object} The converted image.
6939	 */
6940	static sRGBToLinear( image ) {
6941
6942		if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) ||
6943			( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) ||
6944			( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) {
6945
6946			const canvas = createElementNS( 'canvas' );
6947
6948			canvas.width = image.width;
6949			canvas.height = image.height;
6950
6951			const context = canvas.getContext( '2d' );
6952			context.drawImage( image, 0, 0, image.width, image.height );
6953
6954			const imageData = context.getImageData( 0, 0, image.width, image.height );
6955			const data = imageData.data;
6956
6957			for ( let i = 0; i < data.length; i ++ ) {
6958
6959				data[ i ] = SRGBToLinear( data[ i ] / 255 ) * 255;
6960
6961			}
6962
6963			context.putImageData( imageData, 0, 0 );
6964
6965			return canvas;
6966
6967		} else if ( image.data ) {
6968
6969			const data = image.data.slice( 0 );
6970
6971			for ( let i = 0; i < data.length; i ++ ) {
6972
6973				if ( data instanceof Uint8Array || data instanceof Uint8ClampedArray ) {
6974
6975					data[ i ] = Math.floor( SRGBToLinear( data[ i ] / 255 ) * 255 );
6976
6977				} else {
6978
6979					// assuming float
6980
6981					data[ i ] = SRGBToLinear( data[ i ] );
6982
6983				}
6984
6985			}
6986
6987			return {
6988				data: data,
6989				width: image.width,
6990				height: image.height
6991			};
6992
6993		} else {
6994
6995			warn( 'ImageUtils.sRGBToLinear(): Unsupported image type. No color space conversion applied.' );
6996			return image;
6997
6998		}
6999
7000	}
7001
7002}
7003
7004let _sourceId = 0;
7005
7006/**
7007 * Represents the data source of a texture.
7008 *
7009 * The main purpose of this class is to decouple the data definition from the texture
7010 * definition so the same data can be used with multiple texture instances.
7011 */
7012class Source {
7013
7014	/**
7015	 * Constructs a new video texture.
7016	 *
7017	 * @param {any} [data=null] - The data definition of a texture.
7018	 */
7019	constructor( data = null ) {
7020
7021		/**
7022		 * This flag can be used for type testing.
7023		 *
7024		 * @type {boolean}
7025		 * @readonly
7026		 * @default true
7027		 */
7028		this.isSource = true;
7029
7030		/**
7031		 * The ID of the source.
7032		 *
7033		 * @name Source#id
7034		 * @type {number}
7035		 * @readonly
7036		 */
7037		Object.defineProperty( this, 'id', { value: _sourceId ++ } );
7038
7039		/**
7040		 * The UUID of the source.
7041		 *
7042		 * @type {string}
7043		 * @readonly
7044		 */
7045		this.uuid = generateUUID();
7046
7047		/**
7048		 * The data definition of a texture.
7049		 *
7050		 * @type {any}
7051		 */
7052		this.data = data;
7053
7054		/**
7055		 * This property is only relevant when {@link Source#needsUpdate} is set to `true` and
7056		 * provides more control on how texture data should be processed. When `dataReady` is set
7057		 * to `false`, the engine performs the memory allocation (if necessary) but does not transfer
7058		 * the data into the GPU memory.
7059		 *
7060		 * @type {boolean}
7061		 * @default true
7062		 */
7063		this.dataReady = true;
7064
7065		/**
7066		 * This starts at `0` and counts how many times {@link Source#needsUpdate} is set to `true`.
7067		 *
7068		 * @type {number}
7069		 * @readonly
7070		 * @default 0
7071		 */
7072		this.version = 0;
7073
7074	}
7075
7076	/**
7077	 * Returns the dimensions of the source into the given target vector.
7078	 *
7079	 * @param {(Vector2|Vector3)} target - The target object the result is written into.
7080	 * @return {(Vector2|Vector3)} The dimensions of the source.
7081	 */
7082	getSize( target ) {
7083
7084		const data = this.data;
7085
7086		if ( ( typeof HTMLVideoElement !== 'undefined' ) && ( data instanceof HTMLVideoElement ) ) {
7087
7088			target.set( data.videoWidth, data.videoHeight, 0 );
7089
7090		} else if ( ( typeof VideoFrame !== 'undefined' ) && ( data instanceof VideoFrame ) ) {
7091
7092			target.set( data.display
vendor: 2,595 bytes, lines 7092-7240
7092Width, data.displayHeight, 0 );
7093
7094		} else if ( data !== null ) {
7095
7096			target.set( data.width, data.height, data.depth || 0 );
7097
7098		} else {
7099
7100			target.set( 0, 0, 0 );
7101
7102		}
7103
7104		return target;
7105
7106	}
7107
7108	/**
7109	 * When the property is set to `true`, the engine allocates the memory
7110	 * for the texture (if necessary) and triggers the actual texture upload
7111	 * to the GPU next time the source is used.
7112	 *
7113	 * @type {boolean}
7114	 * @default false
7115	 * @param {boolean} value
7116	 */
7117	set needsUpdate( value ) {
7118
7119		if ( value === true ) this.version ++;
7120
7121	}
7122
7123	/**
7124	 * Serializes the source into JSON.
7125	 *
7126	 * @param {?(Object|string)} meta - An optional value holding meta information about the serialization.
7127	 * @return {Object} A JSON object representing the serialized source.
7128	 * @see {@link ObjectLoader#parse}
7129	 */
7130	toJSON( meta ) {
7131
7132		const isRootObject = ( meta === undefined || typeof meta === 'string' );
7133
7134		if ( ! isRootObject && meta.images[ this.uuid ] !== undefined ) {
7135
7136			return meta.images[ this.uuid ];
7137
7138		}
7139
7140		const output = {
7141			uuid: this.uuid,
7142			url: ''
7143		};
7144
7145		const data = this.data;
7146
7147		if ( data !== null ) {
7148
7149			let url;
7150
7151			if ( Array.isArray( data ) ) {
7152
7153				// cube texture
7154
7155				url = [];
7156
7157				for ( let i = 0, l = data.length; i < l; i ++ ) {
7158
7159					if ( data[ i ].isDataTexture ) {
7160
7161						url.push( serializeImage( data[ i ].image ) );
7162
7163					} else {
7164
7165						url.push( serializeImage( data[ i ] ) );
7166
7167					}
7168
7169				}
7170
7171			} else {
7172
7173				// texture
7174
7175				url = serializeImage( data );
7176
7177			}
7178
7179			output.url = url;
7180
7181		}
7182
7183		if ( ! isRootObject ) {
7184
7185			meta.images[ this.uuid ] = output;
7186
7187		}
7188
7189		return output;
7190
7191	}
7192
7193}
7194
7195function serializeImage( image ) {
7196
7197	if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) ||
7198		( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) ||
7199		( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) {
7200
7201		// default images
7202
7203		return ImageUtils.getDataURL( image );
7204
7205	} else {
7206
7207		if ( image.data ) {
7208
7209			// images of DataTexture
7210
7211			return {
7212				data: Array.from( image.data ),
7213				width: image.width,
7214				height: image.height,
7215				type: image.data.constructor.name
7216			};
7217
7218		} else {
7219
7220			warn( 'Texture: Unable to serialize Texture.' );
7221			return {};
7222
7223		}
7224
7225	}
7226
7227}
7228
7229let _textureId = 0;
7230
7231const _tempVec3 = /*@__PURE__*/ new Vector3();
7232
7233/**
7234 * Base class for all textures.
7235 *
7236 * Note: After the initial use of a texture, its dimensions, format, and type
7237 * cannot be changed. Instead, call {@link Texture#dispose} on the texture and instantiate a new one.
7238 *
7239 * @augments EventDispatcher
7240 */
vendor: 6,879 bytes, lines 7241-7478
7241class Texture extends EventDispatcher {
7242
7243	/**
7244	 * Constructs a new texture.
7245	 *
7246	 * @param {?Object} [image=Texture.DEFAULT_IMAGE] - The image holding the texture data.
7247	 * @param {number} [mapping=Texture.DEFAULT_MAPPING] - The texture mapping.
7248	 * @param {number} [wrapS=ClampToEdgeWrapping] - The wrapS value.
7249	 * @param {number} [wrapT=ClampToEdgeWrapping] - The wrapT value.
7250	 * @param {number} [magFilter=LinearFilter] - The mag filter value.
7251	 * @param {number} [minFilter=LinearMipmapLinearFilter] - The min filter value.
7252	 * @param {number} [format=RGBAFormat] - The texture format.
7253	 * @param {number} [type=UnsignedByteType] - The texture type.
7254	 * @param {number} [anisotropy=Texture.DEFAULT_ANISOTROPY] - The anisotropy value.
7255	 * @param {string} [colorSpace=NoColorSpace] - The color space.
7256	 */
7257	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 ) {
7258
7259		super();
7260
7261		/**
7262		 * This flag can be used for type testing.
7263		 *
7264		 * @type {boolean}
7265		 * @readonly
7266		 * @default true
7267		 */
7268		this.isTexture = true;
7269
7270		/**
7271		 * The ID of the texture.
7272		 *
7273		 * @name Texture#id
7274		 * @type {number}
7275		 * @readonly
7276		 */
7277		Object.defineProperty( this, 'id', { value: _textureId ++ } );
7278
7279		/**
7280		 * The UUID of the texture.
7281		 *
7282		 * @type {string}
7283		 * @readonly
7284		 */
7285		this.uuid = generateUUID();
7286
7287		/**
7288		 * The name of the texture.
7289		 *
7290		 * @type {string}
7291		 */
7292		this.name = '';
7293
7294		/**
7295		 * The data definition of a texture. A reference to the data source can be
7296		 * shared across textures. This is often useful in context of spritesheets
7297		 * where multiple textures render the same data but with different texture
7298		 * transformations.
7299		 *
7300		 * @type {Source}
7301		 */
7302		this.source = new Source( image );
7303
7304		/**
7305		 * An array holding user-defined mipmaps.
7306		 *
7307		 * @type {Array<Object>}
7308		 */
7309		this.mipmaps = [];
7310
7311		/**
7312		 * How the texture is applied to the object. The value `UVMapping`
7313		 * is the default, where texture or uv coordinates are used to apply the map.
7314		 *
7315		 * @type {(UVMapping|CubeReflectionMapping|CubeRefractionMapping|EquirectangularReflectionMapping|EquirectangularRefractionMapping|CubeUVReflectionMapping)}
7316		 * @default UVMapping
7317		*/
7318		this.mapping = mapping;
7319
7320		/**
7321		 * Lets you select the uv attribute to map the texture to. `0` for `uv`,
7322		 * `1` for `uv1`, `2` for `uv2` and `3` for `uv3`.
7323		 *
7324		 * @type {number}
7325		 * @default 0
7326		 */
7327		this.channel = 0;
7328
7329		/**
7330		 * This defines how the texture is wrapped horizontally and corresponds to
7331		 * *U* in UV mapping.
7332		 *
7333		 * @type {(RepeatWrapping|ClampToEdgeWrapping|MirroredRepeatWrapping)}
7334		 * @default ClampToEdgeWrapping
7335		 */
7336		this.wrapS = wrapS;
7337
7338		/**
7339		 * This defines how the texture is wrapped horizontally and corresponds to
7340		 * *V* in UV mapping.
7341		 *
7342		 * @type {(RepeatWrapping|ClampToEdgeWrapping|MirroredRepeatWrapping)}
7343		 * @default ClampToEdgeWrapping
7344		 */
7345		this.wrapT = wrapT;
7346
7347		/**
7348		 * How the texture is sampled when a texel covers more than one pixel.
7349		 *
7350		 * @type {(NearestFilter|NearestMipmapNearestFilter|NearestMipmapLinearFilter|LinearFilter|LinearMipmapNearestFilter|LinearMipmapLinearFilter)}
7351		 * @default LinearFilter
7352		 */
7353		this.magFilter = magFilter;
7354
7355		/**
7356		 * How the texture is sampled when a texel covers less than one pixel.
7357		 *
7358		 * @type {(NearestFilter|NearestMipmapNearestFilter|NearestMipmapLinearFilter|LinearFilter|LinearMipmapNearestFilter|LinearMipmapLinearFilter)}
7359		 * @default LinearMipmapLinearFilter
7360		 */
7361		this.minFilter = minFilter;
7362
7363		/**
7364		 * The number of samples taken along the axis through the pixel that has the
7365		 * highest density of texels. By default, this value is `1`. A higher value
7366		 * gives a less blurry result than a basic mipmap, at the cost of more
7367		 * texture samples being used.
7368		 *
7369		 * @type {number}
7370		 * @default Texture.DEFAULT_ANISOTROPY
7371		 */
7372		this.anisotropy = anisotropy;
7373
7374		/**
7375		 * The format of the texture.
7376		 *
7377		 * @type {number}
7378		 * @default RGBAFormat
7379		 */
7380		this.format = format;
7381
7382		/**
7383		 * The default internal format is derived from {@link Texture#format} and {@link Texture#type} and
7384		 * defines how the texture data is going to be stored on the GPU.
7385		 *
7386		 * This property allows to overwrite the default format.
7387		 *
7388		 * @type {?string}
7389		 * @default null
7390		 */
7391		this.internalFormat = null;
7392
7393		/**
7394		 * The data type of the texture.
7395		 *
7396		 * @type {number}
7397		 * @default UnsignedByteType
7398		 */
7399		this.type = type;
7400
7401		/**
7402		 * How much a single repetition of the texture is offset from the beginning,
7403		 * in each direction U and V. Typical range is `0.0` to `1.0`.
7404		 *
7405		 * @type {Vector2}
7406		 * @default (0,0)
7407		 */
7408		this.offset = new Vector2( 0, 0 );
7409
7410		/**
7411		 * How many times the texture is repeated across the surface, in each
7412		 * direction U and V. If repeat is set greater than `1` in either direction,
7413		 * the corresponding wrap parameter should also be set to `RepeatWrapping`
7414		 * or `MirroredRepeatWrapping` to achieve the desired tiling effect.
7415		 *
7416		 * @type {Vector2}
7417		 * @default (1,1)
7418		 */
7419		this.repeat = new Vector2( 1, 1 );
7420
7421		/**
7422		 * The point around which rotation occurs. A value of `(0.5, 0.5)` corresponds
7423		 * to the center of the texture. Default is `(0, 0)`, the lower left.
7424		 *
7425		 * @type {Vector2}
7426		 * @default (0,0)
7427		 */
7428		this.center = new Vector2( 0, 0 );
7429
7430		/**
7431		 * How much the texture is rotated around the center point, in radians.
7432		 * Positive values are counter-clockwise.
7433		 *
7434		 * @type {number}
7435		 * @default 0
7436		 */
7437		this.rotation = 0;
7438
7439		/**
7440		 * Whether to update the texture's uv-transformation {@link Texture#matrix}
7441		 * from the properties {@link Texture#offset}, {@link Texture#repeat},
7442		 * {@link Texture#rotation}, and {@link Texture#center}.
7443		 *
7444		 * Set this to `false` if you are specifying the uv-transform matrix directly.
7445		 *
7446		 * @type {boolean}
7447		 * @default true
7448		 */
7449		this.matrixAutoUpdate = true;
7450
7451		/**
7452		 * The uv-transformation matrix of the texture.
7453		 *
7454		 * @type {Matrix3}
7455		 */
7456		this.matrix = new Matrix3();
7457
7458		/**
7459		 * Whether to generate mipmaps (if possible) for a texture.
7460		 *
7461		 * Set this to `false` if you are creating mipmaps manually.
7462		 *
7463		 * @type {boolean}
7464		 * @default true
7465		 */
7466		this.generateMipmaps = true;
7467
7468		/**
7469		 * If set to `true`, the alpha channel, if present, is multiplied into the
7470		 * color channels when the texture is uploaded to the GPU.
7471		 *
7472		 * Note that this property has no effect when using `ImageBitmap`. You need to
7473		 * configure premultiply alpha on bitmap creation instead.
7474		 *
7475		 * @type {boolean}
7476		 * @default false
7477		 */
7478		this.premultiplyAlpha = false;
vendor: 15,080 bytes, lines 7479-8243
7479
7480		/**
7481		 * If set to `true`, the texture is flipped along the vertical axis when
7482		 * uploaded to the GPU.
7483		 *
7484		 * Note that this property has no effect when using `ImageBitmap`. You need to
7485		 * configure the flip on bitmap creation instead.
7486		 *
7487		 * @type {boolean}
7488		 * @default true
7489		 */
7490		this.flipY = true;
7491
7492		/**
7493		 * Specifies the alignment requirements for the start of each pixel row in memory.
7494		 * The allowable values are `1` (byte-alignment), `2` (rows aligned to even-numbered bytes),
7495		 * `4` (word-alignment), and `8` (rows start on double-word boundaries).
7496		 *
7497		 * @type {number}
7498		 * @default 4
7499		 */
7500		this.unpackAlignment = 4;	// valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml)
7501
7502		/**
7503		 * Textures containing color data should be annotated with `SRGBColorSpace` or `LinearSRGBColorSpace`.
7504		 *
7505		 * @type {string}
7506		 * @default NoColorSpace
7507		 */
7508		this.colorSpace = colorSpace;
7509
7510		/**
7511		 * An object that can be used to store custom data about the texture. It
7512		 * should not hold references to functions as these will not be cloned.
7513		 *
7514		 * @type {Object}
7515		 */
7516		this.userData = {};
7517
7518		/**
7519		 * This can be used to only update a subregion or specific rows of the texture (for example, just the
7520		 * first 3 rows). Use the `addUpdateRange()` function to add ranges to this array.
7521		 *
7522		 * @type {Array<Object>}
7523		 */
7524		this.updateRanges = [];
7525
7526		/**
7527		 * This starts at `0` and counts how many times {@link Texture#needsUpdate} is set to `true`.
7528		 *
7529		 * @type {number}
7530		 * @readonly
7531		 * @default 0
7532		 */
7533		this.version = 0;
7534
7535		/**
7536		 * A callback function, called when the texture is updated (e.g., when
7537		 * {@link Texture#needsUpdate} has been set to true and then the texture is used).
7538		 *
7539		 * @type {?Function}
7540		 * @default null
7541		 */
7542		this.onUpdate = null;
7543
7544		/**
7545		 * An optional back reference to the textures render target.
7546		 *
7547		 * @type {?(RenderTarget|WebGLRenderTarget)}
7548		 * @default null
7549		 */
7550		this.renderTarget = null;
7551
7552		/**
7553		 * Indicates whether a texture belongs to a render target or not.
7554		 *
7555		 * @type {boolean}
7556		 * @readonly
7557		 * @default false
7558		 */
7559		this.isRenderTargetTexture = false;
7560
7561		/**
7562		 * Indicates if a texture should be handled like a texture array.
7563		 *
7564		 * @type {boolean}
7565		 * @readonly
7566		 * @default false
7567		 */
7568		this.isArrayTexture = image && image.depth && image.depth > 1 ? true : false;
7569
7570		/**
7571		 * Indicates whether this texture should be processed by `PMREMGenerator` or not
7572		 * (only relevant for render target textures).
7573		 *
7574		 * @type {number}
7575		 * @readonly
7576		 * @default 0
7577		 */
7578		this.pmremVersion = 0;
7579
7580		/**
7581		 * Whether the texture should use one of the 16 bit integer formats which are normalized
7582		 * to [0, 1] or [-1, 1] (depending on signed/unsigned) when sampled.
7583		 *
7584		 * @type {boolean}
7585		 * @default false
7586		 */
7587		this.normalized = false;
7588
7589	}
7590
7591	/**
7592	 * The width of the texture in pixels.
7593	 */
7594	get width() {
7595
7596		return this.source.getSize( _tempVec3 ).x;
7597
7598	}
7599
7600	/**
7601	 * The height of the texture in pixels.
7602	 */
7603	get height() {
7604
7605		return this.source.getSize( _tempVec3 ).y;
7606
7607	}
7608
7609	/**
7610	 * The depth of the texture in pixels.
7611	 */
7612	get depth() {
7613
7614		return this.source.getSize( _tempVec3 ).z;
7615
7616	}
7617
7618	/**
7619	 * The image object holding the texture data.
7620	 *
7621	 * @type {?Object}
7622	 */
7623	get image() {
7624
7625		return this.source.data;
7626
7627	}
7628
7629	set image( value ) {
7630
7631		this.source.data = value;
7632
7633	}
7634
7635	/**
7636	 * Updates the texture transformation matrix from the properties {@link Texture#offset},
7637	 * {@link Texture#repeat}, {@link Texture#rotation}, and {@link Texture#center}.
7638	 */
7639	updateMatrix() {
7640
7641		this.matrix.setUvTransform( this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y );
7642
7643	}
7644
7645	/**
7646	 * Adds a range of data in the data texture to be updated on the GPU.
7647	 *
7648	 * @param {number} start - Position at which to start update.
7649	 * @param {number} count - The number of components to update.
7650	 */
7651	addUpdateRange( start, count ) {
7652
7653		this.updateRanges.push( { start, count } );
7654
7655	}
7656
7657	/**
7658	 * Clears the update ranges.
7659	 */
7660	clearUpdateRanges() {
7661
7662		this.updateRanges.length = 0;
7663
7664	}
7665
7666	/**
7667	 * Returns a new texture with copied values from this instance.
7668	 *
7669	 * @return {Texture} A clone of this instance.
7670	 */
7671	clone() {
7672
7673		return new this.constructor().copy( this );
7674
7675	}
7676
7677	/**
7678	 * Copies the values of the given texture to this instance.
7679	 *
7680	 * @param {Texture} source - The texture to copy.
7681	 * @return {Texture} A reference to this instance.
7682	 */
7683	copy( source ) {
7684
7685		this.name = source.name;
7686
7687		this.source = source.source;
7688		this.mipmaps = source.mipmaps.slice( 0 );
7689
7690		this.mapping = source.mapping;
7691		this.channel = source.channel;
7692
7693		this.wrapS = source.wrapS;
7694		this.wrapT = source.wrapT;
7695
7696		this.magFilter = source.magFilter;
7697		this.minFilter = source.minFilter;
7698
7699		this.anisotropy = source.anisotropy;
7700
7701		this.format = source.format;
7702		this.internalFormat = source.internalFormat;
7703		this.type = source.type;
7704		this.normalized = source.normalized;
7705
7706		this.offset.copy( source.offset );
7707		this.repeat.copy( source.repeat );
7708		this.center.copy( source.center );
7709		this.rotation = source.rotation;
7710
7711		this.matrixAutoUpdate = source.matrixAutoUpdate;
7712		this.matrix.copy( source.matrix );
7713
7714		this.generateMipmaps = source.generateMipmaps;
7715		this.premultiplyAlpha = source.premultiplyAlpha;
7716		this.flipY = source.flipY;
7717		this.unpackAlignment = source.unpackAlignment;
7718		this.colorSpace = source.colorSpace;
7719
7720		this.renderTarget = source.renderTarget;
7721		this.isRenderTargetTexture = source.isRenderTargetTexture;
7722		this.isArrayTexture = source.isArrayTexture;
7723
7724		this.userData = JSON.parse( JSON.stringify( source.userData ) );
7725
7726		this.needsUpdate = true;
7727
7728		return this;
7729
7730	}
7731
7732	/**
7733	 * Sets this texture's properties based on `values`.
7734	 * @param {Object} values - A container with texture parameters.
7735	 */
7736	setValues( values ) {
7737
7738		for ( const key in values ) {
7739
7740			const newValue = values[ key ];
7741
7742			if ( newValue === undefined ) {
7743
7744				warn( `Texture.setValues(): parameter '${ key }' has value of undefined.` );
7745				continue;
7746
7747			}
7748
7749			const currentValue = this[ key ];
7750
7751			if ( currentValue === undefined ) {
7752
7753				warn( `Texture.setValues(): property '${ key }' does not exist.` );
7754				continue;
7755
7756			}
7757
7758			if ( ( currentValue && newValue ) && ( currentValue.isVector2 && newValue.isVector2 ) ) {
7759
7760				currentValue.copy( newValue );
7761
7762			} else if ( ( currentValue && newValue ) && ( currentValue.isVector3 && newValue.isVector3 ) ) {
7763
7764				currentValue.copy( newValue );
7765
7766			} else if ( ( currentValue && newValue ) && ( currentValue.isMatrix3 && newValue.isMatrix3 ) ) {
7767
7768				currentValue.copy( newValue );
7769
7770			} else {
7771
7772				this[ key ] = newValue;
7773
7774			}
7775
7776		}
7777
7778	}
7779
7780	/**
7781	 * Serializes the texture into JSON.
7782	 *
7783	 * @param {?(Object|string)} meta - An optional value holding meta information about the serialization.
7784	 * @return {Object} A JSON object representing the serialized texture.
7785	 * @see {@link ObjectLoader#parse}
7786	 */
7787	toJSON( meta ) {
7788
7789		const isRootObject = ( meta === undefined || typeof meta === 'string' );
7790
7791		if ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) {
7792
7793			return meta.textures[ this.uuid ];
7794
7795		}
7796
7797		const output = {
7798
7799			metadata: {
7800				version: 4.7,
7801				type: 'Texture',
7802				generator: 'Texture.toJSON'
7803			},
7804
7805			uuid: this.uuid,
7806			name: this.name,
7807
7808			image: this.source.toJSON( meta ).uuid,
7809
7810			mapping: this.mapping,
7811			channel: this.channel,
7812
7813			repeat: [ this.repeat.x, this.repeat.y ],
7814			offset: [ this.offset.x, this.offset.y ],
7815			center: [ this.center.x, this.center.y ],
7816			rotation: this.rotation,
7817
7818			wrap: [ this.wrapS, this.wrapT ],
7819
7820			format: this.format,
7821			internalFormat: this.internalFormat,
7822			type: this.type,
7823			normalized: this.normalized,
7824			colorSpace: this.colorSpace,
7825
7826			minFilter: this.minFilter,
7827			magFilter: this.magFilter,
7828			anisotropy: this.anisotropy,
7829
7830			flipY: this.flipY,
7831
7832			generateMipmaps: this.generateMipmaps,
7833			premultiplyAlpha: this.premultiplyAlpha,
7834			unpackAlignment: this.unpackAlignment
7835
7836		};
7837
7838		if ( Object.keys( this.userData ).length > 0 ) output.userData = this.userData;
7839
7840		if ( ! isRootObject ) {
7841
7842			meta.textures[ this.uuid ] = output;
7843
7844		}
7845
7846		return output;
7847
7848	}
7849
7850	/**
7851	 * Frees the GPU-related resources allocated by this instance. Call this
7852	 * method whenever this instance is no longer used in your app.
7853	 *
7854	 * @fires Texture#dispose
7855	 */
7856	dispose() {
7857
7858		/**
7859		 * Fires when the texture has been disposed of.
7860		 *
7861		 * @event Texture#dispose
7862		 * @type {Object}
7863		 */
7864		this.dispatchEvent( { type: 'dispose' } );
7865
7866	}
7867
7868	/**
7869	 * Transforms the given uv vector with the textures uv transformation matrix.
7870	 *
7871	 * @param {Vector2} uv - The uv vector.
7872	 * @return {Vector2} The transformed uv vector.
7873	 */
7874	transformUv( uv ) {
7875
7876		if ( this.mapping !== UVMapping ) return uv;
7877
7878		uv.applyMatrix3( this.matrix );
7879
7880		if ( uv.x < 0 || uv.x > 1 ) {
7881
7882			switch ( this.wrapS ) {
7883
7884				case RepeatWrapping:
7885
7886					uv.x = uv.x - Math.floor( uv.x );
7887					break;
7888
7889				case ClampToEdgeWrapping:
7890
7891					uv.x = uv.x < 0 ? 0 : 1;
7892					break;
7893
7894				case MirroredRepeatWrapping:
7895
7896					if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) {
7897
7898						uv.x = Math.ceil( uv.x ) - uv.x;
7899
7900					} else {
7901
7902						uv.x = uv.x - Math.floor( uv.x );
7903
7904					}
7905
7906					break;
7907
7908			}
7909
7910		}
7911
7912		if ( uv.y < 0 || uv.y > 1 ) {
7913
7914			switch ( this.wrapT ) {
7915
7916				case RepeatWrapping:
7917
7918					uv.y = uv.y - Math.floor( uv.y );
7919					break;
7920
7921				case ClampToEdgeWrapping:
7922
7923					uv.y = uv.y < 0 ? 0 : 1;
7924					break;
7925
7926				case MirroredRepeatWrapping:
7927
7928					if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) {
7929
7930						uv.y = Math.ceil( uv.y ) - uv.y;
7931
7932					} else {
7933
7934						uv.y = uv.y - Math.floor( uv.y );
7935
7936					}
7937
7938					break;
7939
7940			}
7941
7942		}
7943
7944		if ( this.flipY ) {
7945
7946			uv.y = 1 - uv.y;
7947
7948		}
7949
7950		return uv;
7951
7952	}
7953
7954	/**
7955	 * Setting this property to `true` indicates the engine the texture
7956	 * must be updated in the next render. This triggers a texture upload
7957	 * to the GPU and ensures correct texture parameter configuration.
7958	 *
7959	 * @type {boolean}
7960	 * @default false
7961	 * @param {boolean} value
7962	 */
7963	set needsUpdate( value ) {
7964
7965		if ( value === true ) {
7966
7967			this.version ++;
7968			this.source.needsUpdate = true;
7969
7970		}
7971
7972	}
7973
7974	/**
7975	 * Setting this property to `true` indicates the engine the PMREM
7976	 * must be regenerated.
7977	 *
7978	 * @type {boolean}
7979	 * @default false
7980	 * @param {boolean} value
7981	 */
7982	set needsPMREMUpdate( value ) {
7983
7984		if ( value === true ) {
7985
7986			this.pmremVersion ++;
7987
7988		}
7989
7990	}
7991
7992}
7993
7994/**
7995 * The default image for all textures.
7996 *
7997 * @static
7998 * @type {?Image}
7999 * @default null
8000 */
8001Texture.DEFAULT_IMAGE = null;
8002
8003/**
8004 * The default mapping for all textures.
8005 *
8006 * @static
8007 * @type {number}
8008 * @default UVMapping
8009 */
8010Texture.DEFAULT_MAPPING = UVMapping;
8011
8012/**
8013 * The default anisotropy value for all textures.
8014 *
8015 * @static
8016 * @type {number}
8017 * @default 1
8018 */
8019Texture.DEFAULT_ANISOTROPY = 1;
8020
8021/**
8022 * Class representing a 4D vector. A 4D vector is an ordered quadruplet of numbers
8023 * (labeled x, y, z and w), which can be used to represent a number of things, such as:
8024 *
8025 * - A point in 4D space.
8026 * - A direction and length in 4D space. In three.js the length will
8027 * always be the Euclidean distance(straight-line distance) from `(0, 0, 0, 0)` to `(x, y, z, w)`
8028 * and the direction is also measured from `(0, 0, 0, 0)` towards `(x, y, z, w)`.
8029 * - Any arbitrary ordered quadruplet of numbers.
8030 *
8031 * There are other things a 4D vector can be used to represent, however these
8032 * are the most common uses in *three.js*.
8033 *
8034 * Iterating through a vector instance will yield its components `(x, y, z, w)` in
8035 * the corresponding order.
8036 * ```js
8037 * const a = new THREE.Vector4( 0, 1, 0, 0 );
8038 *
8039 * //no arguments; will be initialised to (0, 0, 0, 1)
8040 * const b = new THREE.Vector4( );
8041 *
8042 * const d = a.dot( b );
8043 * ```
8044 */
8045class Vector4 {
8046
8047	static {
8048
8049		/**
8050		 * This flag can be used for type testing.
8051		 *
8052		 * @type {boolean}
8053		 * @readonly
8054		 * @default true
8055		 */
8056		Vector4.prototype.isVector4 = true;
8057
8058	}
8059
8060	/**
8061	 * Constructs a new 4D vector.
8062	 *
8063	 * @param {number} [x=0] - The x value of this vector.
8064	 * @param {number} [y=0] - The y value of this vector.
8065	 * @param {number} [z=0] - The z value of this vector.
8066	 * @param {number} [w=1] - The w value of this vector.
8067	 */
8068	constructor( x = 0, y = 0, z = 0, w = 1 ) {
8069
8070		/**
8071		 * The x value of this vector.
8072		 *
8073		 * @type {number}
8074		 */
8075		this.x = x;
8076
8077		/**
8078		 * The y value of this vector.
8079		 *
8080		 * @type {number}
8081		 */
8082		this.y = y;
8083
8084		/**
8085		 * The z value of this vector.
8086		 *
8087		 * @type {number}
8088		 */
8089		this.z = z;
8090
8091		/**
8092		 * The w value of this vector.
8093		 *
8094		 * @type {number}
8095		 */
8096		this.w = w;
8097
8098	}
8099
8100	/**
8101	 * Alias for {@link Vector4#z}.
8102	 *
8103	 * @type {number}
8104	 */
8105	get width() {
8106
8107		return this.z;
8108
8109	}
8110
8111	set width( value ) {
8112
8113		this.z = value;
8114
8115	}
8116
8117	/**
8118	 * Alias for {@link Vector4#w}.
8119	 *
8120	 * @type {number}
8121	 */
8122	get height() {
8123
8124		return this.w;
8125
8126	}
8127
8128	set height( value ) {
8129
8130		this.w = value;
8131
8132	}
8133
8134	/**
8135	 * Sets the vector components.
8136	 *
8137	 * @param {number} x - The value of the x component.
8138	 * @param {number} y - The value of the y component.
8139	 * @param {number} z - The value of the z component.
8140	 * @param {number} w - The value of the w component.
8141	 * @return {Vector4} A reference to this vector.
8142	 */
8143	set( x, y, z, w ) {
8144
8145		this.x = x;
8146		this.y = y;
8147		this.z = z;
8148		this.w = w;
8149
8150		return this;
8151
8152	}
8153
8154	/**
8155	 * Sets the vector components to the same value.
8156	 *
8157	 * @param {number} scalar - The value to set for all vector components.
8158	 * @return {Vector4} A reference to this vector.
8159	 */
8160	setScalar( scalar ) {
8161
8162		this.x = scalar;
8163		this.y = scalar;
8164		this.z = scalar;
8165		this.w = scalar;
8166
8167		return this;
8168
8169	}
8170
8171	/**
8172	 * Sets the vector's x component to the given value
8173	 *
8174	 * @param {number} x - The value to set.
8175	 * @return {Vector4} A reference to this vector.
8176	 */
8177	setX( x ) {
8178
8179		this.x = x;
8180
8181		return this;
8182
8183	}
8184
8185	/**
8186	 * Sets the vector's y component to the given value
8187	 *
8188	 * @param {number} y - The value to set.
8189	 * @return {Vector4} A reference to this vector.
8190	 */
8191	setY( y ) {
8192
8193		this.y = y;
8194
8195		return this;
8196
8197	}
8198
8199	/**
8200	 * Sets the vector's z component to the given value
8201	 *
8202	 * @param {number} z - The value to set.
8203	 * @return {Vector4} A reference to this vector.
8204	 */
8205	setZ( z ) {
8206
8207		this.z = z;
8208
8209		return this;
8210
8211	}
8212
8213	/**
8214	 * Sets the vector's w component to the given value
8215	 *
8216	 * @param {number} w - The value to set.
8217	 * @return {Vector4} A reference to this vector.
8218	 */
8219	setW( w ) {
8220
8221		this.w = w;
8222
8223		return this;
8224
8225	}
8226
8227	/**
8228	 * Allows to set a vector component with an index.
8229	 *
8230	 * @param {number} index - The component index. `0` equals to x, `1` equals to y,
8231	 * `2` equals to z, `3` equals to w.
8232	 * @param {number} value - The value to set.
8233	 * @return {Vector4} A reference to this vector.
8234	 */
8235	setComponent( index, value ) {
8236
8237		switch ( index ) {
8238
8239			case 0: this.x = value; break;
8240			case 1: this.y = value; break;
8241			case 2: this.z = value; break;
8242			case 3: this.w = value; break;
8243			default: throw new Error( '
vendor: 10,358 bytes, lines 8243-8747
8243index is out of range: ' + index );
8244
8245		}
8246
8247		return this;
8248
8249	}
8250
8251	/**
8252	 * Returns the value of the vector component which matches the given index.
8253	 *
8254	 * @param {number} index - The component index. `0` equals to x, `1` equals to y,
8255	 * `2` equals to z, `3` equals to w.
8256	 * @return {number} A vector component value.
8257	 */
8258	getComponent( index ) {
8259
8260		switch ( index ) {
8261
8262			case 0: return this.x;
8263			case 1: return this.y;
8264			case 2: return this.z;
8265			case 3: return this.w;
8266			default: throw new Error( 'index is out of range: ' + index );
8267
8268		}
8269
8270	}
8271
8272	/**
8273	 * Returns a new vector with copied values from this instance.
8274	 *
8275	 * @return {Vector4} A clone of this instance.
8276	 */
8277	clone() {
8278
8279		return new this.constructor( this.x, this.y, this.z, this.w );
8280
8281	}
8282
8283	/**
8284	 * Copies the values of the given vector to this instance.
8285	 *
8286	 * @param {Vector3|Vector4} v - The vector to copy.
8287	 * @return {Vector4} A reference to this vector.
8288	 */
8289	copy( v ) {
8290
8291		this.x = v.x;
8292		this.y = v.y;
8293		this.z = v.z;
8294		this.w = ( v.w !== undefined ) ? v.w : 1;
8295
8296		return this;
8297
8298	}
8299
8300	/**
8301	 * Adds the given vector to this instance.
8302	 *
8303	 * @param {Vector4} v - The vector to add.
8304	 * @return {Vector4} A reference to this vector.
8305	 */
8306	add( v ) {
8307
8308		this.x += v.x;
8309		this.y += v.y;
8310		this.z += v.z;
8311		this.w += v.w;
8312
8313		return this;
8314
8315	}
8316
8317	/**
8318	 * Adds the given scalar value to all components of this instance.
8319	 *
8320	 * @param {number} s - The scalar to add.
8321	 * @return {Vector4} A reference to this vector.
8322	 */
8323	addScalar( s ) {
8324
8325		this.x += s;
8326		this.y += s;
8327		this.z += s;
8328		this.w += s;
8329
8330		return this;
8331
8332	}
8333
8334	/**
8335	 * Adds the given vectors and stores the result in this instance.
8336	 *
8337	 * @param {Vector4} a - The first vector.
8338	 * @param {Vector4} b - The second vector.
8339	 * @return {Vector4} A reference to this vector.
8340	 */
8341	addVectors( a, b ) {
8342
8343		this.x = a.x + b.x;
8344		this.y = a.y + b.y;
8345		this.z = a.z + b.z;
8346		this.w = a.w + b.w;
8347
8348		return this;
8349
8350	}
8351
8352	/**
8353	 * Adds the given vector scaled by the given factor to this instance.
8354	 *
8355	 * @param {Vector4} v - The vector.
8356	 * @param {number} s - The factor that scales `v`.
8357	 * @return {Vector4} A reference to this vector.
8358	 */
8359	addScaledVector( v, s ) {
8360
8361		this.x += v.x * s;
8362		this.y += v.y * s;
8363		this.z += v.z * s;
8364		this.w += v.w * s;
8365
8366		return this;
8367
8368	}
8369
8370	/**
8371	 * Subtracts the given vector from this instance.
8372	 *
8373	 * @param {Vector4} v - The vector to subtract.
8374	 * @return {Vector4} A reference to this vector.
8375	 */
8376	sub( v ) {
8377
8378		this.x -= v.x;
8379		this.y -= v.y;
8380		this.z -= v.z;
8381		this.w -= v.w;
8382
8383		return this;
8384
8385	}
8386
8387	/**
8388	 * Subtracts the given scalar value from all components of this instance.
8389	 *
8390	 * @param {number} s - The scalar to subtract.
8391	 * @return {Vector4} A reference to this vector.
8392	 */
8393	subScalar( s ) {
8394
8395		this.x -= s;
8396		this.y -= s;
8397		this.z -= s;
8398		this.w -= s;
8399
8400		return this;
8401
8402	}
8403
8404	/**
8405	 * Subtracts the given vectors and stores the result in this instance.
8406	 *
8407	 * @param {Vector4} a - The first vector.
8408	 * @param {Vector4} b - The second vector.
8409	 * @return {Vector4} A reference to this vector.
8410	 */
8411	subVectors( a, b ) {
8412
8413		this.x = a.x - b.x;
8414		this.y = a.y - b.y;
8415		this.z = a.z - b.z;
8416		this.w = a.w - b.w;
8417
8418		return this;
8419
8420	}
8421
8422	/**
8423	 * Multiplies the given vector with this instance.
8424	 *
8425	 * @param {Vector4} v - The vector to multiply.
8426	 * @return {Vector4} A reference to this vector.
8427	 */
8428	multiply( v ) {
8429
8430		this.x *= v.x;
8431		this.y *= v.y;
8432		this.z *= v.z;
8433		this.w *= v.w;
8434
8435		return this;
8436
8437	}
8438
8439	/**
8440	 * Multiplies the given scalar value with all components of this instance.
8441	 *
8442	 * @param {number} scalar - The scalar to multiply.
8443	 * @return {Vector4} A reference to this vector.
8444	 */
8445	multiplyScalar( scalar ) {
8446
8447		this.x *= scalar;
8448		this.y *= scalar;
8449		this.z *= scalar;
8450		this.w *= scalar;
8451
8452		return this;
8453
8454	}
8455
8456	/**
8457	 * Multiplies this vector with the given 4x4 matrix.
8458	 *
8459	 * @param {Matrix4} m - The 4x4 matrix.
8460	 * @return {Vector4} A reference to this vector.
8461	 */
8462	applyMatrix4( m ) {
8463
8464		const x = this.x, y = this.y, z = this.z, w = this.w;
8465		const e = m.elements;
8466
8467		this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w;
8468		this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w;
8469		this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w;
8470		this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w;
8471
8472		return this;
8473
8474	}
8475
8476	/**
8477	 * Divides this instance by the given vector.
8478	 *
8479	 * @param {Vector4} v - The vector to divide.
8480	 * @return {Vector4} A reference to this vector.
8481	 */
8482	divide( 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	 * Divides this vector by the given scalar.
8495	 *
8496	 * @param {number} scalar - The scalar to divide.
8497	 * @return {Vector4} A reference to this vector.
8498	 */
8499	divideScalar( scalar ) {
8500
8501		return this.multiplyScalar( 1 / scalar );
8502
8503	}
8504
8505	/**
8506	 * Sets the x, y and z components of this
8507	 * vector to the quaternion's axis and w to the angle.
8508	 *
8509	 * @param {Quaternion} q - The Quaternion to set.
8510	 * @return {Vector4} A reference to this vector.
8511	 */
8512	setAxisAngleFromQuaternion( q ) {
8513
8514		// http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm
8515
8516		// q is assumed to be normalized
8517
8518		this.w = 2 * Math.acos( q.w );
8519
8520		const s = Math.sqrt( 1 - q.w * q.w );
8521
8522		if ( s < 0.0001 ) {
8523
8524			this.x = 1;
8525			this.y = 0;
8526			this.z = 0;
8527
8528		} else {
8529
8530			this.x = q.x / s;
8531			this.y = q.y / s;
8532			this.z = q.z / s;
8533
8534		}
8535
8536		return this;
8537
8538	}
8539
8540	/**
8541	 * Sets the x, y and z components of this
8542	 * vector to the axis of rotation and w to the angle.
8543	 *
8544	 * @param {Matrix4} m - A 4x4 matrix of which the upper left 3x3 matrix is a pure rotation matrix.
8545	 * @return {Vector4} A reference to this vector.
8546	 */
8547	setAxisAngleFromRotationMatrix( m ) {
8548
8549		// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm
8550
8551		// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
8552
8553		let angle, x, y, z; // variables for result
8554		const epsilon = 0.01,		// margin to allow for rounding errors
8555			epsilon2 = 0.1,		// margin to distinguish between 0 and 180 degrees
8556
8557			te = m.elements,
8558
8559			m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
8560			m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
8561			m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
8562
8563		if ( ( Math.abs( m12 - m21 ) < epsilon ) &&
8564		     ( Math.abs( m13 - m31 ) < epsilon ) &&
8565		     ( Math.abs( m23 - m32 ) < epsilon ) ) {
8566
8567			// singularity found
8568			// first check for identity matrix which must have +1 for all terms
8569			// in leading diagonal and zero in other terms
8570
8571			if ( ( Math.abs( m12 + m21 ) < epsilon2 ) &&
8572			     ( Math.abs( m13 + m31 ) < epsilon2 ) &&
8573			     ( Math.abs( m23 + m32 ) < epsilon2 ) &&
8574			     ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) {
8575
8576				// this singularity is identity matrix so angle = 0
8577
8578				this.set( 1, 0, 0, 0 );
8579
8580				return this; // zero angle, arbitrary axis
8581
8582			}
8583
8584			// otherwise this singularity is angle = 180
8585
8586			angle = Math.PI;
8587
8588			const xx = ( m11 + 1 ) / 2;
8589			const yy = ( m22 + 1 ) / 2;
8590			const zz = ( m33 + 1 ) / 2;
8591			const xy = ( m12 + m21 ) / 4;
8592			const xz = ( m13 + m31 ) / 4;
8593			const yz = ( m23 + m32 ) / 4;
8594
8595			if ( ( xx > yy ) && ( xx > zz ) ) {
8596
8597				// m11 is the largest diagonal term
8598
8599				if ( xx < epsilon ) {
8600
8601					x = 0;
8602					y = 0.707106781;
8603					z = 0.707106781;
8604
8605				} else {
8606
8607					x = Math.sqrt( xx );
8608					y = xy / x;
8609					z = xz / x;
8610
8611				}
8612
8613			} else if ( yy > zz ) {
8614
8615				// m22 is the largest diagonal term
8616
8617				if ( yy < epsilon ) {
8618
8619					x = 0.707106781;
8620					y = 0;
8621					z = 0.707106781;
8622
8623				} else {
8624
8625					y = Math.sqrt( yy );
8626					x = xy / y;
8627					z = yz / y;
8628
8629				}
8630
8631			} else {
8632
8633				// m33 is the largest diagonal term so base result on this
8634
8635				if ( zz < epsilon ) {
8636
8637					x = 0.707106781;
8638					y = 0.707106781;
8639					z = 0;
8640
8641				} else {
8642
8643					z = Math.sqrt( zz );
8644					x = xz / z;
8645					y = yz / z;
8646
8647				}
8648
8649			}
8650
8651			this.set( x, y, z, angle );
8652
8653			return this; // return 180 deg rotation
8654
8655		}
8656
8657		// as we have reached here there are no singularities so we can handle normally
8658
8659		let s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) +
8660			( m13 - m31 ) * ( m13 - m31 ) +
8661			( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize
8662
8663		if ( Math.abs( s ) < 0.001 ) s = 1;
8664
8665		// prevent divide by zero, should not happen if matrix is orthogonal and should be
8666		// caught by singularity test above, but I've left it in just in case
8667
8668		this.x = ( m32 - m23 ) / s;
8669		this.y = ( m13 - m31 ) / s;
8670		this.z = ( m21 - m12 ) / s;
8671		this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 );
8672
8673		return this;
8674
8675	}
8676
8677	/**
8678	 * Sets the vector components to the position elements of the
8679	 * given transformation matrix.
8680	 *
8681	 * @param {Matrix4} m - The 4x4 matrix.
8682	 * @return {Vector4} A reference to this vector.
8683	 */
8684	setFromMatrixPosition( m ) {
8685
8686		const e = m.elements;
8687
8688		this.x = e[ 12 ];
8689		this.y = e[ 13 ];
8690		this.z = e[ 14 ];
8691		this.w = e[ 15 ];
8692
8693		return this;
8694
8695	}
8696
8697	/**
8698	 * If this vector's x, y, z or w value is greater than the given vector's x, y, z or w
8699	 * value, replace that value with the corresponding min value.
8700	 *
8701	 * @param {Vector4} v - The vector.
8702	 * @return {Vector4} A reference to this vector.
8703	 */
8704	min( v ) {
8705
8706		this.x = Math.min( this.x, v.x );
8707		this.y = Math.min( this.y, v.y );
8708		this.z = Math.min( this.z, v.z );
8709		this.w = Math.min( this.w, v.w );
8710
8711		return this;
8712
8713	}
8714
8715	/**
8716	 * If this vector's x, y, z or w value is less than the given vector's x, y, z or w
8717	 * value, replace that value with the corresponding max value.
8718	 *
8719	 * @param {Vector4} v - The vector.
8720	 * @return {Vector4} A reference to this vector.
8721	 */
8722	max( v ) {
8723
8724		this.x = Math.max( this.x, v.x );
8725		this.y = Math.max( this.y, v.y );
8726		this.z = Math.max( this.z, v.z );
8727		this.w = Math.max( this.w, v.w );
8728
8729		return this;
8730
8731	}
8732
8733	/**
8734	 * If this vector's x, y, z or w value is greater than the max vector's x, y, z or w
8735	 * value, it is replaced by the corresponding value.
8736	 * If this vector's x, y, z or w value is less than the min vector's x, y, z or w value,
8737	 * it is replaced by the corresponding value.
8738	 *
8739	 * @param {Vector4} min - The minimum x, y and z values.
8740	 * @param {Vector4} max - The maximum x, y and z values in the desired range.
8741	 * @return {Vector4} A reference to this vector.
8742	 */
8743	clamp( min, max ) {
8744
8745		// assumes min < max, componentwise
8746
8747		this.x = clamp
8747( this.x, min.x, max.x );
8748		this.y = clamp( this.y, min.y, max.y );
8749		this.z = clamp( this.z, min.z, max.z );
8750		this.w = clamp( this.w, min.w, max.w );
8751
8752		return this;
8753
8754	}
8755
8756	/**
8757	 * If this vector's x, y, z or w values are greater than the max value, they are
8758	 * replaced by the max value.
8759	 * If this vector's x, y, z or w values are less than the min value, they are
8760	 * replaced by the min value.
8761	 *
8762	 * @param {number} minVal - The minimum value the components will be clamped to.
8763	 * @param {number} maxVal - The maximum value the components will be clamped to.
8764	 * @return {Vector4} A reference to this vector.
8765	 */
8766	clampScalar( minVal, maxVal ) {
8767
8768		this.x = clamp( this.x, minVal, maxVal );
8769		this.y = clamp( this.y, minVal, maxVal );
8770		this.z = clamp( this.z, minVal, maxVal );
8771		this.w = clamp( this.w, minVal, maxVal );
8772
8773		return this;
8774
8775	}
8776
8777	/**
8778	 * If this vector's length is greater than the max value, it is replaced by
8779	 * the max value.
8780	 * If this vector's length is less than the min value, it is replaced by the
8781	 * min value.
8782	 *
8783	 * @param {number} min - The minimum value the vector length will be clamped to.
8784	 * @param {number} max - The maximum value the vector length will be clamped to.
8785	 * @return {Vector4} A reference to this vector.
8786	 */
8787	clampLength( min, max ) {
8788
8789		const length = this.length();
8790
8791		return this.divideScalar( length || 1 ).multiplyScalar( clamp
vendor: 16,862 bytes, lines 8791-9449
8791( length, min, max ) );
8792
8793	}
8794
8795	/**
8796	 * The components of this vector are rounded down to the nearest integer value.
8797	 *
8798	 * @return {Vector4} A reference to this vector.
8799	 */
8800	floor() {
8801
8802		this.x = Math.floor( this.x );
8803		this.y = Math.floor( this.y );
8804		this.z = Math.floor( this.z );
8805		this.w = Math.floor( this.w );
8806
8807		return this;
8808
8809	}
8810
8811	/**
8812	 * The components of this vector are rounded up to the nearest integer value.
8813	 *
8814	 * @return {Vector4} A reference to this vector.
8815	 */
8816	ceil() {
8817
8818		this.x = Math.ceil( this.x );
8819		this.y = Math.ceil( this.y );
8820		this.z = Math.ceil( this.z );
8821		this.w = Math.ceil( this.w );
8822
8823		return this;
8824
8825	}
8826
8827	/**
8828	 * The components of this vector are rounded to the nearest integer value
8829	 *
8830	 * @return {Vector4} A reference to this vector.
8831	 */
8832	round() {
8833
8834		this.x = Math.round( this.x );
8835		this.y = Math.round( this.y );
8836		this.z = Math.round( this.z );
8837		this.w = Math.round( this.w );
8838
8839		return this;
8840
8841	}
8842
8843	/**
8844	 * The components of this vector are rounded towards zero (up if negative,
8845	 * down if positive) to an integer value.
8846	 *
8847	 * @return {Vector4} A reference to this vector.
8848	 */
8849	roundToZero() {
8850
8851		this.x = Math.trunc( this.x );
8852		this.y = Math.trunc( this.y );
8853		this.z = Math.trunc( this.z );
8854		this.w = Math.trunc( this.w );
8855
8856		return this;
8857
8858	}
8859
8860	/**
8861	 * Inverts this vector - i.e. sets x = -x, y = -y, z = -z, w = -w.
8862	 *
8863	 * @return {Vector4} A reference to this vector.
8864	 */
8865	negate() {
8866
8867		this.x = - this.x;
8868		this.y = - this.y;
8869		this.z = - this.z;
8870		this.w = - this.w;
8871
8872		return this;
8873
8874	}
8875
8876	/**
8877	 * Calculates the dot product of the given vector with this instance.
8878	 *
8879	 * @param {Vector4} v - The vector to compute the dot product with.
8880	 * @return {number} The result of the dot product.
8881	 */
8882	dot( v ) {
8883
8884		return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;
8885
8886	}
8887
8888	/**
8889	 * Computes the square of the Euclidean length (straight-line length) from
8890	 * (0, 0, 0, 0) to (x, y, z, w). If you are comparing the lengths of vectors, you should
8891	 * compare the length squared instead as it is slightly more efficient to calculate.
8892	 *
8893	 * @return {number} The square length of this vector.
8894	 */
8895	lengthSq() {
8896
8897		return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
8898
8899	}
8900
8901	/**
8902	 * Computes the  Euclidean length (straight-line length) from (0, 0, 0, 0) to (x, y, z, w).
8903	 *
8904	 * @return {number} The length of this vector.
8905	 */
8906	length() {
8907
8908		return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w );
8909
8910	}
8911
8912	/**
8913	 * Computes the Manhattan length of this vector.
8914	 *
8915	 * @return {number} The length of this vector.
8916	 */
8917	manhattanLength() {
8918
8919		return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w );
8920
8921	}
8922
8923	/**
8924	 * Converts this vector to a unit vector - that is, sets it equal to a vector
8925	 * with the same direction as this one, but with a vector length of `1`.
8926	 *
8927	 * @return {Vector4} A reference to this vector.
8928	 */
8929	normalize() {
8930
8931		return this.divideScalar( this.length() || 1 );
8932
8933	}
8934
8935	/**
8936	 * Sets this vector to a vector with the same direction as this one, but
8937	 * with the specified length.
8938	 *
8939	 * @param {number} length - The new length of this vector.
8940	 * @return {Vector4} A reference to this vector.
8941	 */
8942	setLength( length ) {
8943
8944		return this.normalize().multiplyScalar( length );
8945
8946	}
8947
8948	/**
8949	 * Linearly interpolates between the given vector and this instance, where
8950	 * alpha is the percent distance along the line - alpha = 0 will be this
8951	 * vector, and alpha = 1 will be the given one.
8952	 *
8953	 * @param {Vector4} v - The vector to interpolate towards.
8954	 * @param {number} alpha - The interpolation factor, typically in the closed interval `[0, 1]`.
8955	 * @return {Vector4} A reference to this vector.
8956	 */
8957	lerp( v, alpha ) {
8958
8959		this.x += ( v.x - this.x ) * alpha;
8960		this.y += ( v.y - this.y ) * alpha;
8961		this.z += ( v.z - this.z ) * alpha;
8962		this.w += ( v.w - this.w ) * alpha;
8963
8964		return this;
8965
8966	}
8967
8968	/**
8969	 * Linearly interpolates between the given vectors, where alpha is the percent
8970	 * distance along the line - alpha = 0 will be first vector, and alpha = 1 will
8971	 * be the second one. The result is stored in this instance.
8972	 *
8973	 * @param {Vector4} v1 - The first vector.
8974	 * @param {Vector4} v2 - The second vector.
8975	 * @param {number} alpha - The interpolation factor, typically in the closed interval `[0, 1]`.
8976	 * @return {Vector4} A reference to this vector.
8977	 */
8978	lerpVectors( v1, v2, alpha ) {
8979
8980		this.x = v1.x + ( v2.x - v1.x ) * alpha;
8981		this.y = v1.y + ( v2.y - v1.y ) * alpha;
8982		this.z = v1.z + ( v2.z - v1.z ) * alpha;
8983		this.w = v1.w + ( v2.w - v1.w ) * alpha;
8984
8985		return this;
8986
8987	}
8988
8989	/**
8990	 * Returns `true` if this vector is equal with the given one.
8991	 *
8992	 * @param {Vector4} v - The vector to test for equality.
8993	 * @return {boolean} Whether this vector is equal with the given one.
8994	 */
8995	equals( v ) {
8996
8997		return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) );
8998
8999	}
9000
9001	/**
9002	 * Sets this vector's x value to be `array[ offset ]`, y value to be `array[ offset + 1 ]`,
9003	 * z value to be `array[ offset + 2 ]`, w value to be `array[ offset + 3 ]`.
9004	 *
9005	 * @param {Array<number>} array - An array holding the vector component values.
9006	 * @param {number} [offset=0] - The offset into the array.
9007	 * @return {Vector4} A reference to this vector.
9008	 */
9009	fromArray( array, offset = 0 ) {
9010
9011		this.x = array[ offset ];
9012		this.y = array[ offset + 1 ];
9013		this.z = array[ offset + 2 ];
9014		this.w = array[ offset + 3 ];
9015
9016		return this;
9017
9018	}
9019
9020	/**
9021	 * Writes the components of this vector to the given array. If no array is provided,
9022	 * the method returns a new instance.
9023	 *
9024	 * @param {Array<number>} [array=[]] - The target array holding the vector components.
9025	 * @param {number} [offset=0] - Index of the first element in the array.
9026	 * @return {Array<number>} The vector components.
9027	 */
9028	toArray( array = [], offset = 0 ) {
9029
9030		array[ offset ] = this.x;
9031		array[ offset + 1 ] = this.y;
9032		array[ offset + 2 ] = this.z;
9033		array[ offset + 3 ] = this.w;
9034
9035		return array;
9036
9037	}
9038
9039	/**
9040	 * Sets the components of this vector from the given buffer attribute.
9041	 *
9042	 * @param {BufferAttribute} attribute - The buffer attribute holding vector data.
9043	 * @param {number} index - The index into the attribute.
9044	 * @return {Vector4} A reference to this vector.
9045	 */
9046	fromBufferAttribute( attribute, index ) {
9047
9048		this.x = attribute.getX( index );
9049		this.y = attribute.getY( index );
9050		this.z = attribute.getZ( index );
9051		this.w = attribute.getW( index );
9052
9053		return this;
9054
9055	}
9056
9057	/**
9058	 * Sets each component of this vector to a pseudo-random value between `0` and
9059	 * `1`, excluding `1`.
9060	 *
9061	 * @return {Vector4} A reference to this vector.
9062	 */
9063	random() {
9064
9065		this.x = Math.random();
9066		this.y = Math.random();
9067		this.z = Math.random();
9068		this.w = Math.random();
9069
9070		return this;
9071
9072	}
9073
9074	*[ Symbol.iterator ]() {
9075
9076		yield this.x;
9077		yield this.y;
9078		yield this.z;
9079		yield this.w;
9080
9081	}
9082
9083}
9084
9085/**
9086 * A render target is a buffer where the video card draws pixels for a scene
9087 * that is being rendered in the background. It is used in different effects,
9088 * such as applying postprocessing to a rendered image before displaying it
9089 * on the screen.
9090 *
9091 * @augments EventDispatcher
9092 */
9093class RenderTarget extends EventDispatcher {
9094
9095	/**
9096	 * Render target options.
9097	 *
9098	 * @typedef {Object} RenderTarget~Options
9099	 * @property {boolean} [generateMipmaps=false] - Whether to generate mipmaps or not.
9100	 * @property {number} [magFilter=LinearFilter] - The mag filter.
9101	 * @property {number} [minFilter=LinearFilter] - The min filter.
9102	 * @property {number} [format=RGBAFormat] - The texture format.
9103	 * @property {number} [type=UnsignedByteType] - The texture type.
9104	 * @property {?string} [internalFormat=null] - The texture's internal format.
9105	 * @property {number} [wrapS=ClampToEdgeWrapping] - The texture's uv wrapping mode.
9106	 * @property {number} [wrapT=ClampToEdgeWrapping] - The texture's uv wrapping mode.
9107	 * @property {number} [anisotropy=1] - The texture's anisotropy value.
9108	 * @property {string} [colorSpace=NoColorSpace] - The texture's color space.
9109	 * @property {boolean} [depthBuffer=true] - Whether to allocate a depth buffer or not.
9110	 * @property {boolean} [stencilBuffer=false] - Whether to allocate a stencil buffer or not.
9111	 * @property {boolean} [resolveDepthBuffer=true] - Whether to resolve the depth buffer or not.
9112	 * @property {boolean} [resolveStencilBuffer=true] - Whether  to resolve the stencil buffer or not.
9113	 * @property {?Texture} [depthTexture=null] - Reference to a depth texture.
9114	 * @property {number} [samples=0] - The MSAA samples count.
9115	 * @property {number} [count=1] - Defines the number of color attachments . Must be at least `1`.
9116	 * @property {number} [depth=1] - The texture depth.
9117	 * @property {boolean} [multiview=false] - Whether this target is used for multiview rendering.
9118	 */
9119
9120	/**
9121	 * Constructs a new render target.
9122	 *
9123	 * @param {number} [width=1] - The width of the render target.
9124	 * @param {number} [height=1] - The height of the render target.
9125	 * @param {RenderTarget~Options} [options] - The configuration object.
9126	 */
9127	constructor( width = 1, height = 1, options = {} ) {
9128
9129		super();
9130
9131		options = Object.assign( {
9132			generateMipmaps: false,
9133			internalFormat: null,
9134			minFilter: LinearFilter,
9135			depthBuffer: true,
9136			stencilBuffer: false,
9137			resolveDepthBuffer: true,
9138			resolveStencilBuffer: true,
9139			depthTexture: null,
9140			samples: 0,
9141			count: 1,
9142			depth: 1,
9143			multiview: false
9144		}, options );
9145
9146		/**
9147		 * This flag can be used for type testing.
9148		 *
9149		 * @type {boolean}
9150		 * @readonly
9151		 * @default true
9152		 */
9153		this.isRenderTarget = true;
9154
9155		/**
9156		 * The width of the render target.
9157		 *
9158		 * @type {number}
9159		 * @default 1
9160		 */
9161		this.width = width;
9162
9163		/**
9164		 * The height of the render target.
9165		 *
9166		 * @type {number}
9167		 * @default 1
9168		 */
9169		this.height = height;
9170
9171		/**
9172		 * The depth of the render target.
9173		 *
9174		 * @type {number}
9175		 * @default 1
9176		 */
9177		this.depth = options.depth;
9178
9179		/**
9180		 * A rectangular area inside the render target's viewport. Fragments that are
9181		 * outside the area will be discarded.
9182		 *
9183		 * @type {Vector4}
9184		 * @default (0,0,width,height)
9185		 */
9186		this.scissor = new Vector4( 0, 0, width, height );
9187
9188		/**
9189		 * Indicates whether the scissor test should be enabled when rendering into
9190		 * this render target or not.
9191		 *
9192		 * @type {boolean}
9193		 * @default false
9194		 */
9195		this.scissorTest = false;
9196
9197		/**
9198		 * A rectangular area representing the render target's viewport.
9199		 *
9200		 * @type {Vector4}
9201		 * @default (0,0,width,height)
9202		 */
9203		this.viewport = new Vector4( 0, 0, width, height );
9204
9205		/**
9206		 * An array of textures. Each color attachment is represented as a separate texture.
9207		 * Has at least a single entry for the default color attachment.
9208		 *
9209		 * @type {Array<Texture>}
9210		 */
9211		this.textures = [];
9212
9213		const image = { width: width, height: height, depth: options.depth };
9214		const texture = new Texture( image );
9215
9216		const count = options.count;
9217		for ( let i = 0; i < count; i ++ ) {
9218
9219			this.textures[ i ] = texture.clone();
9220			this.textures[ i ].isRenderTargetTexture = true;
9221			this.textures[ i ].renderTarget = this;
9222
9223		}
9224
9225		this._setTextureOptions( options );
9226
9227		/**
9228		 * Whether to allocate a depth buffer or not.
9229		 *
9230		 * @type {boolean}
9231		 * @default true
9232		 */
9233		this.depthBuffer = options.depthBuffer;
9234
9235		/**
9236		 * Whether to allocate a stencil buffer or not.
9237		 *
9238		 * @type {boolean}
9239		 * @default false
9240		 */
9241		this.stencilBuffer = options.stencilBuffer;
9242
9243		/**
9244		 * Whether to resolve the depth buffer or not.
9245		 *
9246		 * @type {boolean}
9247		 * @default true
9248		 */
9249		this.resolveDepthBuffer = options.resolveDepthBuffer;
9250
9251		/**
9252		 * Whether to resolve the stencil buffer or not.
9253		 *
9254		 * @type {boolean}
9255		 * @default true
9256		 */
9257		this.resolveStencilBuffer = options.resolveStencilBuffer;
9258
9259		this._depthTexture = null;
9260		this.depthTexture = options.depthTexture;
9261
9262		/**
9263		 * The number of MSAA samples.
9264		 *
9265		 * A value of `0` disables MSAA.
9266		 *
9267		 * @type {number}
9268		 * @default 0
9269		 */
9270		this.samples = options.samples;
9271
9272		/**
9273		 * Whether to this target is used in multiview rendering.
9274		 *
9275		 * @type {boolean}
9276		 * @default false
9277		 */
9278		this.multiview = options.multiview;
9279
9280	}
9281
9282	_setTextureOptions( options = {} ) {
9283
9284		const values = {
9285			minFilter: LinearFilter,
9286			generateMipmaps: false,
9287			flipY: false,
9288			internalFormat: null
9289		};
9290
9291		if ( options.mapping !== undefined ) values.mapping = options.mapping;
9292		if ( options.wrapS !== undefined ) values.wrapS = options.wrapS;
9293		if ( options.wrapT !== undefined ) values.wrapT = options.wrapT;
9294		if ( options.wrapR !== undefined ) values.wrapR = options.wrapR;
9295		if ( options.magFilter !== undefined ) values.magFilter = options.magFilter;
9296		if ( options.minFilter !== undefined ) values.minFilter = options.minFilter;
9297		if ( options.format !== undefined ) values.format = options.format;
9298		if ( options.type !== undefined ) values.type = options.type;
9299		if ( options.anisotropy !== undefined ) values.anisotropy = options.anisotropy;
9300		if ( options.colorSpace !== undefined ) values.colorSpace = options.colorSpace;
9301		if ( options.flipY !== undefined ) values.flipY = options.flipY;
9302		if ( options.generateMipmaps !== undefined ) values.generateMipmaps = options.generateMipmaps;
9303		if ( options.internalFormat !== undefined ) values.internalFormat = options.internalFormat;
9304
9305		for ( let i = 0; i < this.textures.length; i ++ ) {
9306
9307			const texture = this.textures[ i ];
9308			texture.setValues( values );
9309
9310		}
9311
9312	}
9313
9314	/**
9315	 * The texture representing the default color attachment.
9316	 *
9317	 * @type {Texture}
9318	 */
9319	get texture() {
9320
9321		return this.textures[ 0 ];
9322
9323	}
9324
9325	set texture( value ) {
9326
9327		this.textures[ 0 ] = value;
9328
9329	}
9330
9331	set depthTexture( current ) {
9332
9333		if ( this._depthTexture !== null ) this._depthTexture.renderTarget = null;
9334		if ( current !== null ) current.renderTarget = this;
9335
9336		this._depthTexture = current;
9337
9338	}
9339
9340	/**
9341	 * Instead of saving the depth in a renderbuffer, a texture
9342	 * can be used instead which is useful for further processing
9343	 * e.g. in context of post-processing.
9344	 *
9345	 * @type {?DepthTexture}
9346	 * @default null
9347	 */
9348	get depthTexture() {
9349
9350		return this._depthTexture;
9351
9352	}
9353
9354	/**
9355	 * Sets the size of this render target.
9356	 *
9357	 * @param {number} width - The width.
9358	 * @param {number} height - The height.
9359	 * @param {number} [depth=1] - The depth.
9360	 */
9361	setSize( width, height, depth = 1 ) {
9362
9363		if ( this.width !== width || this.height !== height || this.depth !== depth ) {
9364
9365			this.width = width;
9366			this.height = height;
9367			this.depth = depth;
9368
9369			for ( let i = 0, il = this.textures.length; i < il; i ++ ) {
9370
9371				this.textures[ i ].image.width = width;
9372				this.textures[ i ].image.height = height;
9373				this.textures[ i ].image.depth = depth;
9374
9375				if ( this.textures[ i ].isData3DTexture !== true ) { // Fix for #31693
9376
9377					// TODO: Reconsider setting isArrayTexture flag here and in the ctor of Texture.
9378					// Maybe a method `isArrayTexture()` or just a getter could replace a flag since
9379					// both are evaluated on each call?
9380
9381					this.textures[ i ].isArrayTexture = this.textures[ i ].image.depth > 1;
9382
9383				}
9384
9385			}
9386
9387			this.dispose();
9388
9389		}
9390
9391		this.viewport.set( 0, 0, width, height );
9392		this.scissor.set( 0, 0, width, height );
9393
9394	}
9395
9396	/**
9397	 * Returns a new render target with copied values from this instance.
9398	 *
9399	 * @return {RenderTarget} A clone of this instance.
9400	 */
9401	clone() {
9402
9403		return new this.constructor().copy( this );
9404
9405	}
9406
9407	/**
9408	 * Copies the settings of the given render target. This is a structural copy so
9409	 * no resources are shared between render targets after the copy. That includes
9410	 * all MRT textures and the depth texture.
9411	 *
9412	 * @param {RenderTarget} source - The render target to copy.
9413	 * @return {RenderTarget} A reference to this instance.
9414	 */
9415	copy( source ) {
9416
9417		this.width = source.width;
9418		this.height = source.height;
9419		this.depth = source.depth;
9420
9421		this.scissor.copy( source.scissor );
9422		this.scissorTest = source.scissorTest;
9423
9424		this.viewport.copy( source.viewport );
9425
9426		this.textures.length = 0;
9427
9428		for ( let i = 0, il = source.textures.length; i < il; i ++ ) {
9429
9430			this.textures[ i ] = source.textures[ i ].clone();
9431			this.textures[ i ].isRenderTargetTexture = true;
9432			this.textures[ i ].renderTarget = this;
9433
9434			// ensure image object is not shared, see #20328
9435
9436			const image = Object.assign( {}, source.textures[ i ].image );
9437			this.textures[ i ].source = new Source( image );
9438
9439		}
9440
9441		this.depthBuffer = source.depthBuffer;
9442		this.stencilBuffer = source.stencilBuffer;
9443
9444		this.resolveDepthBuffer = source.resolveDepthBuffer;
9445		this.resolveStencilBuffer = source.resolveStencilBuffer;
9446
9447		if ( source.depthTexture !== null ) this.depthTexture = source.depthTexture.clone();
9448
9449		this.samples = source.samples;
9450		this.multiview = source.multiview;
9451
9452		return this;
9453
9454	}
9455
9456	/**
9457	 * Frees the GPU-related resources allocated by this instance. Call this
9458	 * method whenever this instance is no longer used in your app.
9459	 *
9460	 * @fires RenderTarget#dispose
9461	 */
9462	dispose() {
9463
9464		this.dispatchEvent( { type: 'dispose' } );
9465
9466	}
9467
9468}
9469
9470/**
9471 * A render target used in context of {@link WebGLRenderer}.
9472 *
9473 * @augments RenderTarget
9474 */
9475class WebGLRenderTarget extends RenderTarget {
9476
9477	/**
9478	 * Constructs a new 3D render target.
9479	 *
9480	 * @param {number} [width=1] - The width of the render target.
9481	 * @param {number} [height=1] - The height of the render target.
9482	 * @param {RenderTarget~Options} [options] - The configuration object.
9483	 */
9484	constructor( width = 1, height = 1, options = {} ) {
9485
9486		super( width, height, options );
9487
9488		/**
9489		 * This flag can be used for type testing.
9490		 *
9491		 * @type {boolean}
9492		 * @readonly
9493		 * @default true
9494		 */
9495		this.isWebGLRenderTarget = true;
9496
9497	}
9498
9499}
9500
9501/**
9502 * Creates an array of textures directly from raw buffer data.
9503 *
9504 * @augments Texture
9505 */
9506class DataArrayTexture extends Texture {
9507
9508	/**
9509	 * Constructs a new data array texture.
9510	 *
9511	 * @param {?TypedArray} [data=null] - The buffer data.
9512	 * @param {number} [width=1] - The width of the texture.
9513	 * @param {number} [height=1] - The height of the texture.
9514	 * @param {number} [depth=1] - The depth of the texture.
9515	 */
9516	constructor( data = null, width = 1, height = 1, depth = 1 ) {
9517
9518		super( null );
9519
9520		/**
9521		 * This flag can be used for type testing.
9522		 *
9523		 * @type {boolean}
9524		 * @readonly
9525		 * @default true
9526		 */
9527		this.isDataArrayTexture = true;
9528
9529		/**
9530		 * The image definition of a data texture.
9531		 *
9532		 * @type {{data:TypedArray,width:number,height:number,depth:number}}
9533		 */
9534		this.image = { data, width, height, depth };
9535
9536		/**
9537		 * How the texture is sampled when a texel covers more than one pixel.
9538		 *
9539		 * Overwritten and set to `NearestFilter` by default.
9540		 *
9541		 * @type {(NearestFilter|NearestMipmapNearestFilter|NearestMipmapLinearFilter|LinearFilter|LinearMipmapNearestFilter|LinearMipmapLinearFilter)}
9542		 * @default NearestFilter
9543		 */
9544		this.magFilter = NearestFilter;
9545
9546		/**
9547		 * How the texture is sampled when a texel covers less than one pixel.
9548		 *
9549		 * Overwritten and set to `NearestFilter` by default.
9550		 *
9551		 * @type {(NearestFilter|NearestMipmapNearestFilter|NearestMipmapLinearFilter|LinearFilter|LinearMipmapNearestFilter|LinearMipmapLinearFilter)}
9552		 * @default NearestFilter
9553		 */
9554		this.minFilter = NearestFilter;
9555
9556		/**
9557		 * This defines how the texture is wrapped in the depth and corresponds to
9558		 * *W* in UVW mapping.
9559		 *
9560		 * @type {(RepeatWrapping|ClampToEdgeWrapping|MirroredRepeatWrapping)}
9561		 * @default ClampToEdgeWrapping
9562		 */
9563		this.wrapR = ClampToEdgeWrapping;
9564
9565		/**
9566		 * Whether to generate mipmaps (if possible) for a texture.
9567		 *
9568		 * Overwritten and set to `false` by default.
9569		 *
9570		 * @type {boolean}
9571		 * @default false
9572		 */
9573		this.generateMipmaps = false;
9574
9575		/**
9576		 * If set to `true`, the texture is flipped along the vertical axis when
9577		 * uploaded to the GPU.
9578		 *
9579		 * Overwritten and set to `false` by default.
9580		 *
9581		 * @type {boolean}
9582		 * @default false
9583		 */
9584		this.flipY = false;
9585
9586		/**
9587		 * Specifies the alignment requirements for the start of each pixel row in memory.
9588		 *
9589		 * Overwritten and set to `1` by default.
9590		 *
9591		 * @type {boolean}
9592		 * @default 1
9593		 */
9594		this.unpackAlignment = 1;
9595
9596		/**
9597		 * A set of all layers which need to be updated in the texture.
9598		 *
9599		 * @type {Set<number>}
9600		 */
9601		this.layerUpdates = new Set();
9602
9603	}
9604
9605	/**
9606	 * Describes that a specific layer of the texture needs to be updated.
9607	 * Normally when {@link Texture#needsUpdate} is set to `true`, the
9608	 * entire data texture array is sent to the GPU. Marking specific
9609	 * layers will only transmit subsets of all mipmaps associated with a
9610	 * specific depth in the array which is often much more performant.
9611	 *
9612	 * @param {number} layerIndex - The layer index that should be updated.
9613	 */
9614	addLayerUpdate( layerIndex ) {
9615
9616		this.layerUpdates.add( layerIndex );
9617
9618	}
9619
9620	/**
9621	 * Resets the layer updates registry.
9622	 */
9623	clearLayerUpdates() {
9624
9625		this.layerUpdates.clear();
9626
9627	}
9628
9629}
9630
9631/**
9632 * An array render target used in context of {@link WebGLRenderer}.
9633 *
9634 * @augments WebGLRenderTarget
9635 */
9636class WebGLArrayRenderTarget extends WebGLRenderTarget {
9637
9638	/**
9639	 * Constructs a new array render target.
9640	 *
9641	 * @param {number} [width=1] - The width of the render target.
9642	 * @param {number} [height=1] - The height of the render target.
9643	 * @param {number} [depth=1] - The height of the render target.
9644	 * @param {RenderTarget~Options} [options] - The configuration object.
9645	 */
9646	constructor( width = 1, height = 1, depth = 1, options = {} ) {
9647
9648		super( width, height, options );
9649
9650		/**
9651		 * This flag can be used for type testing.
9652		 *
9653		 * @type {boolean}
9654		 * @readonly
9655		 * @default true
9656		 */
9657		this.isWebGLArrayRenderTarget = true;
9658
9659		this.depth = depth;
9660
9661		/**
9662		 * Overwritten with a different texture type.
9663		 *
9664		 * @type {DataArrayTexture}
9665		 */
9666		this.texture = new DataArrayTexture( null, width, height, depth );
9667		this._setTextureOptions( options );
9668
9669		this.texture.isRenderTargetTexture = true;
9670
9671	}
9672
9673}
9674
9675/**
9676 * Creates a three-dimensional texture from raw data, with parameters to
9677 * divide it into width, height, and depth.
9678 *
9679 * @augments Texture
9680 */
9681class Data3DTexture extends Texture {
9682
9683	/**
9684	 * Constructs a new data array texture.
9685	 *
9686	 * @param {?TypedArray} [data=null] - The buffer data.
9687	 * @param {number} [width=1] - The width of the texture.
9688	 * @param {number} [height=1] - The height of the texture.
9689	 * @param {number} [depth=1] - The depth of the texture.
9690	 */
9691	constructor( data = null, width = 1, height = 1, depth = 1 ) {
9692
9693		// We're going to add .setXXX() methods for setting properties later.
9694		// Users can still set in Data3DTexture directly.
9695		//
9696		//	const texture = new THREE.Data3DTexture( data, width, height, depth );
9697		// 	texture.anisotropy = 16;
9698		//
9699		// See #14839
9700
9701		super( null );
9702
9703		/**
9704		 * This flag can be used for type testing.
9705		 *
9706		 * @type {boolean}
9707		 * @readonly
9708		 * @default true
9709		 */
9710		this.isData3DTexture = true;
9711
9712		/**
9713		 * The image definition of a data texture.
9714		 *
9715		 * @type {{data:TypedArray,width:number,height:number,depth:number}}
9716		 */
9717		this.image = { data, width, height, depth };
9718
9719		/**
9720		 * How the texture is sampled when a texel covers more than one pixel.
9721		 *
9722		 * Overwritten and set to `NearestFilter` by default.
9723		 *
9724		 * @type {(NearestFilter|NearestMipmapNearestFilter|NearestMipmapLinearFilter|LinearFilter|LinearMipmapNearestFilter|LinearMipmapLinearFilter)}
9725		 * @default NearestFilter
9726		 */
9727		this.magFilter = NearestFilter;
9728
9729		/**
9730		 * How the texture is sampled when a texel covers less than one pixel.
9731		 *
9732		 * Overwritten and set to `NearestFilter` by default.
9733		 *
9734		 * @type {(NearestFilter|NearestMipmapNearestFilter|NearestMipmapLinearFilter|LinearFilter|LinearMipmapNearestFilter|LinearMipmapLinearFilter)}
9735		 * @default NearestFilter
9736		 */
9737		this.minFilter = NearestFilter;
9738
9739		/**
9740		 * This defines how the texture is wrapped in the depth and corresponds to
9741		 * *W* in UVW mapping.
9742		 *
9743		 * @type {(RepeatWrapping|ClampToEdgeWrapping|MirroredRepeatWrapping)}
9744		 * @default ClampToEdgeWrapping
9745		 */
9746		this.wrapR = ClampToEdgeWrapping;
9747
9748		/**
9749		 * Whether to generate mipmaps (if possible) for a texture.
9750		 *
9751		 * Overwritten and set to `false` by default.
9752		 *
9753		 * @type {boolean}
9754		 * @default false
9755		 */
9756		this.generateMipmaps = false;
9757
9758		/**
9759		 * If set to `true`, the texture is flipped along the vertical axis when
9760		 * uploaded to the GPU.
9761		 *
9762		 * Overwritten and set to `false` by default.
9763		 *
9764		 * @type {boolean}
9765		 * @default false
9766		 */
9767		this.flipY = false;
9768
9769		/**
9770		 * Specifies the alignment requirements for the start of each pixel row in memory.
9771		 *
9772		 * Overwritten and set to `1` by default.
9773		 *
9774		 * @type {boolean}
9775		 * @default 1
9776		 */
9777		this.unpackAlignment = 1;
9778
9779	}
9780
9781}
9782
9783/**
9784 * A 3D render target used in context of {@link WebGLRenderer}.
9785 *
9786 * @augments WebGLRenderTarget
9787 */
9788class WebGL3DRenderTarget extends WebGLRenderTarget {
9789
9790	/**
9791	 * Constructs a new 3D render target.
9792	 *
9793	 * @param {number} [width=1] - The width of the render target.
9794	 * @param {number} [height=1] - The height of the render target.
9795	 * @param {number} [depth=1] - The height of the render target.
9796	 * @param {RenderTarget~Options} [options] - The configuration object.
9797	 */
9798	constructor( width = 1, height = 1, depth = 1, options = {} ) {
9799
9800		super( width, height, options );
9801
9802		/**
9803		 * This flag can be used for type testing.
9804		 *
9805		 * @type {boolean}
9806		 * @readonly
9807		 * @default true
9808		 */
9809		this.isWebGL3DRenderTarget = true;
9810
9811		this.depth = depth;
9812
9813		/**
9814		 * Overwritten with a different texture type.
9815		 *
9816		 * @type {Data3DTexture}
9817		 */
9818		this.texture = new Data3DTexture( null, width, height, depth );
9819		this._setTextureOptions( options );
9820
9821		this.texture.isRenderTargetTexture = true;
9822
9823	}
9824
9825}
9826
9827/**
9828 * Represents a 4x4 matrix.
9829 *
9830 * The most common use of a 4x4 matrix in 3D computer graphics is as a transformation matrix.
9831 * For an introduction to transformation matrices as used in WebGL, check out [this tutorial](https://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices)
9832 *
9833 * This allows a 3D vector representing a point in 3D space to undergo
9834 * transformations such as translation, rotation, shear, scale, reflection,
9835 * orthogonal or perspective projection and so on, by being multiplied by the
9836 * matrix. This is known as `applying` the matrix to the vector.
9837 *
9838 * A Note on Row-Major and Column-Major Ordering:
9839 *
9840 * The constructor and {@link Matrix3#set} method take arguments in
9841 * [row-major](https://en.wikipedia.org/wiki/Row-_and_column-major_order#Column-major_order)
9842 * order, while internally they are stored in the {@link Matrix3#elements} array in column-major order.
9843 * This means that calling:
9844 * ```js
9845 * const m = new THREE.Matrix4();
9846 * m.set( 11, 12, 13, 14,
9847 *        21, 22, 23, 24,
9848 *        31, 32, 33, 34,
9849 *        41, 42, 43, 44 );
9850 * ```
9851 * will result in the elements array containing:
9852 * ```js
9853 * m.elements = [ 11, 21, 31, 41,
9854 *                12, 22, 32, 42,
9855 *                13, 23, 33, 43,
9856 *                14, 24, 34, 44 ];
9857 * ```
9858 * and internally all calculations are performed using column-major ordering.
9859 * However, as the actual ordering makes no difference mathematically and
9860 * most people are used to thinking about matrices in row-major order, the
9861 * three.js documentation shows matrices in row-major order. Just bear in
9862 * mind that if you are reading the source code, you'll have to take the
9863 * transpose of any matrices outlined here to make sense of the calculations.
9864 */
9865class Matrix4 {
9866
9867	static {
9868
9869		/**
9870		 * This flag can be used for type testing.
9871		 *
9872		 * @type {boolean}
9873		 * @readonly
9874		 * @default true
9875		 */
9876		Matrix4.prototype.isMatrix4 = true;
9877
9878	}
9879
9880	/**
9881	 * Constructs a new 4x4 matrix. The arguments are supposed to be
9882	 * in row-major order. If no arguments are provided, the constructor
9883	 * initializes the matrix as an identity matrix.
9884	 *
9885	 * @param {number} [n11] - 1-1 matrix element.
9886	 * @param {number} [n12] - 1-2 matrix element.
9887	 * @param {number} [n13] - 1-3 matrix element.
9888	 * @param {number} [n14] - 1-4 matrix element.
9889	 * @param {number} [n21] - 2-1 matrix element.
9890	 * @param {number} [n22] - 2-2 matrix element.
9891	 * @param {number} [n23] - 2-3 matrix element.
9892	 * @param {number} [n24] - 2-4 matrix element.
9893	 * @param {number} [n31] - 3-1 matrix element.
9894	 * @param {number} [n32] - 3-2 matrix element.
9895	 * @param {number} [n33] - 3-3 matrix element.
9896	 * @param {number} [n34] - 3-4 matrix element.
9897	 * @param {number} [n41] - 4-1 matrix element.
9898	 * @param {number} [n42] - 4-2 matrix element.
9899	 * @param {number} [n43] - 4-3 matrix element.
9900	 * @param {number} [n44] - 4-4 matrix element.
9901	 */
9902	constructor( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
vendor: 31,611 bytes, lines 9902-11183
9902
9903
9904		/**
9905		 * A column-major list of matrix values.
9906		 *
9907		 * @type {Array<number>}
9908		 */
9909		this.elements = [
9910
9911			1, 0, 0, 0,
9912			0, 1, 0, 0,
9913			0, 0, 1, 0,
9914			0, 0, 0, 1
9915
9916		];
9917
9918		if ( n11 !== undefined ) {
9919
9920			this.set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 );
9921
9922		}
9923
9924	}
9925
9926	/**
9927	 * Sets the elements of the matrix.The arguments are supposed to be
9928	 * in row-major order.
9929	 *
9930	 * @param {number} [n11] - 1-1 matrix element.
9931	 * @param {number} [n12] - 1-2 matrix element.
9932	 * @param {number} [n13] - 1-3 matrix element.
9933	 * @param {number} [n14] - 1-4 matrix element.
9934	 * @param {number} [n21] - 2-1 matrix element.
9935	 * @param {number} [n22] - 2-2 matrix element.
9936	 * @param {number} [n23] - 2-3 matrix element.
9937	 * @param {number} [n24] - 2-4 matrix element.
9938	 * @param {number} [n31] - 3-1 matrix element.
9939	 * @param {number} [n32] - 3-2 matrix element.
9940	 * @param {number} [n33] - 3-3 matrix element.
9941	 * @param {number} [n34] - 3-4 matrix element.
9942	 * @param {number} [n41] - 4-1 matrix element.
9943	 * @param {number} [n42] - 4-2 matrix element.
9944	 * @param {number} [n43] - 4-3 matrix element.
9945	 * @param {number} [n44] - 4-4 matrix element.
9946	 * @return {Matrix4} A reference to this matrix.
9947	 */
9948	set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
9949
9950		const te = this.elements;
9951
9952		te[ 0 ] = n11; te[ 4 ] = n12; te[ 8 ] = n13; te[ 12 ] = n14;
9953		te[ 1 ] = n21; te[ 5 ] = n22; te[ 9 ] = n23; te[ 13 ] = n24;
9954		te[ 2 ] = n31; te[ 6 ] = n32; te[ 10 ] = n33; te[ 14 ] = n34;
9955		te[ 3 ] = n41; te[ 7 ] = n42; te[ 11 ] = n43; te[ 15 ] = n44;
9956
9957		return this;
9958
9959	}
9960
9961	/**
9962	 * Sets this matrix to the 4x4 identity matrix.
9963	 *
9964	 * @return {Matrix4} A reference to this matrix.
9965	 */
9966	identity() {
9967
9968		this.set(
9969
9970			1, 0, 0, 0,
9971			0, 1, 0, 0,
9972			0, 0, 1, 0,
9973			0, 0, 0, 1
9974
9975		);
9976
9977		return this;
9978
9979	}
9980
9981	/**
9982	 * Returns a matrix with copied values from this instance.
9983	 *
9984	 * @return {Matrix4} A clone of this instance.
9985	 */
9986	clone() {
9987
9988		return new Matrix4().fromArray( this.elements );
9989
9990	}
9991
9992	/**
9993	 * Copies the values of the given matrix to this instance.
9994	 *
9995	 * @param {Matrix4} m - The matrix to copy.
9996	 * @return {Matrix4} A reference to this matrix.
9997	 */
9998	copy( m ) {
9999
10000		const te = this.elements;
10001		const me = m.elements;
10002
10003		te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ]; te[ 3 ] = me[ 3 ];
10004		te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ]; te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ];
10005		te[ 8 ] = me[ 8 ]; te[ 9 ] = me[ 9 ]; te[ 10 ] = me[ 10 ]; te[ 11 ] = me[ 11 ];
10006		te[ 12 ] = me[ 12 ]; te[ 13 ] = me[ 13 ]; te[ 14 ] = me[ 14 ]; te[ 15 ] = me[ 15 ];
10007
10008		return this;
10009
10010	}
10011
10012	/**
10013	 * Copies the translation component of the given matrix
10014	 * into this matrix's translation component.
10015	 *
10016	 * @param {Matrix4} m - The matrix to copy the translation component.
10017	 * @return {Matrix4} A reference to this matrix.
10018	 */
10019	copyPosition( m ) {
10020
10021		const te = this.elements, me = m.elements;
10022
10023		te[ 12 ] = me[ 12 ];
10024		te[ 13 ] = me[ 13 ];
10025		te[ 14 ] = me[ 14 ];
10026
10027		return this;
10028
10029	}
10030
10031	/**
10032	 * Set the upper 3x3 elements of this matrix to the values of given 3x3 matrix.
10033	 *
10034	 * @param {Matrix3} m - The 3x3 matrix.
10035	 * @return {Matrix4} A reference to this matrix.
10036	 */
10037	setFromMatrix3( m ) {
10038
10039		const me = m.elements;
10040
10041		this.set(
10042
10043			me[ 0 ], me[ 3 ], me[ 6 ], 0,
10044			me[ 1 ], me[ 4 ], me[ 7 ], 0,
10045			me[ 2 ], me[ 5 ], me[ 8 ], 0,
10046			0, 0, 0, 1
10047
10048		);
10049
10050		return this;
10051
10052	}
10053
10054	/**
10055	 * Extracts the basis of this matrix into the three axis vectors provided.
10056	 *
10057	 * @param {Vector3} xAxis - The basis's x axis.
10058	 * @param {Vector3} yAxis - The basis's y axis.
10059	 * @param {Vector3} zAxis - The basis's z axis.
10060	 * @return {Matrix4} A reference to this matrix.
10061	 */
10062	extractBasis( xAxis, yAxis, zAxis ) {
10063
10064		if ( this.determinant() === 0 ) {
10065
10066			xAxis.set( 1, 0, 0 );
10067			yAxis.set( 0, 1, 0 );
10068			zAxis.set( 0, 0, 1 );
10069
10070			return this;
10071
10072		}
10073
10074		xAxis.setFromMatrixColumn( this, 0 );
10075		yAxis.setFromMatrixColumn( this, 1 );
10076		zAxis.setFromMatrixColumn( this, 2 );
10077
10078		return this;
10079
10080	}
10081
10082	/**
10083	 * Sets the given basis vectors to this matrix.
10084	 *
10085	 * @param {Vector3} xAxis - The basis's x axis.
10086	 * @param {Vector3} yAxis - The basis's y axis.
10087	 * @param {Vector3} zAxis - The basis's z axis.
10088	 * @return {Matrix4} A reference to this matrix.
10089	 */
10090	makeBasis( xAxis, yAxis, zAxis ) {
10091
10092		this.set(
10093			xAxis.x, yAxis.x, zAxis.x, 0,
10094			xAxis.y, yAxis.y, zAxis.y, 0,
10095			xAxis.z, yAxis.z, zAxis.z, 0,
10096			0, 0, 0, 1
10097		);
10098
10099		return this;
10100
10101	}
10102
10103	/**
10104	 * Extracts the rotation component of the given matrix
10105	 * into this matrix's rotation component.
10106	 *
10107	 * Note: This method does not support reflection matrices.
10108	 *
10109	 * @param {Matrix4} m - The matrix.
10110	 * @return {Matrix4} A reference to this matrix.
10111	 */
10112	extractRotation( m ) {
10113
10114		if ( m.determinant() === 0 ) {
10115
10116			return this.identity();
10117
10118		}
10119
10120		const te = this.elements;
10121		const me = m.elements;
10122
10123		const scaleX = 1 / _v1$7.setFromMatrixColumn( m, 0 ).length();
10124		const scaleY = 1 / _v1$7.setFromMatrixColumn( m, 1 ).length();
10125		const scaleZ = 1 / _v1$7.setFromMatrixColumn( m, 2 ).length();
10126
10127		te[ 0 ] = me[ 0 ] * scaleX;
10128		te[ 1 ] = me[ 1 ] * scaleX;
10129		te[ 2 ] = me[ 2 ] * scaleX;
10130		te[ 3 ] = 0;
10131
10132		te[ 4 ] = me[ 4 ] * scaleY;
10133		te[ 5 ] = me[ 5 ] * scaleY;
10134		te[ 6 ] = me[ 6 ] * scaleY;
10135		te[ 7 ] = 0;
10136
10137		te[ 8 ] = me[ 8 ] * scaleZ;
10138		te[ 9 ] = me[ 9 ] * scaleZ;
10139		te[ 10 ] = me[ 10 ] * scaleZ;
10140		te[ 11 ] = 0;
10141
10142		te[ 12 ] = 0;
10143		te[ 13 ] = 0;
10144		te[ 14 ] = 0;
10145		te[ 15 ] = 1;
10146
10147		return this;
10148
10149	}
10150
10151	/**
10152	 * Sets the rotation component (the upper left 3x3 matrix) of this matrix to
10153	 * the rotation specified by the given Euler angles. The rest of
10154	 * the matrix is set to the identity. Depending on the {@link Euler#order},
10155	 * there are six possible outcomes. See [this page](https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix)
10156	 * for a complete list.
10157	 *
10158	 * @param {Euler} euler - The Euler angles.
10159	 * @return {Matrix4} A reference to this matrix.
10160	 */
10161	makeRotationFromEuler( euler ) {
10162
10163		const te = this.elements;
10164
10165		const x = euler.x, y = euler.y, z = euler.z;
10166		const a = Math.cos( x ), b = Math.sin( x );
10167		const c = Math.cos( y ), d = Math.sin( y );
10168		const e = Math.cos( z ), f = Math.sin( z );
10169
10170		if ( euler.order === 'XYZ' ) {
10171
10172			const ae = a * e, af = a * f, be = b * e, bf = b * f;
10173
10174			te[ 0 ] = c * e;
10175			te[ 4 ] = - c * f;
10176			te[ 8 ] = d;
10177
10178			te[ 1 ] = af + be * d;
10179			te[ 5 ] = ae - bf * d;
10180			te[ 9 ] = - b * c;
10181
10182			te[ 2 ] = bf - ae * d;
10183			te[ 6 ] = be + af * d;
10184			te[ 10 ] = a * c;
10185
10186		} else if ( euler.order === 'YXZ' ) {
10187
10188			const ce = c * e, cf = c * f, de = d * e, df = d * f;
10189
10190			te[ 0 ] = ce + df * b;
10191			te[ 4 ] = de * b - cf;
10192			te[ 8 ] = a * d;
10193
10194			te[ 1 ] = a * f;
10195			te[ 5 ] = a * e;
10196			te[ 9 ] = - b;
10197
10198			te[ 2 ] = cf * b - de;
10199			te[ 6 ] = df + ce * b;
10200			te[ 10 ] = a * c;
10201
10202		} else if ( euler.order === 'ZXY' ) {
10203
10204			const ce = c * e, cf = c * f, de = d * e, df = d * f;
10205
10206			te[ 0 ] = ce - df * b;
10207			te[ 4 ] = - a * f;
10208			te[ 8 ] = de + cf * b;
10209
10210			te[ 1 ] = cf + de * b;
10211			te[ 5 ] = a * e;
10212			te[ 9 ] = df - ce * b;
10213
10214			te[ 2 ] = - a * d;
10215			te[ 6 ] = b;
10216			te[ 10 ] = a * c;
10217
10218		} else if ( euler.order === 'ZYX' ) {
10219
10220			const ae = a * e, af = a * f, be = b * e, bf = b * f;
10221
10222			te[ 0 ] = c * e;
10223			te[ 4 ] = be * d - af;
10224			te[ 8 ] = ae * d + bf;
10225
10226			te[ 1 ] = c * f;
10227			te[ 5 ] = bf * d + ae;
10228			te[ 9 ] = af * d - be;
10229
10230			te[ 2 ] = - d;
10231			te[ 6 ] = b * c;
10232			te[ 10 ] = a * c;
10233
10234		} else if ( euler.order === 'YZX' ) {
10235
10236			const ac = a * c, ad = a * d, bc = b * c, bd = b * d;
10237
10238			te[ 0 ] = c * e;
10239			te[ 4 ] = bd - ac * f;
10240			te[ 8 ] = bc * f + ad;
10241
10242			te[ 1 ] = f;
10243			te[ 5 ] = a * e;
10244			te[ 9 ] = - b * e;
10245
10246			te[ 2 ] = - d * e;
10247			te[ 6 ] = ad * f + bc;
10248			te[ 10 ] = ac - bd * f;
10249
10250		} else if ( euler.order === 'XZY' ) {
10251
10252			const ac = a * c, ad = a * d, bc = b * c, bd = b * d;
10253
10254			te[ 0 ] = c * e;
10255			te[ 4 ] = - f;
10256			te[ 8 ] = d * e;
10257
10258			te[ 1 ] = ac * f + bd;
10259			te[ 5 ] = a * e;
10260			te[ 9 ] = ad * f - bc;
10261
10262			te[ 2 ] = bc * f - ad;
10263			te[ 6 ] = b * e;
10264			te[ 10 ] = bd * f + ac;
10265
10266		}
10267
10268		// bottom row
10269		te[ 3 ] = 0;
10270		te[ 7 ] = 0;
10271		te[ 11 ] = 0;
10272
10273		// last column
10274		te[ 12 ] = 0;
10275		te[ 13 ] = 0;
10276		te[ 14 ] = 0;
10277		te[ 15 ] = 1;
10278
10279		return this;
10280
10281	}
10282
10283	/**
10284	 * Sets the rotation component of this matrix to the rotation specified by
10285	 * the given Quaternion as outlined [here](https://en.wikipedia.org/wiki/Rotation_matrix#Quaternion)
10286	 * The rest of the matrix is set to the identity.
10287	 *
10288	 * @param {Quaternion} q - The Quaternion.
10289	 * @return {Matrix4} A reference to this matrix.
10290	 */
10291	makeRotationFromQuaternion( q ) {
10292
10293		return this.compose( _zero, q, _one );
10294
10295	}
10296
10297	/**
10298	 * Sets the rotation component of the transformation matrix, looking from `eye` towards
10299	 * `target`, and oriented by the up-direction.
10300	 *
10301	 * @param {Vector3} eye - The eye vector.
10302	 * @param {Vector3} target - The target vector.
10303	 * @param {Vector3} up - The up vector.
10304	 * @return {Matrix4} A reference to this matrix.
10305	 */
10306	lookAt( eye, target, up ) {
10307
10308		const te = this.elements;
10309
10310		_z.subVectors( eye, target );
10311
10312		if ( _z.lengthSq() === 0 ) {
10313
10314			// eye and target are in the same position
10315
10316			_z.z = 1;
10317
10318		}
10319
10320		_z.normalize();
10321		_x.crossVectors( up, _z );
10322
10323		if ( _x.lengthSq() === 0 ) {
10324
10325			// up and z are parallel
10326
10327			if ( Math.abs( up.z ) === 1 ) {
10328
10329				_z.x += 0.0001;
10330
10331			} else {
10332
10333				_z.z += 0.0001;
10334
10335			}
10336
10337			_z.normalize();
10338			_x.crossVectors( up, _z );
10339
10340		}
10341
10342		_x.normalize();
10343		_y.crossVectors( _z, _x );
10344
10345		te[ 0 ] = _x.x; te[ 4 ] = _y.x; te[ 8 ] = _z.x;
10346		te[ 1 ] = _x.y; te[ 5 ] = _y.y; te[ 9 ] = _z.y;
10347		te[ 2 ] = _x.z; te[ 6 ] = _y.z; te[ 10 ] = _z.z;
10348
10349		return this;
10350
10351	}
10352
10353	/**
10354	 * Post-multiplies this matrix by the given 4x4 matrix.
10355	 *
10356	 * @param {Matrix4} m - The matrix to multiply with.
10357	 * @return {Matrix4} A reference to this matrix.
10358	 */
10359	multiply( m ) {
10360
10361		return this.multiplyMatrices( this, m );
10362
10363	}
10364
10365	/**
10366	 * Pre-multiplies this matrix by the given 4x4 matrix.
10367	 *
10368	 * @param {Matrix4} m - The matrix to multiply with.
10369	 * @return {Matrix4} A reference to this matrix.
10370	 */
10371	premultiply( m ) {
10372
10373		return this.multiplyMatrices( m, this );
10374
10375	}
10376
10377	/**
10378	 * Multiples the given 4x4 matrices and stores the result
10379	 * in this matrix.
10380	 *
10381	 * @param {Matrix4} a - The first matrix.
10382	 * @param {Matrix4} b - The second matrix.
10383	 * @return {Matrix4} A reference to this matrix.
10384	 */
10385	multiplyMatrices( a, b ) {
10386
10387		const ae = a.elements;
10388		const be = b.elements;
10389		const te = this.elements;
10390
10391		const a11 = ae[ 0 ], a12 = ae[ 4 ], a13 = ae[ 8 ], a14 = ae[ 12 ];
10392		const a21 = ae[ 1 ], a22 = ae[ 5 ], a23 = ae[ 9 ], a24 = ae[ 13 ];
10393		const a31 = ae[ 2 ], a32 = ae[ 6 ], a33 = ae[ 10 ], a34 = ae[ 14 ];
10394		const a41 = ae[ 3 ], a42 = ae[ 7 ], a43 = ae[ 11 ], a44 = ae[ 15 ];
10395
10396		const b11 = be[ 0 ], b12 = be[ 4 ], b13 = be[ 8 ], b14 = be[ 12 ];
10397		const b21 = be[ 1 ], b22 = be[ 5 ], b23 = be[ 9 ], b24 = be[ 13 ];
10398		const b31 = be[ 2 ], b32 = be[ 6 ], b33 = be[ 10 ], b34 = be[ 14 ];
10399		const b41 = be[ 3 ], b42 = be[ 7 ], b43 = be[ 11 ], b44 = be[ 15 ];
10400
10401		te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
10402		te[ 4 ] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
10403		te[ 8 ] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
10404		te[ 12 ] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
10405
10406		te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
10407		te[ 5 ] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
10408		te[ 9 ] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
10409		te[ 13 ] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
10410
10411		te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
10412		te[ 6 ] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
10413		te[ 10 ] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
10414		te[ 14 ] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
10415
10416		te[ 3 ] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
10417		te[ 7 ] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
10418		te[ 11 ] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
10419		te[ 15 ] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
10420
10421		return this;
10422
10423	}
10424
10425	/**
10426	 * Multiplies every component of the matrix by the given scalar.
10427	 *
10428	 * @param {number} s - The scalar.
10429	 * @return {Matrix4} A reference to this matrix.
10430	 */
10431	multiplyScalar( s ) {
10432
10433		const te = this.elements;
10434
10435		te[ 0 ] *= s; te[ 4 ] *= s; te[ 8 ] *= s; te[ 12 ] *= s;
10436		te[ 1 ] *= s; te[ 5 ] *= s; te[ 9 ] *= s; te[ 13 ] *= s;
10437		te[ 2 ] *= s; te[ 6 ] *= s; te[ 10 ] *= s; te[ 14 ] *= s;
10438		te[ 3 ] *= s; te[ 7 ] *= s; te[ 11 ] *= s; te[ 15 ] *= s;
10439
10440		return this;
10441
10442	}
10443
10444	/**
10445	 * Computes and returns the determinant of this matrix.
10446	 *
10447	 * Based on the method outlined [here](http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.html).
10448	 *
10449	 * @return {number} The determinant.
10450	 */
10451	determinant() {
10452
10453		const te = this.elements;
10454
10455		const n11 = te[ 0 ], n12 = te[ 4 ], n13 = te[ 8 ], n14 = te[ 12 ];
10456		const n21 = te[ 1 ], n22 = te[ 5 ], n23 = te[ 9 ], n24 = te[ 13 ];
10457		const n31 = te[ 2 ], n32 = te[ 6 ], n33 = te[ 10 ], n34 = te[ 14 ];
10458		const n41 = te[ 3 ], n42 = te[ 7 ], n43 = te[ 11 ], n44 = te[ 15 ];
10459
10460		const t11 = n23 * n34 - n24 * n33;
10461		const t12 = n22 * n34 - n24 * n32;
10462		const t13 = n22 * n33 - n23 * n32;
10463
10464		const t21 = n21 * n34 - n24 * n31;
10465		const t22 = n21 * n33 - n23 * n31;
10466		const t23 = n21 * n32 - n22 * n31;
10467
10468		return n11 * ( n42 * t11 - n43 * t12 + n44 * t13 ) -
10469			n12 * ( n41 * t11 - n43 * t21 + n44 * t22 ) +
10470			n13 * ( n41 * t12 - n42 * t21 + n44 * t23 ) -
10471			n14 * ( n41 * t13 - n42 * t22 + n43 * t23 );
10472
10473	}
10474
10475	/**
10476	 * Transposes this matrix in place.
10477	 *
10478	 * @return {Matrix4} A reference to this matrix.
10479	 */
10480	transpose() {
10481
10482		const te = this.elements;
10483		let tmp;
10484
10485		tmp = te[ 1 ]; te[ 1 ] = te[ 4 ]; te[ 4 ] = tmp;
10486		tmp = te[ 2 ]; te[ 2 ] = te[ 8 ]; te[ 8 ] = tmp;
10487		tmp = te[ 6 ]; te[ 6 ] = te[ 9 ]; te[ 9 ] = tmp;
10488
10489		tmp = te[ 3 ]; te[ 3 ] = te[ 12 ]; te[ 12 ] = tmp;
10490		tmp = te[ 7 ]; te[ 7 ] = te[ 13 ]; te[ 13 ] = tmp;
10491		tmp = te[ 11 ]; te[ 11 ] = te[ 14 ]; te[ 14 ] = tmp;
10492
10493		return this;
10494
10495	}
10496
10497	/**
10498	 * Sets the position component for this matrix from the given vector,
10499	 * without affecting the rest of the matrix.
10500	 *
10501	 * @param {number|Vector3} x - The x component of the vector or alternatively the vector object.
10502	 * @param {number} y - The y component of the vector.
10503	 * @param {number} z - The z component of the vector.
10504	 * @return {Matrix4} A reference to this matrix.
10505	 */
10506	setPosition( x, y, z ) {
10507
10508		const te = this.elements;
10509
10510		if ( x.isVector3 ) {
10511
10512			te[ 12 ] = x.x;
10513			te[ 13 ] = x.y;
10514			te[ 14 ] = x.z;
10515
10516		} else {
10517
10518			te[ 12 ] = x;
10519			te[ 13 ] = y;
10520			te[ 14 ] = z;
10521
10522		}
10523
10524		return this;
10525
10526	}
10527
10528	/**
10529	 * Inverts this matrix, using the [analytic method](https://en.wikipedia.org/wiki/Invertible_matrix#Analytic_solution).
10530	 * You can not invert with a determinant of zero. If you attempt this, the method produces
10531	 * a zero matrix instead.
10532	 *
10533	 * @return {Matrix4} A reference to this matrix.
10534	 */
10535	invert() {
10536
10537		// based on https://github.com/toji/gl-matrix
10538		const te = this.elements,
10539
10540			n11 = te[ 0 ], n21 = te[ 1 ], n31 = te[ 2 ], n41 = te[ 3 ],
10541			n12 = te[ 4 ], n22 = te[ 5 ], n32 = te[ 6 ], n42 = te[ 7 ],
10542			n13 = te[ 8 ], n23 = te[ 9 ], n33 = te[ 10 ], n43 = te[ 11 ],
10543			n14 = te[ 12 ], n24 = te[ 13 ], n34 = te[ 14 ], n44 = te[ 15 ],
10544
10545			t1 = n11 * n22 - n21 * n12,
10546			t2 = n11 * n32 - n31 * n12,
10547			t3 = n11 * n42 - n41 * n12,
10548			t4 = n21 * n32 - n31 * n22,
10549			t5 = n21 * n42 - n41 * n22,
10550			t6 = n31 * n42 - n41 * n32,
10551			t7 = n13 * n24 - n23 * n14,
10552			t8 = n13 * n34 - n33 * n14,
10553			t9 = n13 * n44 - n43 * n14,
10554			t10 = n23 * n34 - n33 * n24,
10555			t11 = n23 * n44 - n43 * n24,
10556			t12 = n33 * n44 - n43 * n34;
10557
10558		const det = t1 * t12 - t2 * t11 + t3 * t10 + t4 * t9 - t5 * t8 + t6 * t7;
10559
10560		if ( det === 0 ) return this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
10561
10562		const detInv = 1 / det;
10563
10564		te[ 0 ] = ( n22 * t12 - n32 * t11 + n42 * t10 ) * detInv;
10565		te[ 1 ] = ( n31 * t11 - n21 * t12 - n41 * t10 ) * detInv;
10566		te[ 2 ] = ( n24 * t6 - n34 * t5 + n44 * t4 ) * detInv;
10567		te[ 3 ] = ( n33 * t5 - n23 * t6 - n43 * t4 ) * detInv;
10568
10569		te[ 4 ] = ( n32 * t9 - n12 * t12 - n42 * t8 ) * detInv;
10570		te[ 5 ] = ( n11 * t12 - n31 * t9 + n41 * t8 ) * detInv;
10571		te[ 6 ] = ( n34 * t3 - n14 * t6 - n44 * t2 ) * detInv;
10572		te[ 7 ] = ( n13 * t6 - n33 * t3 + n43 * t2 ) * detInv;
10573
10574		te[ 8 ] = ( n12 * t11 - n22 * t9 + n42 * t7 ) * detInv;
10575		te[ 9 ] = ( n21 * t9 - n11 * t11 - n41 * t7 ) * detInv;
10576		te[ 10 ] = ( n14 * t5 - n24 * t3 + n44 * t1 ) * detInv;
10577		te[ 11 ] = ( n23 * t3 - n13 * t5 - n43 * t1 ) * detInv;
10578
10579		te[ 12 ] = ( n22 * t8 - n12 * t10 - n32 * t7 ) * detInv;
10580		te[ 13 ] = ( n11 * t10 - n21 * t8 + n31 * t7 ) * detInv;
10581		te[ 14 ] = ( n24 * t2 - n14 * t4 - n34 * t1 ) * detInv;
10582		te[ 15 ] = ( n13 * t4 - n23 * t2 + n33 * t1 ) * detInv;
10583
10584		return this;
10585
10586	}
10587
10588	/**
10589	 * Multiplies the columns of this matrix by the given vector.
10590	 *
10591	 * @param {Vector3} v - The scale vector.
10592	 * @return {Matrix4} A reference to this matrix.
10593	 */
10594	scale( v ) {
10595
10596		const te = this.elements;
10597		const x = v.x, y = v.y, z = v.z;
10598
10599		te[ 0 ] *= x; te[ 4 ] *= y; te[ 8 ] *= z;
10600		te[ 1 ] *= x; te[ 5 ] *= y; te[ 9 ] *= z;
10601		te[ 2 ] *= x; te[ 6 ] *= y; te[ 10 ] *= z;
10602		te[ 3 ] *= x; te[ 7 ] *= y; te[ 11 ] *= z;
10603
10604		return this;
10605
10606	}
10607
10608	/**
10609	 * Gets the maximum scale value of the three axes.
10610	 *
10611	 * @return {number} The maximum scale.
10612	 */
10613	getMaxScaleOnAxis() {
10614
10615		const te = this.elements;
10616
10617		const scaleXSq = te[ 0 ] * te[ 0 ] + te[ 1 ] * te[ 1 ] + te[ 2 ] * te[ 2 ];
10618		const scaleYSq = te[ 4 ] * te[ 4 ] + te[ 5 ] * te[ 5 ] + te[ 6 ] * te[ 6 ];
10619		const scaleZSq = te[ 8 ] * te[ 8 ] + te[ 9 ] * te[ 9 ] + te[ 10 ] * te[ 10 ];
10620
10621		return Math.sqrt( Math.max( scaleXSq, scaleYSq, scaleZSq ) );
10622
10623	}
10624
10625	/**
10626	 * Sets this matrix as a translation transform from the given vector.
10627	 *
10628	 * @param {number|Vector3} x - The amount to translate in the X axis or alternatively a translation vector.
10629	 * @param {number} y - The amount to translate in the Y axis.
10630	 * @param {number} z - The amount to translate in the z axis.
10631	 * @return {Matrix4} A reference to this matrix.
10632	 */
10633	makeTranslation( x, y, z ) {
10634
10635		if ( x.isVector3 ) {
10636
10637			this.set(
10638
10639				1, 0, 0, x.x,
10640				0, 1, 0, x.y,
10641				0, 0, 1, x.z,
10642				0, 0, 0, 1
10643
10644			);
10645
10646		} else {
10647
10648			this.set(
10649
10650				1, 0, 0, x,
10651				0, 1, 0, y,
10652				0, 0, 1, z,
10653				0, 0, 0, 1
10654
10655			);
10656
10657		}
10658
10659		return this;
10660
10661	}
10662
10663	/**
10664	 * Sets this matrix as a rotational transformation around the X axis by
10665	 * the given angle.
10666	 *
10667	 * @param {number} theta - The rotation in radians.
10668	 * @return {Matrix4} A reference to this matrix.
10669	 */
10670	makeRotationX( theta ) {
10671
10672		const c = Math.cos( theta ), s = Math.sin( theta );
10673
10674		this.set(
10675
10676			1, 0, 0, 0,
10677			0, c, - s, 0,
10678			0, s, c, 0,
10679			0, 0, 0, 1
10680
10681		);
10682
10683		return this;
10684
10685	}
10686
10687	/**
10688	 * Sets this matrix as a rotational transformation around the Y axis by
10689	 * the given angle.
10690	 *
10691	 * @param {number} theta - The rotation in radians.
10692	 * @return {Matrix4} A reference to this matrix.
10693	 */
10694	makeRotationY( theta ) {
10695
10696		const c = Math.cos( theta ), s = Math.sin( theta );
10697
10698		this.set(
10699
10700			 c, 0, s, 0,
10701			 0, 1, 0, 0,
10702			- s, 0, c, 0,
10703			 0, 0, 0, 1
10704
10705		);
10706
10707		return this;
10708
10709	}
10710
10711	/**
10712	 * Sets this matrix as a rotational transformation around the Z axis by
10713	 * the given angle.
10714	 *
10715	 * @param {number} theta - The rotation in radians.
10716	 * @return {Matrix4} A reference to this matrix.
10717	 */
10718	makeRotationZ( theta ) {
10719
10720		const c = Math.cos( theta ), s = Math.sin( theta );
10721
10722		this.set(
10723
10724			c, - s, 0, 0,
10725			s, c, 0, 0,
10726			0, 0, 1, 0,
10727			0, 0, 0, 1
10728
10729		);
10730
10731		return this;
10732
10733	}
10734
10735	/**
10736	 * Sets this matrix as a rotational transformation around the given axis by
10737	 * the given angle.
10738	 *
10739	 * This is a somewhat controversial but mathematically sound alternative to
10740	 * rotating via Quaternions. See the discussion [here](https://www.gamedev.net/articles/programming/math-and-physics/do-we-really-need-quaternions-r1199).
10741	 *
10742	 * @param {Vector3} axis - The normalized rotation axis.
10743	 * @param {number} angle - The rotation in radians.
10744	 * @return {Matrix4} A reference to this matrix.
10745	 */
10746	makeRotationAxis( axis, angle ) {
10747
10748		// Based on http://www.gamedev.net/reference/articles/article1199.asp
10749
10750		const c = Math.cos( angle );
10751		const s = Math.sin( angle );
10752		const t = 1 - c;
10753		const x = axis.x, y = axis.y, z = axis.z;
10754		const tx = t * x, ty = t * y;
10755
10756		this.set(
10757
10758			tx * x + c, tx * y - s * z, tx * z + s * y, 0,
10759			tx * y + s * z, ty * y + c, ty * z - s * x, 0,
10760			tx * z - s * y, ty * z + s * x, t * z * z + c, 0,
10761			0, 0, 0, 1
10762
10763		);
10764
10765		return this;
10766
10767	}
10768
10769	/**
10770	 * Sets this matrix as a scale transformation.
10771	 *
10772	 * @param {number} x - The amount to scale in the X axis.
10773	 * @param {number} y - The amount to scale in the Y axis.
10774	 * @param {number} z - The amount to scale in the Z axis.
10775	 * @return {Matrix4} A reference to this matrix.
10776	 */
10777	makeScale( x, y, z ) {
10778
10779		this.set(
10780
10781			x, 0, 0, 0,
10782			0, y, 0, 0,
10783			0, 0, z, 0,
10784			0, 0, 0, 1
10785
10786		);
10787
10788		return this;
10789
10790	}
10791
10792	/**
10793	 * Sets this matrix as a shear transformation.
10794	 *
10795	 * @param {number} xy - The amount to shear X by Y.
10796	 * @param {number} xz - The amount to shear X by Z.
10797	 * @param {number} yx - The amount to shear Y by X.
10798	 * @param {number} yz - The amount to shear Y by Z.
10799	 * @param {number} zx - The amount to shear Z by X.
10800	 * @param {number} zy - The amount to shear Z by Y.
10801	 * @return {Matrix4} A reference to this matrix.
10802	 */
10803	makeShear( xy, xz, yx, yz, zx, zy ) {
10804
10805		this.set(
10806
10807			1, yx, zx, 0,
10808			xy, 1, zy, 0,
10809			xz, yz, 1, 0,
10810			0, 0, 0, 1
10811
10812		);
10813
10814		return this;
10815
10816	}
10817
10818	/**
10819	 * Sets this matrix to the transformation composed of the given position,
10820	 * rotation (Quaternion) and scale.
10821	 *
10822	 * @param {Vector3} position - The position vector.
10823	 * @param {Quaternion} quaternion - The rotation as a Quaternion.
10824	 * @param {Vector3} scale - The scale vector.
10825	 * @return {Matrix4} A reference to this matrix.
10826	 */
10827	compose( position, quaternion, scale ) {
10828
10829		const te = this.elements;
10830
10831		const x = quaternion._x, y = quaternion._y, z = quaternion._z, w = quaternion._w;
10832		const x2 = x + x,	y2 = y + y, z2 = z + z;
10833		const xx = x * x2, xy = x * y2, xz = x * z2;
10834		const yy = y * y2, yz = y * z2, zz = z * z2;
10835		const wx = w * x2, wy = w * y2, wz = w * z2;
10836
10837		const sx = scale.x, sy = scale.y, sz = scale.z;
10838
10839		te[ 0 ] = ( 1 - ( yy + zz ) ) * sx;
10840		te[ 1 ] = ( xy + wz ) * sx;
10841		te[ 2 ] = ( xz - wy ) * sx;
10842		te[ 3 ] = 0;
10843
10844		te[ 4 ] = ( xy - wz ) * sy;
10845		te[ 5 ] = ( 1 - ( xx + zz ) ) * sy;
10846		te[ 6 ] = ( yz + wx ) * sy;
10847		te[ 7 ] = 0;
10848
10849		te[ 8 ] = ( xz + wy ) * sz;
10850		te[ 9 ] = ( yz - wx ) * sz;
10851		te[ 10 ] = ( 1 - ( xx + yy ) ) * sz;
10852		te[ 11 ] = 0;
10853
10854		te[ 12 ] = position.x;
10855		te[ 13 ] = position.y;
10856		te[ 14 ] = position.z;
10857		te[ 15 ] = 1;
10858
10859		return this;
10860
10861	}
10862
10863	/**
10864	 * Decomposes this matrix into its position, rotation and scale components
10865	 * and provides the result in the given objects.
10866	 *
10867	 * Note: Not all matrices are decomposable in this way. For example, if an
10868	 * object has a non-uniformly scaled parent, then the object's world matrix
10869	 * may not be decomposable, and this method may not be appropriate.
10870	 *
10871	 * @param {Vector3} position - The position vector.
10872	 * @param {Quaternion} quaternion - The rotation as a Quaternion.
10873	 * @param {Vector3} scale - The scale vector.
10874	 * @return {Matrix4} A reference to this matrix.
10875	 */
10876	decompose( position, quaternion, scale ) {
10877
10878		const te = this.elements;
10879
10880		position.x = te[ 12 ];
10881		position.y = te[ 13 ];
10882		position.z = te[ 14 ];
10883
10884		const det = this.determinant();
10885
10886		if ( det === 0 ) {
10887
10888			scale.set( 1, 1, 1 );
10889			quaternion.identity();
10890
10891			return this;
10892
10893		}
10894
10895		let sx = _v1$7.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length();
10896		const sy = _v1$7.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length();
10897		const sz = _v1$7.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length();
10898
10899		// if determinant is negative, we need to invert one scale
10900		if ( det < 0 ) sx = - sx;
10901
10902		// scale the rotation part
10903		_m1$2.copy( this );
10904
10905		const invSX = 1 / sx;
10906		const invSY = 1 / sy;
10907		const invSZ = 1 / sz;
10908
10909		_m1$2.elements[ 0 ] *= invSX;
10910		_m1$2.elements[ 1 ] *= invSX;
10911		_m1$2.elements[ 2 ] *= invSX;
10912
10913		_m1$2.elements[ 4 ] *= invSY;
10914		_m1$2.elements[ 5 ] *= invSY;
10915		_m1$2.elements[ 6 ] *= invSY;
10916
10917		_m1$2.elements[ 8 ] *= invSZ;
10918		_m1$2.elements[ 9 ] *= invSZ;
10919		_m1$2.elements[ 10 ] *= invSZ;
10920
10921		quaternion.setFromRotationMatrix( _m1$2 );
10922
10923		scale.x = sx;
10924		scale.y = sy;
10925		scale.z = sz;
10926
10927		return this;
10928
10929	}
10930
10931	/**
10932	 * Creates a perspective projection matrix. This is used internally by
10933	 * {@link PerspectiveCamera#updateProjectionMatrix}.
10934
10935	 * @param {number} left - Left boundary of the viewing frustum at the near plane.
10936	 * @param {number} right - Right boundary of the viewing frustum at the near plane.
10937	 * @param {number} top - Top boundary of the viewing frustum at the near plane.
10938	 * @param {number} bottom - Bottom boundary of the viewing frustum at the near plane.
10939	 * @param {number} near - The distance from the camera to the near plane.
10940	 * @param {number} far - The distance from the camera to the far plane.
10941	 * @param {(WebGLCoordinateSystem|WebGPUCoordinateSystem)} [coordinateSystem=WebGLCoordinateSystem] - The coordinate system.
10942	 * @param {boolean} [reversedDepth=false] - Whether to use a reversed depth.
10943	 * @return {Matrix4} A reference to this matrix.
10944	 */
10945	makePerspective( left, right, top, bottom, near, far, coordinateSystem = WebGLCoordinateSystem, reversedDepth = false ) {
10946
10947		const te = this.elements;
10948
10949		const x = 2 * near / ( right - left );
10950		const y = 2 * near / ( top - bottom );
10951
10952		const a = ( right + left ) / ( right - left );
10953		const b = ( top + bottom ) / ( top - bottom );
10954
10955		let c, d;
10956
10957		if ( reversedDepth ) {
10958
10959			c = near / ( far - near );
10960			d = ( far * near ) / ( far - near );
10961
10962		} else {
10963
10964			if ( coordinateSystem === WebGLCoordinateSystem ) {
10965
10966				c = - ( far + near ) / ( far - near );
10967				d = ( -2 * far * near ) / ( far - near );
10968
10969			} else if ( coordinateSystem === WebGPUCoordinateSystem ) {
10970
10971				c = - far / ( far - near );
10972				d = ( - far * near ) / ( far - near );
10973
10974			} else {
10975
10976				throw new Error( 'THREE.Matrix4.makePerspective(): Invalid coordinate system: ' + coordinateSystem );
10977
10978			}
10979
10980		}
10981
10982		te[ 0 ] = x;	te[ 4 ] = 0;	te[ 8 ] = a; 	te[ 12 ] = 0;
10983		te[ 1 ] = 0;	te[ 5 ] = y;	te[ 9 ] = b; 	te[ 13 ] = 0;
10984		te[ 2 ] = 0;	te[ 6 ] = 0;	te[ 10 ] = c; 	te[ 14 ] = d;
10985		te[ 3 ] = 0;	te[ 7 ] = 0;	te[ 11 ] = -1;	te[ 15 ] = 0;
10986
10987		return this;
10988
10989	}
10990
10991	/**
10992	 * Creates a orthographic projection matrix. This is used internally by
10993	 * {@link OrthographicCamera#updateProjectionMatrix}.
10994
10995	 * @param {number} left - Left boundary of the viewing frustum at the near plane.
10996	 * @param {number} right - Right boundary of the viewing frustum at the near plane.
10997	 * @param {number} top - Top boundary of the viewing frustum at the near plane.
10998	 * @param {number} bottom - Bottom boundary of the viewing frustum at the near plane.
10999	 * @param {number} near - The distance from the camera to the near plane.
11000	 * @param {number} far - The distance from the camera to the far plane.
11001	 * @param {(WebGLCoordinateSystem|WebGPUCoordinateSystem)} [coordinateSystem=WebGLCoordinateSystem] - The coordinate system.
11002	 * @param {boolean} [reversedDepth=false] - Whether to use a reversed depth.
11003	 * @return {Matrix4} A reference to this matrix.
11004	 */
11005	makeOrthographic( left, right, top, bottom, near, far, coordinateSystem = WebGLCoordinateSystem, reversedDepth = false ) {
11006
11007		const te = this.elements;
11008
11009		const x = 2 / ( right - left );
11010		const y = 2 / ( top - bottom );
11011
11012		const a = - ( right + left ) / ( right - left );
11013		const b = - ( top + bottom ) / ( top - bottom );
11014
11015		let c, d;
11016
11017		if ( reversedDepth ) {
11018
11019			c = 1 / ( far - near );
11020			d = far / ( far - near );
11021
11022		} else {
11023
11024			if ( coordinateSystem === WebGLCoordinateSystem ) {
11025
11026				c = -2 / ( far - near );
11027				d = - ( far + near ) / ( far - near );
11028
11029			} else if ( coordinateSystem === WebGPUCoordinateSystem ) {
11030
11031				c = -1 / ( far - near );
11032				d = - near / ( far - near );
11033
11034			} else {
11035
11036				throw new Error( 'THREE.Matrix4.makeOrthographic(): Invalid coordinate system: ' + coordinateSystem );
11037
11038			}
11039
11040		}
11041
11042		te[ 0 ] = x;		te[ 4 ] = 0;		te[ 8 ] = 0; 		te[ 12 ] = a;
11043		te[ 1 ] = 0; 		te[ 5 ] = y;		te[ 9 ] = 0; 		te[ 13 ] = b;
11044		te[ 2 ] = 0; 		te[ 6 ] = 0;		te[ 10 ] = c;		te[ 14 ] = d;
11045		te[ 3 ] = 0; 		te[ 7 ] = 0;		te[ 11 ] = 0;		te[ 15 ] = 1;
11046
11047		return this;
11048
11049	}
11050
11051	/**
11052	 * Returns `true` if this matrix is equal with the given one.
11053	 *
11054	 * @param {Matrix4} matrix - The matrix to test for equality.
11055	 * @return {boolean} Whether this matrix is equal with the given one.
11056	 */
11057	equals( matrix ) {
11058
11059		const te = this.elements;
11060		const me = matrix.elements;
11061
11062		for ( let i = 0; i < 16; i ++ ) {
11063
11064			if ( te[ i ] !== me[ i ] ) return false;
11065
11066		}
11067
11068		return true;
11069
11070	}
11071
11072	/**
11073	 * Sets the elements of the matrix from the given array.
11074	 *
11075	 * @param {Array<number>} array - The matrix elements in column-major order.
11076	 * @param {number} [offset=0] - Index of the first element in the array.
11077	 * @return {Matrix4} A reference to this matrix.
11078	 */
11079	fromArray( array, offset = 0 ) {
11080
11081		for ( let i = 0; i < 16; i ++ ) {
11082
11083			this.elements[ i ] = array[ i + offset ];
11084
11085		}
11086
11087		return this;
11088
11089	}
11090
11091	/**
11092	 * Writes the elements of this matrix to the given array. If no array is provided,
11093	 * the method returns a new instance.
11094	 *
11095	 * @param {Array<number>} [array=[]] - The target array holding the matrix elements in column-major order.
11096	 * @param {number} [offset=0] - Index of the first element in the array.
11097	 * @return {Array<number>} The matrix elements in column-major order.
11098	 */
11099	toArray( array = [], offset = 0 ) {
11100
11101		const te = this.elements;
11102
11103		array[ offset ] = te[ 0 ];
11104		array[ offset + 1 ] = te[ 1 ];
11105		array[ offset + 2 ] = te[ 2 ];
11106		array[ offset + 3 ] = te[ 3 ];
11107
11108		array[ offset + 4 ] = te[ 4 ];
11109		array[ offset + 5 ] = te[ 5 ];
11110		array[ offset + 6 ] = te[ 6 ];
11111		array[ offset + 7 ] = te[ 7 ];
11112
11113		array[ offset + 8 ] = te[ 8 ];
11114		array[ offset + 9 ] = te[ 9 ];
11115		array[ offset + 10 ] = te[ 10 ];
11116		array[ offset + 11 ] = te[ 11 ];
11117
11118		array[ offset + 12 ] = te[ 12 ];
11119		array[ offset + 13 ] = te[ 13 ];
11120		array[ offset + 14 ] = te[ 14 ];
11121		array[ offset + 15 ] = te[ 15 ];
11122
11123		return array;
11124
11125	}
11126
11127}
11128
11129const _v1$7 = /*@__PURE__*/ new Vector3();
11130const _m1$2 = /*@__PURE__*/ new Matrix4();
11131const _zero = /*@__PURE__*/ new Vector3( 0, 0, 0 );
11132const _one = /*@__PURE__*/ new Vector3( 1, 1, 1 );
11133const _x = /*@__PURE__*/ new Vector3();
11134const _y = /*@__PURE__*/ new Vector3();
11135const _z = /*@__PURE__*/ new Vector3();
11136
11137const _matrix$2 = /*@__PURE__*/ new Matrix4();
11138const _quaternion$4 = /*@__PURE__*/ new Quaternion();
11139
11140/**
11141 * A class representing Euler angles.
11142 *
11143 * Euler angles describe a rotational transformation by rotating an object on
11144 * its various axes in specified amounts per axis, and a specified axis
11145 * order.
11146 *
11147 * Iterating through an instance will yield its components (x, y, z,
11148 * order) in the corresponding order.
11149 *
11150 * ```js
11151 * const a = new THREE.Euler( 0, 1, 1.57, 'XYZ' );
11152 * const b = new THREE.Vector3( 1, 0, 1 );
11153 * b.applyEuler(a);
11154 * ```
11155 */
11156class Euler {
11157
11158	/**
11159	 * Constructs a new euler instance.
11160	 *
11161	 * @param {number} [x=0] - The angle of the x axis in radians.
11162	 * @param {number} [y=0] - The angle of the y axis in radians.
11163	 * @param {number} [z=0] - The angle of the z axis in radians.
11164	 * @param {string} [order=Euler.DEFAULT_ORDER] - A string representing the order that the rotations are applied.
11165	 */
11166	constructor( x = 0, y = 0, z = 0, order = Euler.DEFAULT_ORDER ) {
11167
11168		/**
11169		 * This flag can be used for type testing.
11170		 *
11171		 * @type {boolean}
11172		 * @readonly
11173		 * @default true
11174		 */
11175		this.isEuler = true;
11176
11177		this._x = x;
11178		this._y = y;
11179		this._z = z;
11180		this._order = order;
11181
11182	}
11183
vendor: 33,636 bytes, lines 11184-12659
11184	/**
11185	 * The angle of the x axis in radians.
11186	 *
11187	 * @type {number}
11188	 * @default 0
11189	 */
11190	get x() {
11191
11192		return this._x;
11193
11194	}
11195
11196	set x( value ) {
11197
11198		this._x = value;
11199		this._onChangeCallback();
11200
11201	}
11202
11203	/**
11204	 * The angle of the y axis in radians.
11205	 *
11206	 * @type {number}
11207	 * @default 0
11208	 */
11209	get y() {
11210
11211		return this._y;
11212
11213	}
11214
11215	set y( value ) {
11216
11217		this._y = value;
11218		this._onChangeCallback();
11219
11220	}
11221
11222	/**
11223	 * The angle of the z axis in radians.
11224	 *
11225	 * @type {number}
11226	 * @default 0
11227	 */
11228	get z() {
11229
11230		return this._z;
11231
11232	}
11233
11234	set z( value ) {
11235
11236		this._z = value;
11237		this._onChangeCallback();
11238
11239	}
11240
11241	/**
11242	 * A string representing the order that the rotations are applied.
11243	 *
11244	 * @type {string}
11245	 * @default 'XYZ'
11246	 */
11247	get order() {
11248
11249		return this._order;
11250
11251	}
11252
11253	set order( value ) {
11254
11255		this._order = value;
11256		this._onChangeCallback();
11257
11258	}
11259
11260	/**
11261	 * Sets the Euler components.
11262	 *
11263	 * @param {number} x - The angle of the x axis in radians.
11264	 * @param {number} y - The angle of the y axis in radians.
11265	 * @param {number} z - The angle of the z axis in radians.
11266	 * @param {string} [order] - A string representing the order that the rotations are applied.
11267	 * @return {Euler} A reference to this Euler instance.
11268	 */
11269	set( x, y, z, order = this._order ) {
11270
11271		this._x = x;
11272		this._y = y;
11273		this._z = z;
11274		this._order = order;
11275
11276		this._onChangeCallback();
11277
11278		return this;
11279
11280	}
11281
11282	/**
11283	 * Returns a new Euler instance with copied values from this instance.
11284	 *
11285	 * @return {Euler} A clone of this instance.
11286	 */
11287	clone() {
11288
11289		return new this.constructor( this._x, this._y, this._z, this._order );
11290
11291	}
11292
11293	/**
11294	 * Copies the values of the given Euler instance to this instance.
11295	 *
11296	 * @param {Euler} euler - The Euler instance to copy.
11297	 * @return {Euler} A reference to this Euler instance.
11298	 */
11299	copy( euler ) {
11300
11301		this._x = euler._x;
11302		this._y = euler._y;
11303		this._z = euler._z;
11304		this._order = euler._order;
11305
11306		this._onChangeCallback();
11307
11308		return this;
11309
11310	}
11311
11312	/**
11313	 * Sets the angles of this Euler instance from a pure rotation matrix.
11314	 *
11315	 * @param {Matrix4} m - A 4x4 matrix of which the upper 3x3 of matrix is a pure rotation matrix (i.e. unscaled).
11316	 * @param {string} [order] - A string representing the order that the rotations are applied.
11317	 * @param {boolean} [update=true] - Whether the internal `onChange` callback should be executed or not.
11318	 * @return {Euler} A reference to this Euler instance.
11319	 */
11320	setFromRotationMatrix( m, order = this._order, update = true ) {
11321
11322		const te = m.elements;
11323		const m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ];
11324		const m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ];
11325		const m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
11326
11327		switch ( order ) {
11328
11329			case 'XYZ':
11330
11331				this._y = Math.asin( clamp( m13, -1, 1 ) );
11332
11333				if ( Math.abs( m13 ) < 0.9999999 ) {
11334
11335					this._x = Math.atan2( - m23, m33 );
11336					this._z = Math.atan2( - m12, m11 );
11337
11338				} else {
11339
11340					this._x = Math.atan2( m32, m22 );
11341					this._z = 0;
11342
11343				}
11344
11345				break;
11346
11347			case 'YXZ':
11348
11349				this._x = Math.asin( - clamp( m23, -1, 1 ) );
11350
11351				if ( Math.abs( m23 ) < 0.9999999 ) {
11352
11353					this._y = Math.atan2( m13, m33 );
11354					this._z = Math.atan2( m21, m22 );
11355
11356				} else {
11357
11358					this._y = Math.atan2( - m31, m11 );
11359					this._z = 0;
11360
11361				}
11362
11363				break;
11364
11365			case 'ZXY':
11366
11367				this._x = Math.asin( clamp( m32, -1, 1 ) );
11368
11369				if ( Math.abs( m32 ) < 0.9999999 ) {
11370
11371					this._y = Math.atan2( - m31, m33 );
11372					this._z = Math.atan2( - m12, m22 );
11373
11374				} else {
11375
11376					this._y = 0;
11377					this._z = Math.atan2( m21, m11 );
11378
11379				}
11380
11381				break;
11382
11383			case 'ZYX':
11384
11385				this._y = Math.asin( - clamp( m31, -1, 1 ) );
11386
11387				if ( Math.abs( m31 ) < 0.9999999 ) {
11388
11389					this._x = Math.atan2( m32, m33 );
11390					this._z = Math.atan2( m21, m11 );
11391
11392				} else {
11393
11394					this._x = 0;
11395					this._z = Math.atan2( - m12, m22 );
11396
11397				}
11398
11399				break;
11400
11401			case 'YZX':
11402
11403				this._z = Math.asin( clamp( m21, -1, 1 ) );
11404
11405				if ( Math.abs( m21 ) < 0.9999999 ) {
11406
11407					this._x = Math.atan2( - m23, m22 );
11408					this._y = Math.atan2( - m31, m11 );
11409
11410				} else {
11411
11412					this._x = 0;
11413					this._y = Math.atan2( m13, m33 );
11414
11415				}
11416
11417				break;
11418
11419			case 'XZY':
11420
11421				this._z = Math.asin( - clamp( m12, -1, 1 ) );
11422
11423				if ( Math.abs( m12 ) < 0.9999999 ) {
11424
11425					this._x = Math.atan2( m32, m22 );
11426					this._y = Math.atan2( m13, m11 );
11427
11428				} else {
11429
11430					this._x = Math.atan2( - m23, m33 );
11431					this._y = 0;
11432
11433				}
11434
11435				break;
11436
11437			default:
11438
11439				warn( 'Euler: .setFromRotationMatrix() encountered an unknown order: ' + order );
11440
11441		}
11442
11443		this._order = order;
11444
11445		if ( update === true ) this._onChangeCallback();
11446
11447		return this;
11448
11449	}
11450
11451	/**
11452	 * Sets the angles of this Euler instance from a normalized quaternion.
11453	 *
11454	 * @param {Quaternion} q - A normalized Quaternion.
11455	 * @param {string} [order] - A string representing the order that the rotations are applied.
11456	 * @param {boolean} [update=true] - Whether the internal `onChange` callback should be executed or not.
11457	 * @return {Euler} A reference to this Euler instance.
11458	 */
11459	setFromQuaternion( q, order, update ) {
11460
11461		_matrix$2.makeRotationFromQuaternion( q );
11462
11463		return this.setFromRotationMatrix( _matrix$2, order, update );
11464
11465	}
11466
11467	/**
11468	 * Sets the angles of this Euler instance from the given vector.
11469	 *
11470	 * @param {Vector3} v - The vector.
11471	 * @param {string} [order] - A string representing the order that the rotations are applied.
11472	 * @return {Euler} A reference to this Euler instance.
11473	 */
11474	setFromVector3( v, order = this._order ) {
11475
11476		return this.set( v.x, v.y, v.z, order );
11477
11478	}
11479
11480	/**
11481	 * Resets the euler angle with a new order by creating a quaternion from this
11482	 * euler angle and then setting this euler angle with the quaternion and the
11483	 * new order.
11484	 *
11485	 * Warning: This discards revolution information.
11486	 *
11487	 * @param {string} [newOrder] - A string representing the new order that the rotations are applied.
11488	 * @return {Euler} A reference to this Euler instance.
11489	 */
11490	reorder( newOrder ) {
11491
11492		_quaternion$4.setFromEuler( this );
11493
11494		return this.setFromQuaternion( _quaternion$4, newOrder );
11495
11496	}
11497
11498	/**
11499	 * Returns `true` if this Euler instance is equal with the given one.
11500	 *
11501	 * @param {Euler} euler - The Euler instance to test for equality.
11502	 * @return {boolean} Whether this Euler instance is equal with the given one.
11503	 */
11504	equals( euler ) {
11505
11506		return ( euler._x === this._x ) && ( euler._y === this._y ) && ( euler._z === this._z ) && ( euler._order === this._order );
11507
11508	}
11509
11510	/**
11511	 * Sets this Euler instance's components to values from the given array. The first three
11512	 * entries of the array are assign to the x,y and z components. An optional fourth entry
11513	 * defines the Euler order.
11514	 *
11515	 * @param {Array<number,number,number,?string>} array - An array holding the Euler component values.
11516	 * @return {Euler} A reference to this Euler instance.
11517	 */
11518	fromArray( array ) {
11519
11520		this._x = array[ 0 ];
11521		this._y = array[ 1 ];
11522		this._z = array[ 2 ];
11523		if ( array[ 3 ] !== undefined ) this._order = array[ 3 ];
11524
11525		this._onChangeCallback();
11526
11527		return this;
11528
11529	}
11530
11531	/**
11532	 * Writes the components of this Euler instance to the given array. If no array is provided,
11533	 * the method returns a new instance.
11534	 *
11535	 * @param {Array<number,number,number,string>} [array=[]] - The target array holding the Euler components.
11536	 * @param {number} [offset=0] - Index of the first element in the array.
11537	 * @return {Array<number,number,number,string>} The Euler components.
11538	 */
11539	toArray( array = [], offset = 0 ) {
11540
11541		array[ offset ] = this._x;
11542		array[ offset + 1 ] = this._y;
11543		array[ offset + 2 ] = this._z;
11544		array[ offset + 3 ] = this._order;
11545
11546		return array;
11547
11548	}
11549
11550	_onChange( callback ) {
11551
11552		this._onChangeCallback = callback;
11553
11554		return this;
11555
11556	}
11557
11558	_onChangeCallback() {}
11559
11560	*[ Symbol.iterator ]() {
11561
11562		yield this._x;
11563		yield this._y;
11564		yield this._z;
11565		yield this._order;
11566
11567	}
11568
11569}
11570
11571/**
11572 * The default Euler angle order.
11573 *
11574 * @static
11575 * @type {string}
11576 * @default 'XYZ'
11577 */
11578Euler.DEFAULT_ORDER = 'XYZ';
11579
11580/**
11581 * A layers object assigns an 3D object to 1 or more of 32
11582 * layers numbered `0` to `31` - internally the layers are stored as a
11583 * bit mask], and by default all 3D objects are a member of layer `0`.
11584 *
11585 * This can be used to control visibility - an object must share a layer with
11586 * a camera to be visible when that camera's view is
11587 * rendered.
11588 *
11589 * All classes that inherit from {@link Object3D} have an `layers` property which
11590 * is an instance of this class.
11591 */
11592class Layers {
11593
11594	/**
11595	 * Constructs a new layers instance, with membership
11596	 * initially set to layer `0`.
11597	 */
11598	constructor() {
11599
11600		/**
11601		 * A bit mask storing which of the 32 layers this layers object is currently
11602		 * a member of.
11603		 *
11604		 * @type {number}
11605		 */
11606		this.mask = 1 | 0;
11607
11608	}
11609
11610	/**
11611	 * Sets membership to the given layer, and remove membership all other layers.
11612	 *
11613	 * @param {number} layer - The layer to set.
11614	 */
11615	set( layer ) {
11616
11617		this.mask = ( 1 << layer | 0 ) >>> 0;
11618
11619	}
11620
11621	/**
11622	 * Adds membership of the given layer.
11623	 *
11624	 * @param {number} layer - The layer to enable.
11625	 */
11626	enable( layer ) {
11627
11628		this.mask |= 1 << layer | 0;
11629
11630	}
11631
11632	/**
11633	 * Adds membership to all layers.
11634	 */
11635	enableAll() {
11636
11637		this.mask = 0xffffffff | 0;
11638
11639	}
11640
11641	/**
11642	 * Toggles the membership of the given layer.
11643	 *
11644	 * @param {number} layer - The layer to toggle.
11645	 */
11646	toggle( layer ) {
11647
11648		this.mask ^= 1 << layer | 0;
11649
11650	}
11651
11652	/**
11653	 * Removes membership of the given layer.
11654	 *
11655	 * @param {number} layer - The layer to enable.
11656	 */
11657	disable( layer ) {
11658
11659		this.mask &= ~ ( 1 << layer | 0 );
11660
11661	}
11662
11663	/**
11664	 * Removes the membership from all layers.
11665	 */
11666	disableAll() {
11667
11668		this.mask = 0;
11669
11670	}
11671
11672	/**
11673	 * Returns `true` if this and the given layers object have at least one
11674	 * layer in common.
11675	 *
11676	 * @param {Layers} layers - The layers to test.
11677	 * @return {boolean } Whether this and the given layers object have at least one layer in common or not.
11678	 */
11679	test( layers ) {
11680
11681		return ( this.mask & layers.mask ) !== 0;
11682
11683	}
11684
11685	/**
11686	 * Returns `true` if the given layer is enabled.
11687	 *
11688	 * @param {number} layer - The layer to test.
11689	 * @return {boolean } Whether the given layer is enabled or not.
11690	 */
11691	isEnabled( layer ) {
11692
11693		return ( this.mask & ( 1 << layer | 0 ) ) !== 0;
11694
11695	}
11696
11697}
11698
11699let _object3DId = 0;
11700
11701const _v1$6 = /*@__PURE__*/ new Vector3();
11702const _q1 = /*@__PURE__*/ new Quaternion();
11703const _m1$1 = /*@__PURE__*/ new Matrix4();
11704const _target = /*@__PURE__*/ new Vector3();
11705
11706const _position$4 = /*@__PURE__*/ new Vector3();
11707const _scale$3 = /*@__PURE__*/ new Vector3();
11708const _quaternion$3 = /*@__PURE__*/ new Quaternion();
11709
11710const _xAxis = /*@__PURE__*/ new Vector3( 1, 0, 0 );
11711const _yAxis = /*@__PURE__*/ new Vector3( 0, 1, 0 );
11712const _zAxis = /*@__PURE__*/ new Vector3( 0, 0, 1 );
11713
11714/**
11715 * Fires when the object has been added to its parent object.
11716 *
11717 * @event Object3D#added
11718 * @type {Object}
11719 */
11720const _addedEvent = { type: 'added' };
11721
11722/**
11723 * Fires when the object has been removed from its parent object.
11724 *
11725 * @event Object3D#removed
11726 * @type {Object}
11727 */
11728const _removedEvent = { type: 'removed' };
11729
11730/**
11731 * Fires when a new child object has been added.
11732 *
11733 * @event Object3D#childadded
11734 * @type {Object}
11735 */
11736const _childaddedEvent = { type: 'childadded', child: null };
11737
11738/**
11739 * Fires when a child object has been removed.
11740 *
11741 * @event Object3D#childremoved
11742 * @type {Object}
11743 */
11744const _childremovedEvent = { type: 'childremoved', child: null };
11745
11746/**
11747 * This is the base class for most objects in three.js and provides a set of
11748 * properties and methods for manipulating objects in 3D space.
11749 *
11750 * @augments EventDispatcher
11751 */
11752class Object3D extends EventDispatcher {
11753
11754	/**
11755	 * Constructs a new 3D object.
11756	 */
11757	constructor() {
11758
11759		super();
11760
11761		/**
11762		 * This flag can be used for type testing.
11763		 *
11764		 * @type {boolean}
11765		 * @readonly
11766		 * @default true
11767		 */
11768		this.isObject3D = true;
11769
11770		/**
11771		 * The ID of the 3D object.
11772		 *
11773		 * @name Object3D#id
11774		 * @type {number}
11775		 * @readonly
11776		 */
11777		Object.defineProperty( this, 'id', { value: _object3DId ++ } );
11778
11779		/**
11780		 * The UUID of the 3D object.
11781		 *
11782		 * @type {string}
11783		 * @readonly
11784		 */
11785		this.uuid = generateUUID();
11786
11787		/**
11788		 * The name of the 3D object.
11789		 *
11790		 * @type {string}
11791		 */
11792		this.name = '';
11793
11794		/**
11795		 * The type property is used for detecting the object type
11796		 * in context of serialization/deserialization.
11797		 *
11798		 * @type {string}
11799		 * @readonly
11800		 */
11801		this.type = 'Object3D';
11802
11803		/**
11804		 * A reference to the parent object.
11805		 *
11806		 * @type {?Object3D}
11807		 * @default null
11808		 */
11809		this.parent = null;
11810
11811		/**
11812		 * An array holding the child 3D objects of this instance.
11813		 *
11814		 * @type {Array<Object3D>}
11815		 */
11816		this.children = [];
11817
11818		/**
11819		 * Defines the `up` direction of the 3D object which influences
11820		 * the orientation via methods like {@link Object3D#lookAt}.
11821		 *
11822		 * The default values for all 3D objects is defined by `Object3D.DEFAULT_UP`.
11823		 *
11824		 * @type {Vector3}
11825		 */
11826		this.up = Object3D.DEFAULT_UP.clone();
11827
11828		const position = new Vector3();
11829		const rotation = new Euler();
11830		const quaternion = new Quaternion();
11831		const scale = new Vector3( 1, 1, 1 );
11832
11833		function onRotationChange() {
11834
11835			quaternion.setFromEuler( rotation, false );
11836
11837		}
11838
11839		function onQuaternionChange() {
11840
11841			rotation.setFromQuaternion( quaternion, undefined, false );
11842
11843		}
11844
11845		rotation._onChange( onRotationChange );
11846		quaternion._onChange( onQuaternionChange );
11847
11848		Object.defineProperties( this, {
11849			/**
11850			 * Represents the object's local position.
11851			 *
11852			 * @name Object3D#position
11853			 * @type {Vector3}
11854			 * @default (0,0,0)
11855			 */
11856			position: {
11857				configurable: true,
11858				enumerable: true,
11859				value: position
11860			},
11861			/**
11862			 * Represents the object's local rotation as Euler angles, in radians.
11863			 *
11864			 * @name Object3D#rotation
11865			 * @type {Euler}
11866			 * @default (0,0,0)
11867			 */
11868			rotation: {
11869				configurable: true,
11870				enumerable: true,
11871				value: rotation
11872			},
11873			/**
11874			 * Represents the object's local rotation as Quaternions.
11875			 *
11876			 * @name Object3D#quaternion
11877			 * @type {Quaternion}
11878			 */
11879			quaternion: {
11880				configurable: true,
11881				enumerable: true,
11882				value: quaternion
11883			},
11884			/**
11885			 * Represents the object's local scale.
11886			 *
11887			 * @name Object3D#scale
11888			 * @type {Vector3}
11889			 * @default (1,1,1)
11890			 */
11891			scale: {
11892				configurable: true,
11893				enumerable: true,
11894				value: scale
11895			},
11896			/**
11897			 * Represents the object's model-view matrix.
11898			 *
11899			 * @name Object3D#modelViewMatrix
11900			 * @type {Matrix4}
11901			 */
11902			modelViewMatrix: {
11903				value: new Matrix4()
11904			},
11905			/**
11906			 * Represents the object's normal matrix.
11907			 *
11908			 * @name Object3D#normalMatrix
11909			 * @type {Matrix3}
11910			 */
11911			normalMatrix: {
11912				value: new Matrix3()
11913			}
11914		} );
11915
11916		/**
11917		 * Represents the object's transformation matrix in local space.
11918		 *
11919		 * @type {Matrix4}
11920		 */
11921		this.matrix = new Matrix4();
11922
11923		/**
11924		 * Represents the object's transformation matrix in world space.
11925		 * If the 3D object has no parent, then it's identical to the local transformation matrix
11926		 *
11927		 * @type {Matrix4}
11928		 */
11929		this.matrixWorld = new Matrix4();
11930
11931		/**
11932		 * When set to `true`, the engine automatically computes the local matrix from position,
11933		 * rotation and scale every frame. If set to `false`, the app is responsible for recomputing
11934		 * the local matrix by calling `updateMatrix()`.
11935		 *
11936		 * The default values for all 3D objects is defined by `Object3D.DEFAULT_MATRIX_AUTO_UPDATE`.
11937		 *
11938		 * @type {boolean}
11939		 * @default true
11940		 */
11941		this.matrixAutoUpdate = Object3D.DEFAULT_MATRIX_AUTO_UPDATE;
11942
11943		/**
11944		 * When set to `true`, the engine automatically computes the world matrix from the current local
11945		 * matrix and the object's transformation hierarchy. If set to `false`, the app is responsible for
11946		 * recomputing the world matrix by directly updating the `matrixWorld` property.
11947		 *
11948		 * The default values for all 3D objects is defined by `Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE`.
11949		 *
11950		 * @type {boolean}
11951		 * @default true
11952		 */
11953		this.matrixWorldAutoUpdate = Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE; // checked by the renderer
11954
11955		/**
11956		 * When set to `true`, it calculates the world matrix in that frame and resets this property
11957		 * to `false`.
11958		 *
11959		 * @type {boolean}
11960		 * @default false
11961		 */
11962		this.matrixWorldNeedsUpdate = false;
11963
11964		/**
11965		 * The layer membership of the 3D object. The 3D object is only visible if it has
11966		 * at least one layer in common with the camera in use. This property can also be
11967		 * used to filter out unwanted objects in ray-intersection tests when using {@link Raycaster}.
11968		 *
11969		 * @type {Layers}
11970		 */
11971		this.layers = new Layers();
11972
11973		/**
11974		 * When set to `true`, the 3D object gets rendered.
11975		 *
11976		 * @type {boolean}
11977		 * @default true
11978		 */
11979		this.visible = true;
11980
11981		/**
11982		 * When set to `true`, the 3D object gets rendered into shadow maps.
11983		 *
11984		 * @type {boolean}
11985		 * @default false
11986		 */
11987		this.castShadow = false;
11988
11989		/**
11990		 * When set to `true`, the 3D object is affected by shadows in the scene.
11991		 *
11992		 * @type {boolean}
11993		 * @default false
11994		 */
11995		this.receiveShadow = false;
11996
11997		/**
11998		 * When set to `true`, the 3D object is honored by view frustum culling.
11999		 *
12000		 * @type {boolean}
12001		 * @default true
12002		 */
12003		this.frustumCulled = true;
12004
12005		/**
12006		 * This value allows the default rendering order of scene graph objects to be
12007		 * overridden although opaque and transparent objects remain sorted independently.
12008		 * When this property is set for an instance of {@link Group},all descendants
12009		 * objects will be sorted and rendered together. Sorting is from lowest to highest
12010		 * render order.
12011		 *
12012		 * @type {number}
12013		 * @default 0
12014		 */
12015		this.renderOrder = 0;
12016
12017		/**
12018		 * An array holding the animation clips of the 3D object.
12019		 *
12020		 * @type {Array<AnimationClip>}
12021		 */
12022		this.animations = [];
12023
12024		/**
12025		 * Custom depth material to be used when rendering to the depth map. Can only be used
12026		 * in context of meshes. When shadow-casting with a {@link DirectionalLight} or {@link SpotLight},
12027		 * if you are modifying vertex positions in the vertex shader you must specify a custom depth
12028		 * material for proper shadows.
12029		 *
12030		 * Only relevant in context of {@link WebGLRenderer}.
12031		 *
12032		 * @type {(Material|undefined)}
12033		 * @default undefined
12034		 */
12035		this.customDepthMaterial = undefined;
12036
12037		/**
12038		 * Same as {@link Object3D#customDepthMaterial}, but used with {@link PointLight}.
12039		 *
12040		 * Only relevant in context of {@link WebGLRenderer}.
12041		 *
12042		 * @type {(Material|undefined)}
12043		 * @default undefined
12044		 */
12045		this.customDistanceMaterial = undefined;
12046
12047		/**
12048		 * Whether the 3D object is supposed to be static or not. If set to `true`, it means
12049		 * the 3D object is not going to be changed after the initial renderer. This includes
12050		 * geometry and material settings. A static 3D object can be processed by the renderer
12051		 * slightly faster since certain state checks can be bypassed.
12052		 *
12053		 * Only relevant in context of {@link WebGPURenderer}.
12054		 *
12055		 * @type {boolean}
12056		 * @default false
12057		 */
12058		this.static = false;
12059
12060		/**
12061		 * An object that can be used to store custom data about the 3D object. It
12062		 * should not hold references to functions as these will not be cloned.
12063		 *
12064		 * @type {Object}
12065		 */
12066		this.userData = {};
12067
12068		/**
12069		 * The pivot point for rotation and scale transformations.
12070		 * When set, rotation and scale are applied around this point
12071		 * instead of the object's origin.
12072		 *
12073		 * @type {?Vector3}
12074		 * @default null
12075		 */
12076		this.pivot = null;
12077
12078	}
12079
12080	/**
12081	 * A callback that is executed immediately before a 3D object is rendered to a shadow map.
12082	 *
12083	 * @param {Renderer|WebGLRenderer} renderer - The renderer.
12084	 * @param {Object3D} object - The 3D object.
12085	 * @param {Camera} camera - The camera that is used to render the scene.
12086	 * @param {Camera} shadowCamera - The shadow camera.
12087	 * @param {BufferGeometry} geometry - The 3D object's geometry.
12088	 * @param {Material} depthMaterial - The depth material.
12089	 * @param {Object} group - The geometry group data.
12090	 */
12091	onBeforeShadow( /* renderer, object, camera, shadowCamera, geometry, depthMaterial, group */ ) {}
12092
12093	/**
12094	 * A callback that is executed immediately after a 3D object is rendered to a shadow map.
12095	 *
12096	 * @param {Renderer|WebGLRenderer} renderer - The renderer.
12097	 * @param {Object3D} object - The 3D object.
12098	 * @param {Camera} camera - The camera that is used to render the scene.
12099	 * @param {Camera} shadowCamera - The shadow camera.
12100	 * @param {BufferGeometry} geometry - The 3D object's geometry.
12101	 * @param {Material} depthMaterial - The depth material.
12102	 * @param {Object} group - The geometry group data.
12103	 */
12104	onAfterShadow( /* renderer, object, camera, shadowCamera, geometry, depthMaterial, group */ ) {}
12105
12106	/**
12107	 * A callback that is executed immediately before a 3D object is rendered.
12108	 *
12109	 * @param {Renderer|WebGLRenderer} renderer - The renderer.
12110	 * @param {Object3D} object - The 3D object.
12111	 * @param {Camera} camera - The camera that is used to render the scene.
12112	 * @param {BufferGeometry} geometry - The 3D object's geometry.
12113	 * @param {Material} material - The 3D object's material.
12114	 * @param {Object} group - The geometry group data.
12115	 */
12116	onBeforeRender( /* renderer, scene, camera, geometry, material, group */ ) {}
12117
12118	/**
12119	 * A callback that is executed immediately after a 3D object is rendered.
12120	 *
12121	 * @param {Renderer|WebGLRenderer} renderer - The renderer.
12122	 * @param {Object3D} object - The 3D object.
12123	 * @param {Camera} camera - The camera that is used to render the scene.
12124	 * @param {BufferGeometry} geometry - The 3D object's geometry.
12125	 * @param {Material} material - The 3D object's material.
12126	 * @param {Object} group - The geometry group data.
12127	 */
12128	onAfterRender( /* renderer, scene, camera, geometry, material, group */ ) {}
12129
12130	/**
12131	 * Applies the given transformation matrix to the object and updates the object's position,
12132	 * rotation and scale.
12133	 *
12134	 * @param {Matrix4} matrix - The transformation matrix.
12135	 */
12136	applyMatrix4( matrix ) {
12137
12138		if ( this.matrixAutoUpdate ) this.updateMatrix();
12139
12140		this.matrix.premultiply( matrix );
12141
12142		this.matrix.decompose( this.position, this.quaternion, this.scale );
12143
12144	}
12145
12146	/**
12147	 * Applies a rotation represented by given the quaternion to the 3D object.
12148	 *
12149	 * @param {Quaternion} q - The quaternion.
12150	 * @return {Object3D} A reference to this instance.
12151	 */
12152	applyQuaternion( q ) {
12153
12154		this.quaternion.premultiply( q );
12155
12156		return this;
12157
12158	}
12159
12160	/**
12161	 * Sets the given rotation represented as an axis/angle couple to the 3D object.
12162	 *
12163	 * @param {Vector3} axis - The (normalized) axis vector.
12164	 * @param {number} angle - The angle in radians.
12165	 */
12166	setRotationFromAxisAngle( axis, angle ) {
12167
12168		// assumes axis is normalized
12169
12170		this.quaternion.setFromAxisAngle( axis, angle );
12171
12172	}
12173
12174	/**
12175	 * Sets the given rotation represented as Euler angles to the 3D object.
12176	 *
12177	 * @param {Euler} euler - The Euler angles.
12178	 */
12179	setRotationFromEuler( euler ) {
12180
12181		this.quaternion.setFromEuler( euler, true );
12182
12183	}
12184
12185	/**
12186	 * Sets the given rotation represented as rotation matrix to the 3D object.
12187	 *
12188	 * @param {Matrix4} m - Although a 4x4 matrix is expected, the upper 3x3 portion must be
12189	 * a pure rotation matrix (i.e, unscaled).
12190	 */
12191	setRotationFromMatrix( m ) {
12192
12193		// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
12194
12195		this.quaternion.setFromRotationMatrix( m );
12196
12197	}
12198
12199	/**
12200	 * Sets the given rotation represented as a Quaternion to the 3D object.
12201	 *
12202	 * @param {Quaternion} q - The Quaternion
12203	 */
12204	setRotationFromQuaternion( q ) {
12205
12206		// assumes q is normalized
12207
12208		this.quaternion.copy( q );
12209
12210	}
12211
12212	/**
12213	 * Rotates the 3D object along an axis in local space.
12214	 *
12215	 * @param {Vector3} axis - The (normalized) axis vector.
12216	 * @param {number} angle - The angle in radians.
12217	 * @return {Object3D} A reference to this instance.
12218	 */
12219	rotateOnAxis( axis, angle ) {
12220
12221		// rotate object on axis in object space
12222		// axis is assumed to be normalized
12223
12224		_q1.setFromAxisAngle( axis, angle );
12225
12226		this.quaternion.multiply( _q1 );
12227
12228		return this;
12229
12230	}
12231
12232	/**
12233	 * Rotates the 3D object along an axis in world space.
12234	 *
12235	 * @param {Vector3} axis - The (normalized) axis vector.
12236	 * @param {number} angle - The angle in radians.
12237	 * @return {Object3D} A reference to this instance.
12238	 */
12239	rotateOnWorldAxis( axis, angle ) {
12240
12241		// rotate object on axis in world space
12242		// axis is assumed to be normalized
12243		// method assumes no rotated parent
12244
12245		_q1.setFromAxisAngle( axis, angle );
12246
12247		this.quaternion.premultiply( _q1 );
12248
12249		return this;
12250
12251	}
12252
12253	/**
12254	 * Rotates the 3D object around its X axis in local space.
12255	 *
12256	 * @param {number} angle - The angle in radians.
12257	 * @return {Object3D} A reference to this instance.
12258	 */
12259	rotateX( angle ) {
12260
12261		return this.rotateOnAxis( _xAxis, angle );
12262
12263	}
12264
12265	/**
12266	 * Rotates the 3D object around its Y axis in local space.
12267	 *
12268	 * @param {number} angle - The angle in radians.
12269	 * @return {Object3D} A reference to this instance.
12270	 */
12271	rotateY( angle ) {
12272
12273		return this.rotateOnAxis( _yAxis, angle );
12274
12275	}
12276
12277	/**
12278	 * Rotates the 3D object around its Z axis in local space.
12279	 *
12280	 * @param {number} angle - The angle in radians.
12281	 * @return {Object3D} A reference to this instance.
12282	 */
12283	rotateZ( angle ) {
12284
12285		return this.rotateOnAxis( _zAxis, angle );
12286
12287	}
12288
12289	/**
12290	 * Translate the 3D object by a distance along the given axis in local space.
12291	 *
12292	 * @param {Vector3} axis - The (normalized) axis vector.
12293	 * @param {number} distance - The distance in world units.
12294	 * @return {Object3D} A reference to this instance.
12295	 */
12296	translateOnAxis( axis, distance ) {
12297
12298		// translate object by distance along axis in object space
12299		// axis is assumed to be normalized
12300
12301		_v1$6.copy( axis ).applyQuaternion( this.quaternion );
12302
12303		this.position.add( _v1$6.multiplyScalar( distance ) );
12304
12305		return this;
12306
12307	}
12308
12309	/**
12310	 * Translate the 3D object by a distance along its X-axis in local space.
12311	 *
12312	 * @param {number} distance - The distance in world units.
12313	 * @return {Object3D} A reference to this instance.
12314	 */
12315	translateX( distance ) {
12316
12317		return this.translateOnAxis( _xAxis, distance );
12318
12319	}
12320
12321	/**
12322	 * Translate the 3D object by a distance along its Y-axis in local space.
12323	 *
12324	 * @param {number} distance - The distance in world units.
12325	 * @return {Object3D} A reference to this instance.
12326	 */
12327	translateY( distance ) {
12328
12329		return this.translateOnAxis( _yAxis, distance );
12330
12331	}
12332
12333	/**
12334	 * Translate the 3D object by a distance along its Z-axis in local space.
12335	 *
12336	 * @param {number} distance - The distance in world units.
12337	 * @return {Object3D} A reference to this instance.
12338	 */
12339	translateZ( distance ) {
12340
12341		return this.translateOnAxis( _zAxis, distance );
12342
12343	}
12344
12345	/**
12346	 * Converts the given vector from this 3D object's local space to world space.
12347	 *
12348	 * @param {Vector3} vector - The vector to convert.
12349	 * @return {Vector3} The converted vector.
12350	 */
12351	localToWorld( vector ) {
12352
12353		this.updateWorldMatrix( true, false );
12354
12355		return vector.applyMatrix4( this.matrixWorld );
12356
12357	}
12358
12359	/**
12360	 * Converts the given vector from this 3D object's world space to local space.
12361	 *
12362	 * @param {Vector3} vector - The vector to convert.
12363	 * @return {Vector3} The converted vector.
12364	 */
12365	worldToLocal( vector ) {
12366
12367		this.updateWorldMatrix( true, false );
12368
12369		return vector.applyMatrix4( _m1$1.copy( this.matrixWorld ).invert() );
12370
12371	}
12372
12373	/**
12374	 * Rotates the object to face a point in world space.
12375	 *
12376	 * This method does not support objects having non-uniformly-scaled parent(s).
12377	 *
12378	 * @param {number|Vector3} x - The x coordinate in world space. Alternatively, a vector representing a position in world space
12379	 * @param {number} [y] - The y coordinate in world space.
12380	 * @param {number} [z] - The z coordinate in world space.
12381	 */
12382	lookAt( x, y, z ) {
12383
12384		// This method does not support objects having non-uniformly-scaled parent(s)
12385
12386		if ( x.isVector3 ) {
12387
12388			_target.copy( x );
12389
12390		} else {
12391
12392			_target.set( x, y, z );
12393
12394		}
12395
12396		const parent = this.parent;
12397
12398		this.updateWorldMatrix( true, false );
12399
12400		_position$4.setFromMatrixPosition( this.matrixWorld );
12401
12402		if ( this.isCamera || this.isLight ) {
12403
12404			_m1$1.lookAt( _position$4, _target, this.up );
12405
12406		} else {
12407
12408			_m1$1.lookAt( _target, _position$4, this.up );
12409
12410		}
12411
12412		this.quaternion.setFromRotationMatrix( _m1$1 );
12413
12414		if ( parent ) {
12415
12416			_m1$1.extractRotation( parent.matrixWorld );
12417			_q1.setFromRotationMatrix( _m1$1 );
12418			this.quaternion.premultiply( _q1.invert() );
12419
12420		}
12421
12422	}
12423
12424	/**
12425	 * Adds the given 3D object as a child to this 3D object. An arbitrary number of
12426	 * objects may be added. Any current parent on an object passed in here will be
12427	 * removed, since an object can have at most one parent.
12428	 *
12429	 * @fires Object3D#added
12430	 * @fires Object3D#childadded
12431	 * @param {Object3D} object - The 3D object to add.
12432	 * @return {Object3D} A reference to this instance.
12433	 */
12434	add( object ) {
12435
12436		if ( arguments.length > 1 ) {
12437
12438			for ( let i = 0; i < arguments.length; i ++ ) {
12439
12440				this.add( arguments[ i ] );
12441
12442			}
12443
12444			return this;
12445
12446		}
12447
12448		if ( object === this ) {
12449
12450			error( 'Object3D.add: object can\'t be added as a child of itself.', object );
12451			return this;
12452
12453		}
12454
12455		if ( object && object.isObject3D ) {
12456
12457			object.removeFromParent();
12458			object.parent = this;
12459			this.children.push( object );
12460
12461			object.dispatchEvent( _addedEvent );
12462
12463			_childaddedEvent.child = object;
12464			this.dispatchEvent( _childaddedEvent );
12465			_childaddedEvent.child = null;
12466
12467		} else {
12468
12469			error( 'Object3D.add: object not an instance of THREE.Object3D.', object );
12470
12471		}
12472
12473		return this;
12474
12475	}
12476
12477	/**
12478	 * Removes the given 3D object as child from this 3D object.
12479	 * An arbitrary number of objects may be removed.
12480	 *
12481	 * @fires Object3D#removed
12482	 * @fires Object3D#childremoved
12483	 * @param {Object3D} object - The 3D object to remove.
12484	 * @return {Object3D} A reference to this instance.
12485	 */
12486	remove( object ) {
12487
12488		if ( arguments.length > 1 ) {
12489
12490			for ( let i = 0; i < arguments.length; i ++ ) {
12491
12492				this.remove( arguments[ i ] );
12493
12494			}
12495
12496			return this;
12497
12498		}
12499
12500		const index = this.children.indexOf( object );
12501
12502		if ( index !== -1 ) {
12503
12504			object.parent = null;
12505			this.children.splice( index, 1 );
12506
12507			object.dispatchEvent( _removedEvent );
12508
12509			_childremovedEvent.child = object;
12510			this.dispatchEvent( _childremovedEvent );
12511			_childremovedEvent.child = null;
12512
12513		}
12514
12515		return this;
12516
12517	}
12518
12519	/**
12520	 * Removes this 3D object from its current parent.
12521	 *
12522	 * @fires Object3D#removed
12523	 * @fires Object3D#childremoved
12524	 * @return {Object3D} A reference to this instance.
12525	 */
12526	removeFromParent() {
12527
12528		const parent = this.parent;
12529
12530		if ( parent !== null ) {
12531
12532			parent.remove( this );
12533
12534		}
12535
12536		return this;
12537
12538	}
12539
12540	/**
12541	 * Removes all child objects.
12542	 *
12543	 * @fires Object3D#removed
12544	 * @fires Object3D#childremoved
12545	 * @return {Object3D} A reference to this instance.
12546	 */
12547	clear() {
12548
12549		return this.remove( ... this.children );
12550
12551	}
12552
12553	/**
12554	 * Adds the given 3D object as a child of this 3D object, while maintaining the object's world
12555	 * transform. This method does not support scene graphs having non-uniformly-scaled nodes(s).
12556	 *
12557	 * @fires Object3D#added
12558	 * @fires Object3D#childadded
12559	 * @param {Object3D} object - The 3D object to attach.
12560	 * @return {Object3D} A reference to this instance.
12561	 */
12562	attach( object ) {
12563
12564		// adds object as a child of this, while maintaining the object's world transform
12565
12566		// Note: This method does not support scene graphs having non-uniformly-scaled nodes(s)
12567
12568		this.updateWorldMatrix( true, false );
12569
12570		_m1$1.copy( this.matrixWorld ).invert();
12571
12572		if ( object.parent !== null ) {
12573
12574			object.parent.updateWorldMatrix( true, false );
12575
12576			_m1$1.multiply( object.parent.matrixWorld );
12577
12578		}
12579
12580		object.applyMatrix4( _m1$1 );
12581
12582		object.removeFromParent();
12583		object.parent = this;
12584		this.children.push( object );
12585
12586		object.updateWorldMatrix( false, true );
12587
12588		object.dispatchEvent( _addedEvent );
12589
12590		_childaddedEvent.child = object;
12591		this.dispatchEvent( _childaddedEvent );
12592		_childaddedEvent.child = null;
12593
12594		return this;
12595
12596	}
12597
12598	/**
12599	 * Searches through the 3D object and its children, starting with the 3D object
12600	 * itself, and returns the first with a matching ID.
12601	 *
12602	 * @param {number} id - The id.
12603	 * @return {Object3D|undefined} The found 3D object. Returns `undefined` if no 3D object has been found.
12604	 */
12605	getObjectById( id ) {
12606
12607		return this.getObjectByProperty( 'id', id );
12608
12609	}
12610
12611	/**
12612	 * Searches through the 3D object and its children, starting with the 3D object
12613	 * itself, and returns the first with a matching name.
12614	 *
12615	 * @param {string} name - The name.
12616	 * @return {Object3D|undefined} The found 3D object. Returns `undefined` if no 3D object has been found.
12617	 */
12618	getObjectByName( name ) {
12619
12620		return this.getObjectByProperty( 'name', name );
12621
12622	}
12623
12624	/**
12625	 * Searches through the 3D object and its children, starting with the 3D object
12626	 * itself, and returns the first with a matching property value.
12627	 *
12628	 * @param {string} name - The name of the property.
12629	 * @param {any} value - The value.
12630	 * @return {Object3D|undefined} The found 3D object. Returns `undefined` if no 3D object has been found.
12631	 */
12632	getObjectByProperty( name, value ) {
12633
12634		if ( this[ name ] === value ) return this;
12635
12636		for ( let i = 0, l = this.children.length; i < l; i ++ ) {
12637
12638			const child = this.children[ i ];
12639			const object = child.getObjectByProperty( name, value );
12640
12641			if ( object !== undefined ) {
12642
12643				return object;
12644
12645			}
12646
12647		}
12648
12649		return undefined;
12650
12651	}
12652
12653	/**
12654	 * Searches through the 3D object and its children, starting with the 3D object
12655	 * itself, and returns all 3D objects with a matching property value.
12656	 *
12657	 * @param {string} name - The name of the property.
12658	 * @param {any} value - The value.
12659	 * @param {Array<Object3D>} result - The method stores the result in this array.
vendor: 15,125 bytes, lines 12660-13283
12660	 * @return {Array<Object3D>} The found 3D objects.
12661	 */
12662	getObjectsByProperty( name, value, result = [] ) {
12663
12664		if ( this[ name ] === value ) result.push( this );
12665
12666		const children = this.children;
12667
12668		for ( let i = 0, l = children.length; i < l; i ++ ) {
12669
12670			children[ i ].getObjectsByProperty( name, value, result );
12671
12672		}
12673
12674		return result;
12675
12676	}
12677
12678	/**
12679	 * Returns a vector representing the position of the 3D object in world space.
12680	 *
12681	 * @param {Vector3} target - The target vector the result is stored to.
12682	 * @return {Vector3} The 3D object's position in world space.
12683	 */
12684	getWorldPosition( target ) {
12685
12686		this.updateWorldMatrix( true, false );
12687
12688		return target.setFromMatrixPosition( this.matrixWorld );
12689
12690	}
12691
12692	/**
12693	 * Returns a Quaternion representing the position of the 3D object in world space.
12694	 *
12695	 * @param {Quaternion} target - The target Quaternion the result is stored to.
12696	 * @return {Quaternion} The 3D object's rotation in world space.
12697	 */
12698	getWorldQuaternion( target ) {
12699
12700		this.updateWorldMatrix( true, false );
12701
12702		this.matrixWorld.decompose( _position$4, target, _scale$3 );
12703
12704		return target;
12705
12706	}
12707
12708	/**
12709	 * Returns a vector representing the scale of the 3D object in world space.
12710	 *
12711	 * @param {Vector3} target - The target vector the result is stored to.
12712	 * @return {Vector3} The 3D object's scale in world space.
12713	 */
12714	getWorldScale( target ) {
12715
12716		this.updateWorldMatrix( true, false );
12717
12718		this.matrixWorld.decompose( _position$4, _quaternion$3, target );
12719
12720		return target;
12721
12722	}
12723
12724	/**
12725	 * Returns a vector representing the ("look") direction of the 3D object in world space.
12726	 *
12727	 * @param {Vector3} target - The target vector the result is stored to.
12728	 * @return {Vector3} The 3D object's direction in world space.
12729	 */
12730	getWorldDirection( target ) {
12731
12732		this.updateWorldMatrix( true, false );
12733
12734		const e = this.matrixWorld.elements;
12735
12736		return target.set( e[ 8 ], e[ 9 ], e[ 10 ] ).normalize();
12737
12738	}
12739
12740	/**
12741	 * Abstract method to get intersections between a casted ray and this
12742	 * 3D object. Renderable 3D objects such as {@link Mesh}, {@link Line} or {@link Points}
12743	 * implement this method in order to use raycasting.
12744	 *
12745	 * @abstract
12746	 * @param {Raycaster} raycaster - The raycaster.
12747	 * @param {Array<Object>} intersects - An array holding the result of the method.
12748	 */
12749	raycast( /* raycaster, intersects */ ) {}
12750
12751	/**
12752	 * Executes the callback on this 3D object and all descendants.
12753	 *
12754	 * Note: Modifying the scene graph inside the callback is discouraged.
12755	 *
12756	 * @param {Function} callback - A callback function that allows to process the current 3D object.
12757	 */
12758	traverse( callback ) {
12759
12760		callback( this );
12761
12762		const children = this.children;
12763
12764		for ( let i = 0, l = children.length; i < l; i ++ ) {
12765
12766			children[ i ].traverse( callback );
12767
12768		}
12769
12770	}
12771
12772	/**
12773	 * Like {@link Object3D#traverse}, but the callback will only be executed for visible 3D objects.
12774	 * Descendants of invisible 3D objects are not traversed.
12775	 *
12776	 * Note: Modifying the scene graph inside the callback is discouraged.
12777	 *
12778	 * @param {Function} callback - A callback function that allows to process the current 3D object.
12779	 */
12780	traverseVisible( callback ) {
12781
12782		if ( this.visible === false ) return;
12783
12784		callback( this );
12785
12786		const children = this.children;
12787
12788		for ( let i = 0, l = children.length; i < l; i ++ ) {
12789
12790			children[ i ].traverseVisible( callback );
12791
12792		}
12793
12794	}
12795
12796	/**
12797	 * Like {@link Object3D#traverse}, but the callback will only be executed for all ancestors.
12798	 *
12799	 * Note: Modifying the scene graph inside the callback is discouraged.
12800	 *
12801	 * @param {Function} callback - A callback function that allows to process the current 3D object.
12802	 */
12803	traverseAncestors( callback ) {
12804
12805		const parent = this.parent;
12806
12807		if ( parent !== null ) {
12808
12809			callback( parent );
12810
12811			parent.traverseAncestors( callback );
12812
12813		}
12814
12815	}
12816
12817	/**
12818	 * Updates the transformation matrix in local space by computing it from the current
12819	 * position, rotation and scale values.
12820	 */
12821	updateMatrix() {
12822
12823		this.matrix.compose( this.position, this.quaternion, this.scale );
12824
12825		const pivot = this.pivot;
12826
12827		if ( pivot !== null ) {
12828
12829			const px = pivot.x, py = pivot.y, pz = pivot.z;
12830			const te = this.matrix.elements;
12831
12832			te[ 12 ] += px - te[ 0 ] * px - te[ 4 ] * py - te[ 8 ] * pz;
12833			te[ 13 ] += py - te[ 1 ] * px - te[ 5 ] * py - te[ 9 ] * pz;
12834			te[ 14 ] += pz - te[ 2 ] * px - te[ 6 ] * py - te[ 10 ] * pz;
12835
12836		}
12837
12838		this.matrixWorldNeedsUpdate = true;
12839
12840	}
12841
12842	/**
12843	 * Updates the transformation matrix in world space of this 3D objects and its descendants.
12844	 *
12845	 * To ensure correct results, this method also recomputes the 3D object's transformation matrix in
12846	 * local space. The computation of the local and world matrix can be controlled with the
12847	 * {@link Object3D#matrixAutoUpdate} and {@link Object3D#matrixWorldAutoUpdate} flags which are both
12848	 * `true` by default.  Set these flags to `false` if you need more control over the update matrix process.
12849	 *
12850	 * @param {boolean} [force=false] - When set to `true`, a recomputation of world matrices is forced even
12851	 * when {@link Object3D#matrixWorldNeedsUpdate} is `false`.
12852	 */
12853	updateMatrixWorld( force ) {
12854
12855		if ( this.matrixAutoUpdate ) this.updateMatrix();
12856
12857		if ( this.matrixWorldNeedsUpdate || force ) {
12858
12859			if ( this.matrixWorldAutoUpdate === true ) {
12860
12861				if ( this.parent === null ) {
12862
12863					this.matrixWorld.copy( this.matrix );
12864
12865				} else {
12866
12867					this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
12868
12869				}
12870
12871			}
12872
12873			this.matrixWorldNeedsUpdate = false;
12874
12875			force = true;
12876
12877		}
12878
12879		// make sure descendants are updated if required
12880
12881		const children = this.children;
12882
12883		for ( let i = 0, l = children.length; i < l; i ++ ) {
12884
12885			const child = children[ i ];
12886
12887			child.updateMatrixWorld( force );
12888
12889		}
12890
12891	}
12892
12893	/**
12894	 * An alternative version of {@link Object3D#updateMatrixWorld} with more control over the
12895	 * update of ancestor and descendant nodes.
12896	 *
12897	 * @param {boolean} [updateParents=false] Whether ancestor nodes should be updated or not.
12898	 * @param {boolean} [updateChildren=false] Whether descendant nodes should be updated or not.
12899	 */
12900	updateWorldMatrix( updateParents, updateChildren ) {
12901
12902		const parent = this.parent;
12903
12904		if ( updateParents === true && parent !== null ) {
12905
12906			parent.updateWorldMatrix( true, false );
12907
12908		}
12909
12910		if ( this.matrixAutoUpdate ) this.updateMatrix();
12911
12912		if ( this.matrixWorldAutoUpdate === true ) {
12913
12914			if ( this.parent === null ) {
12915
12916				this.matrixWorld.copy( this.matrix );
12917
12918			} else {
12919
12920				this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
12921
12922			}
12923
12924		}
12925
12926		// make sure descendants are updated
12927
12928		if ( updateChildren === true ) {
12929
12930			const children = this.children;
12931
12932			for ( let i = 0, l = children.length; i < l; i ++ ) {
12933
12934				const child = children[ i ];
12935
12936				child.updateWorldMatrix( false, true );
12937
12938			}
12939
12940		}
12941
12942	}
12943
12944	/**
12945	 * Serializes the 3D object into JSON.
12946	 *
12947	 * @param {?(Object|string)} meta - An optional value holding meta information about the serialization.
12948	 * @return {Object} A JSON object representing the serialized 3D object.
12949	 * @see {@link ObjectLoader#parse}
12950	 */
12951	toJSON( meta ) {
12952
12953		// meta is a string when called from JSON.stringify
12954		const isRootObject = ( meta === undefined || typeof meta === 'string' );
12955
12956		const output = {};
12957
12958		// meta is a hash used to collect geometries, materials.
12959		// not providing it implies that this is the root object
12960		// being serialized.
12961		if ( isRootObject ) {
12962
12963			// initialize meta obj
12964			meta = {
12965				geometries: {},
12966				materials: {},
12967				textures: {},
12968				images: {},
12969				shapes: {},
12970				skeletons: {},
12971				animations: {},
12972				nodes: {}
12973			};
12974
12975			output.metadata = {
12976				version: 4.7,
12977				type: 'Object',
12978				generator: 'Object3D.toJSON'
12979			};
12980
12981		}
12982
12983		// standard Object3D serialization
12984
12985		const object = {};
12986
12987		object.uuid = this.uuid;
12988		object.type = this.type;
12989
12990		if ( this.name !== '' ) object.name = this.name;
12991		if ( this.castShadow === true ) object.castShadow = true;
12992		if ( this.receiveShadow === true ) object.receiveShadow = true;
12993		if ( this.visible === false ) object.visible = false;
12994		if ( this.frustumCulled === false ) object.frustumCulled = false;
12995		if ( this.renderOrder !== 0 ) object.renderOrder = this.renderOrder;
12996		if ( this.static !== false ) object.static = this.static;
12997		if ( Object.keys( this.userData ).length > 0 ) object.userData = this.userData;
12998
12999		object.layers = this.layers.mask;
13000		object.matrix = this.matrix.toArray();
13001		object.up = this.up.toArray();
13002
13003		if ( this.pivot !== null ) object.pivot = this.pivot.toArray();
13004
13005		if ( this.matrixAutoUpdate === false ) object.matrixAutoUpdate = false;
13006
13007		if ( this.morphTargetDictionary !== undefined ) object.morphTargetDictionary = Object.assign( {}, this.morphTargetDictionary );
13008		if ( this.morphTargetInfluences !== undefined ) object.morphTargetInfluences = this.morphTargetInfluences.slice();
13009
13010		// object specific properties
13011
13012		if ( this.isInstancedMesh ) {
13013
13014			object.type = 'InstancedMesh';
13015			object.count = this.count;
13016			object.instanceMatrix = this.instanceMatrix.toJSON();
13017			if ( this.instanceColor !== null ) object.instanceColor = this.instanceColor.toJSON();
13018
13019		}
13020
13021		if ( this.isBatchedMesh ) {
13022
13023			object.type = 'BatchedMesh';
13024			object.perObjectFrustumCulled = this.perObjectFrustumCulled;
13025			object.sortObjects = this.sortObjects;
13026
13027			object.drawRanges = this._drawRanges;
13028			object.reservedRanges = this._reservedRanges;
13029
13030			object.geometryInfo = this._geometryInfo.map( info => ( {
13031				...info,
13032				boundingBox: info.boundingBox ? info.boundingBox.toJSON() : undefined,
13033				boundingSphere: info.boundingSphere ? info.boundingSphere.toJSON() : undefined
13034			} ) );
13035			object.instanceInfo = this._instanceInfo.map( info => ( { ...info } ) );
13036
13037			object.availableInstanceIds = this._availableInstanceIds.slice();
13038			object.availableGeometryIds = this._availableGeometryIds.slice();
13039
13040			object.nextIndexStart = this._nextIndexStart;
13041			object.nextVertexStart = this._nextVertexStart;
13042			object.geometryCount = this._geometryCount;
13043
13044			object.maxInstanceCount = this._maxInstanceCount;
13045			object.maxVertexCount = this._maxVertexCount;
13046			object.maxIndexCount = this._maxIndexCount;
13047
13048			object.geometryInitialized = this._geometryInitialized;
13049
13050			object.matricesTexture = this._matricesTexture.toJSON( meta );
13051
13052			object.indirectTexture = this._indirectTexture.toJSON( meta );
13053
13054			if ( this._colorsTexture !== null ) {
13055
13056				object.colorsTexture = this._colorsTexture.toJSON( meta );
13057
13058			}
13059
13060			if ( this.boundingSphere !== null ) {
13061
13062				object.boundingSphere = this.boundingSphere.toJSON();
13063
13064			}
13065
13066			if ( this.boundingBox !== null ) {
13067
13068				object.boundingBox = this.boundingBox.toJSON();
13069
13070			}
13071
13072		}
13073
13074		//
13075
13076		function serialize( library, element ) {
13077
13078			if ( library[ element.uuid ] === undefined ) {
13079
13080				library[ element.uuid ] = element.toJSON( meta );
13081
13082			}
13083
13084			return element.uuid;
13085
13086		}
13087
13088		if ( this.isScene ) {
13089
13090			if ( this.background ) {
13091
13092				if ( this.background.isColor ) {
13093
13094					object.background = this.background.toJSON();
13095
13096				} else if ( this.background.isTexture ) {
13097
13098					object.background = this.background.toJSON( meta ).uuid;
13099
13100				}
13101
13102			}
13103
13104			if ( this.environment && this.environment.isTexture && this.environment.isRenderTargetTexture !== true ) {
13105
13106				object.environment = this.environment.toJSON( meta ).uuid;
13107
13108			}
13109
13110		} else if ( this.isMesh || this.isLine || this.isPoints ) {
13111
13112			object.geometry = serialize( meta.geometries, this.geometry );
13113
13114			const parameters = this.geometry.parameters;
13115
13116			if ( parameters !== undefined && parameters.shapes !== undefined ) {
13117
13118				const shapes = parameters.shapes;
13119
13120				if ( Array.isArray( shapes ) ) {
13121
13122					for ( let i = 0, l = shapes.length; i < l; i ++ ) {
13123
13124						const shape = shapes[ i ];
13125
13126						serialize( meta.shapes, shape );
13127
13128					}
13129
13130				} else {
13131
13132					serialize( meta.shapes, shapes );
13133
13134				}
13135
13136			}
13137
13138		}
13139
13140		if ( this.isSkinnedMesh ) {
13141
13142			object.bindMode = this.bindMode;
13143			object.bindMatrix = this.bindMatrix.toArray();
13144
13145			if ( this.skeleton !== undefined ) {
13146
13147				serialize( meta.skeletons, this.skeleton );
13148
13149				object.skeleton = this.skeleton.uuid;
13150
13151			}
13152
13153		}
13154
13155		if ( this.material !== undefined ) {
13156
13157			if ( Array.isArray( this.material ) ) {
13158
13159				const uuids = [];
13160
13161				for ( let i = 0, l = this.material.length; i < l; i ++ ) {
13162
13163					uuids.push( serialize( meta.materials, this.material[ i ] ) );
13164
13165				}
13166
13167				object.material = uuids;
13168
13169			} else {
13170
13171				object.material = serialize( meta.materials, this.material );
13172
13173			}
13174
13175		}
13176
13177		//
13178
13179		if ( this.children.length > 0 ) {
13180
13181			object.children = [];
13182
13183			for ( let i = 0; i < this.children.length; i ++ ) {
13184
13185				object.children.push( this.children[ i ].toJSON( meta ).object );
13186
13187			}
13188
13189		}
13190
13191		//
13192
13193		if ( this.animations.length > 0 ) {
13194
13195			object.animations = [];
13196
13197			for ( let i = 0; i < this.animations.length; i ++ ) {
13198
13199				const animation = this.animations[ i ];
13200
13201				object.animations.push( serialize( meta.animations, animation ) );
13202
13203			}
13204
13205		}
13206
13207		if ( isRootObject ) {
13208
13209			const geometries = extractFromCache( meta.geometries );
13210			const materials = extractFromCache( meta.materials );
13211			const textures = extractFromCache( meta.textures );
13212			const images = extractFromCache( meta.images );
13213			const shapes = extractFromCache( meta.shapes );
13214			const skeletons = extractFromCache( meta.skeletons );
13215			const animations = extractFromCache( meta.animations );
13216			const nodes = extractFromCache( meta.nodes );
13217
13218			if ( geometries.length > 0 ) output.geometries = geometries;
13219			if ( materials.length > 0 ) output.materials = materials;
13220			if ( textures.length > 0 ) output.textures = textures;
13221			if ( images.length > 0 ) output.images = images;
13222			if ( shapes.length > 0 ) output.shapes = shapes;
13223			if ( skeletons.length > 0 ) output.skeletons = skeletons;
13224			if ( animations.length > 0 ) output.animations = animations;
13225			if ( nodes.length > 0 ) output.nodes = nodes;
13226
13227		}
13228
13229		output.object = object;
13230
13231		return output;
13232
13233		// extract data from the cache hash
13234		// remove metadata on each item
13235		// and return as array
13236		function extractFromCache( cache ) {
13237
13238			const values = [];
13239			for ( const key in cache ) {
13240
13241				const data = cache[ key ];
13242				delete data.metadata;
13243				values.push( data );
13244
13245			}
13246
13247			return values;
13248
13249		}
13250
13251	}
13252
13253	/**
13254	 * Returns a new 3D object with copied values from this instance.
13255	 *
13256	 * @param {boolean} [recursive=true] - When set to `true`, descendants of the 3D object are also cloned.
13257	 * @return {Object3D} A clone of this instance.
13258	 */
13259	clone( recursive ) {
13260
13261		return new this.constructor().copy( this, recursive );
13262
13263	}
13264
13265	/**
13266	 * Copies the values of the given 3D object to this instance.
13267	 *
13268	 * @param {Object3D} source - The 3D object to copy.
13269	 * @param {boolean} [recursive=true] - When set to `true`, descendants of the 3D object are cloned.
13270	 * @return {Object3D} A reference to this instance.
13271	 */
13272	copy( source, recursive = true ) {
13273
13274		this.name = source.name;
13275
13276		this.up.copy( source.up );
13277
13278		this.position.copy( source.position );
13279		this.rotation.order = source.rotation.order;
13280		this.quaternion.copy( source.quaternion );
13281		this.scale.copy( source.scale );
13282
13283		
13283this.pivot = ( source.pivot !== null ) ? source.pivot.clone() : null;
13284
13285		this.matrix.copy( source.matrix );
13286		this.matrixWorld.copy( source.matrixWorld );
13287
13288		this.matrixAutoUpdate = source.matrixAutoUpdate;
13289
13290		this.matrixWorldAutoUpdate = source.matrixWorldAutoUpdate;
13291		this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate;
13292
13293		this.layers.mask = source.layers.mask;
13294		this.visible = source.visible;
13295
13296		this.castShadow = source.castShadow;
13297		this.receiveShadow = source.receiveShadow;
13298
13299		this.frustumCulled = source.frustumCulled;
13300		this.renderOrder = source.renderOrder;
13301
13302		this.static = source.static;
13303
13304		this.animations = source.animations.slice();
13305
13306		this.userData = JSON.parse( JSON.stringify( source.userData ) );
13307
13308		if ( recursive === true ) {
13309
13310			for ( let i = 0; i < source.children.length; i ++ ) {
13311
13312				const child = source.children[ i ];
13313				this.add( child.clone() );
13314
13315			}
13316
13317		}
13318
13319		return this
vendor: 43,089 bytes, lines 13319-15115
13319;
13320
13321	}
13322
13323}
13324
13325/**
13326 * The default up direction for objects, also used as the default
13327 * position for {@link DirectionalLight} and {@link HemisphereLight}.
13328 *
13329 * @static
13330 * @type {Vector3}
13331 * @default (0,1,0)
13332 */
13333Object3D.DEFAULT_UP = /*@__PURE__*/ new Vector3( 0, 1, 0 );
13334
13335/**
13336 * The default setting for {@link Object3D#matrixAutoUpdate} for
13337 * newly created 3D objects.
13338 *
13339 * @static
13340 * @type {boolean}
13341 * @default true
13342 */
13343Object3D.DEFAULT_MATRIX_AUTO_UPDATE = true;
13344
13345/**
13346 * The default setting for {@link Object3D#matrixWorldAutoUpdate} for
13347 * newly created 3D objects.
13348 *
13349 * @static
13350 * @type {boolean}
13351 * @default true
13352 */
13353Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE = true;
13354
13355/**
13356 * This is almost identical to an {@link Object3D}. Its purpose is to
13357 * make working with groups of objects syntactically clearer.
13358 *
13359 * ```js
13360 * // Create a group and add the two cubes.
13361 * // These cubes can now be rotated / scaled etc as a group.
13362 * const group = new THREE.Group();
13363 *
13364 * group.add( meshA );
13365 * group.add( meshB );
13366 *
13367 * scene.add( group );
13368 * ```
13369 *
13370 * @augments Object3D
13371 */
13372class Group extends Object3D {
13373
13374	constructor() {
13375
13376		super();
13377
13378		/**
13379		 * This flag can be used for type testing.
13380		 *
13381		 * @type {boolean}
13382		 * @readonly
13383		 * @default true
13384		 */
13385		this.isGroup = true;
13386
13387		this.type = 'Group';
13388
13389	}
13390
13391}
13392
13393const _moveEvent = { type: 'move' };
13394
13395/**
13396 * Class for representing a XR controller with its
13397 * different coordinate systems.
13398 *
13399 * @private
13400 */
13401class WebXRController {
13402
13403	/**
13404	 * Constructs a new XR controller.
13405	 */
13406	constructor() {
13407
13408		/**
13409		 * A group representing the target ray space
13410		 * of the XR controller.
13411		 *
13412		 * @private
13413		 * @type {?Group}
13414		 * @default null
13415		 */
13416		this._targetRay = null;
13417
13418		/**
13419		 * A group representing the grip space
13420		 * of the XR controller.
13421		 *
13422		 * @private
13423		 * @type {?Group}
13424		 * @default null
13425		 */
13426		this._grip = null;
13427
13428		/**
13429		 * A group representing the hand space
13430		 * of the XR controller.
13431		 *
13432		 * @private
13433		 * @type {?Group}
13434		 * @default null
13435		 */
13436		this._hand = null;
13437
13438	}
13439
13440	/**
13441	 * Returns a group representing the hand space of the XR controller.
13442	 *
13443	 * @return {Group} A group representing the hand space of the XR controller.
13444	 */
13445	getHandSpace() {
13446
13447		if ( this._hand === null ) {
13448
13449			this._hand = new Group();
13450			this._hand.matrixAutoUpdate = false;
13451			this._hand.visible = false;
13452
13453			this._hand.joints = {};
13454			this._hand.inputState = { pinching: false };
13455
13456		}
13457
13458		return this._hand;
13459
13460	}
13461
13462	/**
13463	 * Returns a group representing the target ray space of the XR controller.
13464	 *
13465	 * @return {Group} A group representing the target ray space of the XR controller.
13466	 */
13467	getTargetRaySpace() {
13468
13469		if ( this._targetRay === null ) {
13470
13471			this._targetRay = new Group();
13472			this._targetRay.matrixAutoUpdate = false;
13473			this._targetRay.visible = false;
13474			this._targetRay.hasLinearVelocity = false;
13475			this._targetRay.linearVelocity = new Vector3();
13476			this._targetRay.hasAngularVelocity = false;
13477			this._targetRay.angularVelocity = new Vector3();
13478
13479		}
13480
13481		return this._targetRay;
13482
13483	}
13484
13485	/**
13486	 * Returns a group representing the grip space of the XR controller.
13487	 *
13488	 * @return {Group} A group representing the grip space of the XR controller.
13489	 */
13490	getGripSpace() {
13491
13492		if ( this._grip === null ) {
13493
13494			this._grip = new Group();
13495			this._grip.matrixAutoUpdate = false;
13496			this._grip.visible = false;
13497			this._grip.hasLinearVelocity = false;
13498			this._grip.linearVelocity = new Vector3();
13499			this._grip.hasAngularVelocity = false;
13500			this._grip.angularVelocity = new Vector3();
13501			this._grip.eventsEnabled = false;
13502
13503		}
13504
13505		return this._grip;
13506
13507	}
13508
13509	/**
13510	 * Dispatches the given event to the groups representing
13511	 * the different coordinate spaces of the XR controller.
13512	 *
13513	 * @param {Object} event - The event to dispatch.
13514	 * @return {WebXRController} A reference to this instance.
13515	 */
13516	dispatchEvent( event ) {
13517
13518		if ( this._targetRay !== null ) {
13519
13520			this._targetRay.dispatchEvent( event );
13521
13522		}
13523
13524		if ( this._grip !== null ) {
13525
13526			this._grip.dispatchEvent( event );
13527
13528		}
13529
13530		if ( this._hand !== null ) {
13531
13532			this._hand.dispatchEvent( event );
13533
13534		}
13535
13536		return this;
13537
13538	}
13539
13540	/**
13541	 * Connects the controller with the given XR input source.
13542	 *
13543	 * @param {XRInputSource} inputSource - The input source.
13544	 * @return {WebXRController} A reference to this instance.
13545	 */
13546	connect( inputSource ) {
13547
13548		if ( inputSource && inputSource.hand ) {
13549
13550			const hand = this._hand;
13551
13552			if ( hand ) {
13553
13554				for ( const inputjoint of inputSource.hand.values() ) {
13555
13556					// Initialize hand with joints when connected
13557					this._getHandJoint( hand, inputjoint );
13558
13559				}
13560
13561			}
13562
13563		}
13564
13565		this.dispatchEvent( { type: 'connected', data: inputSource } );
13566
13567		return this;
13568
13569	}
13570
13571	/**
13572	 * Disconnects the controller from the given XR input source.
13573	 *
13574	 * @param {XRInputSource} inputSource - The input source.
13575	 * @return {WebXRController} A reference to this instance.
13576	 */
13577	disconnect( inputSource ) {
13578
13579		this.dispatchEvent( { type: 'disconnected', data: inputSource } );
13580
13581		if ( this._targetRay !== null ) {
13582
13583			this._targetRay.visible = false;
13584
13585		}
13586
13587		if ( this._grip !== null ) {
13588
13589			this._grip.visible = false;
13590
13591		}
13592
13593		if ( this._hand !== null ) {
13594
13595			this._hand.visible = false;
13596
13597		}
13598
13599		return this;
13600
13601	}
13602
13603	/**
13604	 * Updates the controller with the given input source, XR frame and reference space.
13605	 * This updates the transformations of the groups that represent the different
13606	 * coordinate systems of the controller.
13607	 *
13608	 * @param {XRInputSource} inputSource - The input source.
13609	 * @param {XRFrame} frame - The XR frame.
13610	 * @param {XRReferenceSpace} referenceSpace - The reference space.
13611	 * @return {WebXRController} A reference to this instance.
13612	 */
13613	update( inputSource, frame, referenceSpace ) {
13614
13615		let inputPose = null;
13616		let gripPose = null;
13617		let handPose = null;
13618
13619		const targetRay = this._targetRay;
13620		const grip = this._grip;
13621		const hand = this._hand;
13622
13623		if ( inputSource && frame.session.visibilityState !== 'visible-blurred' ) {
13624
13625			if ( hand && inputSource.hand ) {
13626
13627				handPose = true;
13628
13629				for ( const inputjoint of inputSource.hand.values() ) {
13630
13631					// Update the joints groups with the XRJoint poses
13632					const jointPose = frame.getJointPose( inputjoint, referenceSpace );
13633
13634					// The transform of this joint will be updated with the joint pose on each frame
13635					const joint = this._getHandJoint( hand, inputjoint );
13636
13637					if ( jointPose !== null ) {
13638
13639						joint.matrix.fromArray( jointPose.transform.matrix );
13640						joint.matrix.decompose( joint.position, joint.rotation, joint.scale );
13641						joint.matrixWorldNeedsUpdate = true;
13642						joint.jointRadius = jointPose.radius;
13643
13644					}
13645
13646					joint.visible = jointPose !== null;
13647
13648				}
13649
13650				// Custom events
13651
13652				// Check pinchz
13653				const indexTip = hand.joints[ 'index-finger-tip' ];
13654				const thumbTip = hand.joints[ 'thumb-tip' ];
13655				const distance = indexTip.position.distanceTo( thumbTip.position );
13656
13657				const distanceToPinch = 0.02;
13658				const threshold = 0.005;
13659
13660				if ( hand.inputState.pinching && distance > distanceToPinch + threshold ) {
13661
13662					hand.inputState.pinching = false;
13663					this.dispatchEvent( {
13664						type: 'pinchend',
13665						handedness: inputSource.handedness,
13666						target: this
13667					} );
13668
13669				} else if ( ! hand.inputState.pinching && distance <= distanceToPinch - threshold ) {
13670
13671					hand.inputState.pinching = true;
13672					this.dispatchEvent( {
13673						type: 'pinchstart',
13674						handedness: inputSource.handedness,
13675						target: this
13676					} );
13677
13678				}
13679
13680			} else {
13681
13682				if ( grip !== null && inputSource.gripSpace ) {
13683
13684					gripPose = frame.getPose( inputSource.gripSpace, referenceSpace );
13685
13686					if ( gripPose !== null ) {
13687
13688						grip.matrix.fromArray( gripPose.transform.matrix );
13689						grip.matrix.decompose( grip.position, grip.rotation, grip.scale );
13690						grip.matrixWorldNeedsUpdate = true;
13691
13692						if ( gripPose.linearVelocity ) {
13693
13694							grip.hasLinearVelocity = true;
13695							grip.linearVelocity.copy( gripPose.linearVelocity );
13696
13697						} else {
13698
13699							grip.hasLinearVelocity = false;
13700
13701						}
13702
13703						if ( gripPose.angularVelocity ) {
13704
13705							grip.hasAngularVelocity = true;
13706							grip.angularVelocity.copy( gripPose.angularVelocity );
13707
13708						} else {
13709
13710							grip.hasAngularVelocity = false;
13711
13712						}
13713
13714						// grip update event if enabled
13715						if ( grip.eventsEnabled ) {
13716
13717							grip.dispatchEvent( {
13718								type: 'gripUpdated',
13719								data: inputSource,
13720								target: this
13721							} );
13722
13723						}
13724
13725					}
13726
13727				}
13728
13729			}
13730
13731			if ( targetRay !== null ) {
13732
13733				inputPose = frame.getPose( inputSource.targetRaySpace, referenceSpace );
13734
13735				// Some runtimes (namely Vive Cosmos with Vive OpenXR Runtime) have only grip space and ray space is equal to it
13736				if ( inputPose === null && gripPose !== null ) {
13737
13738					inputPose = gripPose;
13739
13740				}
13741
13742				if ( inputPose !== null ) {
13743
13744					targetRay.matrix.fromArray( inputPose.transform.matrix );
13745					targetRay.matrix.decompose( targetRay.position, targetRay.rotation, targetRay.scale );
13746					targetRay.matrixWorldNeedsUpdate = true;
13747
13748					if ( inputPose.linearVelocity ) {
13749
13750						targetRay.hasLinearVelocity = true;
13751						targetRay.linearVelocity.copy( inputPose.linearVelocity );
13752
13753					} else {
13754
13755						targetRay.hasLinearVelocity = false;
13756
13757					}
13758
13759					if ( inputPose.angularVelocity ) {
13760
13761						targetRay.hasAngularVelocity = true;
13762						targetRay.angularVelocity.copy( inputPose.angularVelocity );
13763
13764					} else {
13765
13766						targetRay.hasAngularVelocity = false;
13767
13768					}
13769
13770					this.dispatchEvent( _moveEvent );
13771
13772				}
13773
13774			}
13775
13776
13777		}
13778
13779		if ( targetRay !== null ) {
13780
13781			targetRay.visible = ( inputPose !== null );
13782
13783		}
13784
13785		if ( grip !== null ) {
13786
13787			grip.visible = ( gripPose !== null );
13788
13789		}
13790
13791		if ( hand !== null ) {
13792
13793			hand.visible = ( handPose !== null );
13794
13795		}
13796
13797		return this;
13798
13799	}
13800
13801	/**
13802	 * Returns a group representing the hand joint for the given input joint.
13803	 *
13804	 * @private
13805	 * @param {Group} hand - The group representing the hand space.
13806	 * @param {XRJointSpace} inputjoint - The hand joint data.
13807	 * @return {Group} A group representing the hand joint for the given input joint.
13808	 */
13809	_getHandJoint( hand, inputjoint ) {
13810
13811		if ( hand.joints[ inputjoint.jointName ] === undefined ) {
13812
13813			const joint = new Group();
13814			joint.matrixAutoUpdate = false;
13815			joint.visible = false;
13816			hand.joints[ inputjoint.jointName ] = joint;
13817
13818			hand.add( joint );
13819
13820		}
13821
13822		return hand.joints[ inputjoint.jointName ];
13823
13824	}
13825
13826}
13827
13828const _colorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF,
13829	'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2,
13830	'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50,
13831	'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B,
13832	'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B,
13833	'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F,
13834	'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3,
13835	'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222,
13836	'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700,
13837	'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4,
13838	'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00,
13839	'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3,
13840	'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA,
13841	'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32,
13842	'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3,
13843	'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC,
13844	'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD,
13845	'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6,
13846	'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9,
13847	'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F,
13848	'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE,
13849	'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA,
13850	'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0,
13851	'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 };
13852
13853const _hslA = { h: 0, s: 0, l: 0 };
13854const _hslB = { h: 0, s: 0, l: 0 };
13855
13856function hue2rgb( p, q, t ) {
13857
13858	if ( t < 0 ) t += 1;
13859	if ( t > 1 ) t -= 1;
13860	if ( t < 1 / 6 ) return p + ( q - p ) * 6 * t;
13861	if ( t < 1 / 2 ) return q;
13862	if ( t < 2 / 3 ) return p + ( q - p ) * 6 * ( 2 / 3 - t );
13863	return p;
13864
13865}
13866
13867/**
13868 * A Color instance is represented by RGB components in the linear <i>working
13869 * color space</i>, which defaults to `LinearSRGBColorSpace`. Inputs
13870 * conventionally using `SRGBColorSpace` (such as hexadecimals and CSS
13871 * strings) are converted to the working color space automatically.
13872 *
13873 * ```js
13874 * // converted automatically from SRGBColorSpace to LinearSRGBColorSpace
13875 * const color = new THREE.Color().setHex( 0x112233 );
13876 * ```
13877 * Source color spaces may be specified explicitly, to ensure correct conversions.
13878 * ```js
13879 * // assumed already LinearSRGBColorSpace; no conversion
13880 * const color = new THREE.Color().setRGB( 0.5, 0.5, 0.5 );
13881 *
13882 * // converted explicitly from SRGBColorSpace to LinearSRGBColorSpace
13883 * const color = new THREE.Color().setRGB( 0.5, 0.5, 0.5, SRGBColorSpace );
13884 * ```
13885 * If THREE.ColorManagement is disabled, no conversions occur. For details,
13886 * see <i>Color management</i>. Iterating through a Color instance will yield
13887 * its components (r, g, b) in the corresponding order. A Color can be initialised
13888 * in any of the following ways:
13889 * ```js
13890 * //empty constructor - will default white
13891 * const color1 = new THREE.Color();
13892 *
13893 * //Hexadecimal color (recommended)
13894 * const color2 = new THREE.Color( 0xff0000 );
13895 *
13896 * //RGB string
13897 * const color3 = new THREE.Color("rgb(255, 0, 0)");
13898 * const color4 = new THREE.Color("rgb(100%, 0%, 0%)");
13899 *
13900 * //X11 color name - all 140 color names are supported.
13901 * //Note the lack of CamelCase in the name
13902 * const color5 = new THREE.Color( 'skyblue' );
13903 * //HSL string
13904 * const color6 = new THREE.Color("hsl(0, 100%, 50%)");
13905 *
13906 * //Separate RGB values between 0 and 1
13907 * const color7 = new THREE.Color( 1, 0, 0 );
13908 * ```
13909 */
13910class Color {
13911
13912	/**
13913	 * Constructs a new color.
13914	 *
13915	 * Note that standard method of specifying color in three.js is with a hexadecimal triplet,
13916	 * and that method is used throughout the rest of the documentation.
13917	 *
13918	 * @param {(number|string|Color)} [r] - The red component of the color. If `g` and `b` are
13919	 * not provided, it can be hexadecimal triplet, a CSS-style string or another `Color` instance.
13920	 * @param {number} [g] - The green component.
13921	 * @param {number} [b] - The blue component.
13922	 */
13923	constructor( r, g, b ) {
13924
13925		/**
13926		 * This flag can be used for type testing.
13927		 *
13928		 * @type {boolean}
13929		 * @readonly
13930		 * @default true
13931		 */
13932		this.isColor = true;
13933
13934		/**
13935		 * The red component.
13936		 *
13937		 * @type {number}
13938		 * @default 1
13939		 */
13940		this.r = 1;
13941
13942		/**
13943		 * The green component.
13944		 *
13945		 * @type {number}
13946		 * @default 1
13947		 */
13948		this.g = 1;
13949
13950		/**
13951		 * The blue component.
13952		 *
13953		 * @type {number}
13954		 * @default 1
13955		 */
13956		this.b = 1;
13957
13958		return this.set( r, g, b );
13959
13960	}
13961
13962	/**
13963	 * Sets the colors's components from the given values.
13964	 *
13965	 * @param {(number|string|Color)} [r] - The red component of the color. If `g` and `b` are
13966	 * not provided, it can be hexadecimal triplet, a CSS-style string or another `Color` instance.
13967	 * @param {number} [g] - The green component.
13968	 * @param {number} [b] - The blue component.
13969	 * @return {Color} A reference to this color.
13970	 */
13971	set( r, g, b ) {
13972
13973		if ( g === undefined && b === undefined ) {
13974
13975			// r is THREE.Color, hex or string
13976
13977			const value = r;
13978
13979			if ( value && value.isColor ) {
13980
13981				this.copy( value );
13982
13983			} else if ( typeof value === 'number' ) {
13984
13985				this.setHex( value );
13986
13987			} else if ( typeof value === 'string' ) {
13988
13989				this.setStyle( value );
13990
13991			}
13992
13993		} else {
13994
13995			this.setRGB( r, g, b );
13996
13997		}
13998
13999		return this;
14000
14001	}
14002
14003	/**
14004	 * Sets the colors's components to the given scalar value.
14005	 *
14006	 * @param {number} scalar - The scalar value.
14007	 * @return {Color} A reference to this color.
14008	 */
14009	setScalar( scalar ) {
14010
14011		this.r = scalar;
14012		this.g = scalar;
14013		this.b = scalar;
14014
14015		return this;
14016
14017	}
14018
14019	/**
14020	 * Sets this color from a hexadecimal value.
14021	 *
14022	 * @param {number} hex - The hexadecimal value.
14023	 * @param {string} [colorSpace=SRGBColorSpace] - The color space.
14024	 * @return {Color} A reference to this color.
14025	 */
14026	setHex( hex, colorSpace = SRGBColorSpace ) {
14027
14028		hex = Math.floor( hex );
14029
14030		this.r = ( hex >> 16 & 255 ) / 255;
14031		this.g = ( hex >> 8 & 255 ) / 255;
14032		this.b = ( hex & 255 ) / 255;
14033
14034		ColorManagement.colorSpaceToWorking( this, colorSpace );
14035
14036		return this;
14037
14038	}
14039
14040	/**
14041	 * Sets this color from RGB values.
14042	 *
14043	 * @param {number} r - Red channel value between `0.0` and `1.0`.
14044	 * @param {number} g - Green channel value between `0.0` and `1.0`.
14045	 * @param {number} b - Blue channel value between `0.0` and `1.0`.
14046	 * @param {string} [colorSpace=ColorManagement.workingColorSpace] - The color space.
14047	 * @return {Color} A reference to this color.
14048	 */
14049	setRGB( r, g, b, colorSpace = ColorManagement.workingColorSpace ) {
14050
14051		this.r = r;
14052		this.g = g;
14053		this.b = b;
14054
14055		ColorManagement.colorSpaceToWorking( this, colorSpace );
14056
14057		return this;
14058
14059	}
14060
14061	/**
14062	 * Sets this color from RGB values.
14063	 *
14064	 * @param {number} h - Hue value between `0.0` and `1.0`.
14065	 * @param {number} s - Saturation value between `0.0` and `1.0`.
14066	 * @param {number} l - Lightness value between `0.0` and `1.0`.
14067	 * @param {string} [colorSpace=ColorManagement.workingColorSpace] - The color space.
14068	 * @return {Color} A reference to this color.
14069	 */
14070	setHSL( h, s, l, colorSpace = ColorManagement.workingColorSpace ) {
14071
14072		// h,s,l ranges are in 0.0 - 1.0
14073		h = euclideanModulo( h, 1 );
14074		s = clamp( s, 0, 1 );
14075		l = clamp( l, 0, 1 );
14076
14077		if ( s === 0 ) {
14078
14079			this.r = this.g = this.b = l;
14080
14081		} else {
14082
14083			const p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s );
14084			const q = ( 2 * l ) - p;
14085
14086			this.r = hue2rgb( q, p, h + 1 / 3 );
14087			this.g = hue2rgb( q, p, h );
14088			this.b = hue2rgb( q, p, h - 1 / 3 );
14089
14090		}
14091
14092		ColorManagement.colorSpaceToWorking( this, colorSpace );
14093
14094		return this;
14095
14096	}
14097
14098	/**
14099	 * Sets this color from a CSS-style string. For example, `rgb(250, 0,0)`,
14100	 * `rgb(100%, 0%, 0%)`, `hsl(0, 100%, 50%)`, `#ff0000`, `#f00`, or `red` ( or
14101	 * any [X11 color name](https://en.wikipedia.org/wiki/X11_color_names#Color_name_chart) -
14102	 * all 140 color names are supported).
14103	 *
14104	 * @param {string} style - Color as a CSS-style string.
14105	 * @param {string} [colorSpace=SRGBColorSpace] - The color space.
14106	 * @return {Color} A reference to this color.
14107	 */
14108	setStyle( style, colorSpace = SRGBColorSpace ) {
14109
14110		function handleAlpha( string ) {
14111
14112			if ( string === undefined ) return;
14113
14114			if ( parseFloat( string ) < 1 ) {
14115
14116				warn( 'Color: Alpha component of ' + style + ' will be ignored.' );
14117
14118			}
14119
14120		}
14121
14122
14123		let m;
14124
14125		if ( m = /^(\w+)\(([^\)]*)\)/.exec( style ) ) {
14126
14127			// rgb / hsl
14128
14129			let color;
14130			const name = m[ 1 ];
14131			const components = m[ 2 ];
14132
14133			switch ( name ) {
14134
14135				case 'rgb':
14136				case 'rgba':
14137
14138					if ( color = /^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) {
14139
14140						// rgb(255,0,0) rgba(255,0,0,0.5)
14141
14142						handleAlpha( color[ 4 ] );
14143
14144						return this.setRGB(
14145							Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255,
14146							Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255,
14147							Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255,
14148							colorSpace
14149						);
14150
14151					}
14152
14153					if ( color = /^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) {
14154
14155						// rgb(100%,0%,0%) rgba(100%,0%,0%,0.5)
14156
14157						handleAlpha( color[ 4 ] );
14158
14159						return this.setRGB(
14160							Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100,
14161							Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100,
14162							Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100,
14163							colorSpace
14164						);
14165
14166					}
14167
14168					break;
14169
14170				case 'hsl':
14171				case 'hsla':
14172
14173					if ( color = /^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) {
14174
14175						// hsl(120,50%,50%) hsla(120,50%,50%,0.5)
14176
14177						handleAlpha( color[ 4 ] );
14178
14179						return this.setHSL(
14180							parseFloat( color[ 1 ] ) / 360,
14181							parseFloat( color[ 2 ] ) / 100,
14182							parseFloat( color[ 3 ] ) / 100,
14183							colorSpace
14184						);
14185
14186					}
14187
14188					break;
14189
14190				default:
14191
14192					warn( 'Color: Unknown color model ' + style );
14193
14194			}
14195
14196		} else if ( m = /^\#([A-Fa-f\d]+)$/.exec( style ) ) {
14197
14198			// hex color
14199
14200			const hex = m[ 1 ];
14201			const size = hex.length;
14202
14203			if ( size === 3 ) {
14204
14205				// #ff0
14206				return this.setRGB(
14207					parseInt( hex.charAt( 0 ), 16 ) / 15,
14208					parseInt( hex.charAt( 1 ), 16 ) / 15,
14209					parseInt( hex.charAt( 2 ), 16 ) / 15,
14210					colorSpace
14211				);
14212
14213			} else if ( size === 6 ) {
14214
14215				// #ff0000
14216				return this.setHex( parseInt( hex, 16 ), colorSpace );
14217
14218			} else {
14219
14220				warn( 'Color: Invalid hex color ' + style );
14221
14222			}
14223
14224		} else if ( style && style.length > 0 ) {
14225
14226			return this.setColorName( style, colorSpace );
14227
14228		}
14229
14230		return this;
14231
14232	}
14233
14234	/**
14235	 * Sets this color from a color name. Faster than {@link Color#setStyle} if
14236	 * you don't need the other CSS-style formats.
14237	 *
14238	 * For convenience, the list of names is exposed in `Color.NAMES` as a hash.
14239	 * ```js
14240	 * Color.NAMES.aliceblue // returns 0xF0F8FF
14241	 * ```
14242	 *
14243	 * @param {string} style - The color name.
14244	 * @param {string} [colorSpace=SRGBColorSpace] - The color space.
14245	 * @return {Color} A reference to this color.
14246	 */
14247	setColorName( style, colorSpace = SRGBColorSpace ) {
14248
14249		// color keywords
14250		const hex = _colorKeywords[ style.toLowerCase() ];
14251
14252		if ( hex !== undefined ) {
14253
14254			// red
14255			this.setHex( hex, colorSpace );
14256
14257		} else {
14258
14259			// unknown color
14260			warn( 'Color: Unknown color ' + style );
14261
14262		}
14263
14264		return this;
14265
14266	}
14267
14268	/**
14269	 * Returns a new color with copied values from this instance.
14270	 *
14271	 * @return {Color} A clone of this instance.
14272	 */
14273	clone() {
14274
14275		return new this.constructor( this.r, this.g, this.b );
14276
14277	}
14278
14279	/**
14280	 * Copies the values of the given color to this instance.
14281	 *
14282	 * @param {Color} color - The color to copy.
14283	 * @return {Color} A reference to this color.
14284	 */
14285	copy( color ) {
14286
14287		this.r = color.r;
14288		this.g = color.g;
14289		this.b = color.b;
14290
14291		return this;
14292
14293	}
14294
14295	/**
14296	 * Copies the given color into this color, and then converts this color from
14297	 * `SRGBColorSpace` to `LinearSRGBColorSpace`.
14298	 *
14299	 * @param {Color} color - The color to copy/convert.
14300	 * @return {Color} A reference to this color.
14301	 */
14302	copySRGBToLinear( color ) {
14303
14304		this.r = SRGBToLinear( color.r );
14305		this.g = SRGBToLinear( color.g );
14306		this.b = SRGBToLinear( color.b );
14307
14308		return this;
14309
14310	}
14311
14312	/**
14313	 * Copies the given color into this color, and then converts this color from
14314	 * `LinearSRGBColorSpace` to `SRGBColorSpace`.
14315	 *
14316	 * @param {Color} color - The color to copy/convert.
14317	 * @return {Color} A reference to this color.
14318	 */
14319	copyLinearToSRGB( color ) {
14320
14321		this.r = LinearToSRGB( color.r );
14322		this.g = LinearToSRGB( color.g );
14323		this.b = LinearToSRGB( color.b );
14324
14325		return this;
14326
14327	}
14328
14329	/**
14330	 * Converts this color from `SRGBColorSpace` to `LinearSRGBColorSpace`.
14331	 *
14332	 * @return {Color} A reference to this color.
14333	 */
14334	convertSRGBToLinear() {
14335
14336		this.copySRGBToLinear( this );
14337
14338		return this;
14339
14340	}
14341
14342	/**
14343	 * Converts this color from `LinearSRGBColorSpace` to `SRGBColorSpace`.
14344	 *
14345	 * @return {Color} A reference to this color.
14346	 */
14347	convertLinearToSRGB() {
14348
14349		this.copyLinearToSRGB( this );
14350
14351		return this;
14352
14353	}
14354
14355	/**
14356	 * Returns the hexadecimal value of this color.
14357	 *
14358	 * @param {string} [colorSpace=SRGBColorSpace] - The color space.
14359	 * @return {number} The hexadecimal value.
14360	 */
14361	getHex( colorSpace = SRGBColorSpace ) {
14362
14363		ColorManagement.workingToColorSpace( _color.copy( this ), colorSpace );
14364
14365		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 ) );
14366
14367	}
14368
14369	/**
14370	 * Returns the hexadecimal value of this color as a string (for example, 'FFFFFF').
14371	 *
14372	 * @param {string} [colorSpace=SRGBColorSpace] - The color space.
14373	 * @return {string} The hexadecimal value as a string.
14374	 */
14375	getHexString( colorSpace = SRGBColorSpace ) {
14376
14377		return ( '000000' + this.getHex( colorSpace ).toString( 16 ) ).slice( -6 );
14378
14379	}
14380
14381	/**
14382	 * Converts the colors RGB values into the HSL format and stores them into the
14383	 * given target object.
14384	 *
14385	 * @param {{h:number,s:number,l:number}} target - The target object that is used to store the method's result.
14386	 * @param {string} [colorSpace=ColorManagement.workingColorSpace] - The color space.
14387	 * @return {{h:number,s:number,l:number}} The HSL representation of this color.
14388	 */
14389	getHSL( target, colorSpace = ColorManagement.workingColorSpace ) {
14390
14391		// h,s,l ranges are in 0.0 - 1.0
14392
14393		ColorManagement.workingToColorSpace( _color.copy( this ), colorSpace );
14394
14395		const r = _color.r, g = _color.g, b = _color.b;
14396
14397		const max = Math.max( r, g, b );
14398		const min = Math.min( r, g, b );
14399
14400		let hue, saturation;
14401		const lightness = ( min + max ) / 2.0;
14402
14403		if ( min === max ) {
14404
14405			hue = 0;
14406			saturation = 0;
14407
14408		} else {
14409
14410			const delta = max - min;
14411
14412			saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min );
14413
14414			switch ( max ) {
14415
14416				case r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break;
14417				case g: hue = ( b - r ) / delta + 2; break;
14418				case b: hue = ( r - g ) / delta + 4; break;
14419
14420			}
14421
14422			hue /= 6;
14423
14424		}
14425
14426		target.h = hue;
14427		target.s = saturation;
14428		target.l = lightness;
14429
14430		return target;
14431
14432	}
14433
14434	/**
14435	 * Returns the RGB values of this color and stores them into the given target object.
14436	 *
14437	 * @param {Color} target - The target color that is used to store the method's result.
14438	 * @param {string} [colorSpace=ColorManagement.workingColorSpace] - The color space.
14439	 * @return {Color} The RGB representation of this color.
14440	 */
14441	getRGB( target, colorSpace = ColorManagement.workingColorSpace ) {
14442
14443		ColorManagement.workingToColorSpace( _color.copy( this ), colorSpace );
14444
14445		target.r = _color.r;
14446		target.g = _color.g;
14447		target.b = _color.b;
14448
14449		return target;
14450
14451	}
14452
14453	/**
14454	 * Returns the value of this color as a CSS style string. Example: `rgb(255,0,0)`.
14455	 *
14456	 * @param {string} [colorSpace=SRGBColorSpace] - The color space.
14457	 * @return {string} The CSS representation of this color.
14458	 */
14459	getStyle( colorSpace = SRGBColorSpace ) {
14460
14461		ColorManagement.workingToColorSpace( _color.copy( this ), colorSpace );
14462
14463		const r = _color.r, g = _color.g, b = _color.b;
14464
14465		if ( colorSpace !== SRGBColorSpace ) {
14466
14467			// Requires CSS Color Module Level 4 (https://www.w3.org/TR/css-color-4/).
14468			return `color(${ colorSpace } ${ r.toFixed( 3 ) } ${ g.toFixed( 3 ) } ${ b.toFixed( 3 ) })`;
14469
14470		}
14471
14472		return `rgb(${ Math.round( r * 255 ) },${ Math.round( g * 255 ) },${ Math.round( b * 255 ) })`;
14473
14474	}
14475
14476	/**
14477	 * Adds the given HSL values to this color's values.
14478	 * Internally, this converts the color's RGB values to HSL, adds HSL
14479	 * and then converts the color back to RGB.
14480	 *
14481	 * @param {number} h - Hue value between `0.0` and `1.0`.
14482	 * @param {number} s - Saturation value between `0.0` and `1.0`.
14483	 * @param {number} l - Lightness value between `0.0` and `1.0`.
14484	 * @return {Color} A reference to this color.
14485	 */
14486	offsetHSL( h, s, l ) {
14487
14488		this.getHSL( _hslA );
14489
14490		return this.setHSL( _hslA.h + h, _hslA.s + s, _hslA.l + l );
14491
14492	}
14493
14494	/**
14495	 * Adds the RGB values of the given color to the RGB values of this color.
14496	 *
14497	 * @param {Color} color - The color to add.
14498	 * @return {Color} A reference to this color.
14499	 */
14500	add( color ) {
14501
14502		this.r += color.r;
14503		this.g += color.g;
14504		this.b += color.b;
14505
14506		return this;
14507
14508	}
14509
14510	/**
14511	 * Adds the RGB values of the given colors and stores the result in this instance.
14512	 *
14513	 * @param {Color} color1 - The first color.
14514	 * @param {Color} color2 - The second color.
14515	 * @return {Color} A reference to this color.
14516	 */
14517	addColors( color1, color2 ) {
14518
14519		this.r = color1.r + color2.r;
14520		this.g = color1.g + color2.g;
14521		this.b = color1.b + color2.b;
14522
14523		return this;
14524
14525	}
14526
14527	/**
14528	 * Adds the given scalar value to the RGB values of this color.
14529	 *
14530	 * @param {number} s - The scalar to add.
14531	 * @return {Color} A reference to this color.
14532	 */
14533	addScalar( s ) {
14534
14535		this.r += s;
14536		this.g += s;
14537		this.b += s;
14538
14539		return this;
14540
14541	}
14542
14543	/**
14544	 * Subtracts the RGB values of the given color from the RGB values of this color.
14545	 *
14546	 * @param {Color} color - The color to subtract.
14547	 * @return {Color} A reference to this color.
14548	 */
14549	sub( color ) {
14550
14551		this.r = Math.max( 0, this.r - color.r );
14552		this.g = Math.max( 0, this.g - color.g );
14553		this.b = Math.max( 0, this.b - color.b );
14554
14555		return this;
14556
14557	}
14558
14559	/**
14560	 * Multiplies the RGB values of the given color with the RGB values of this color.
14561	 *
14562	 * @param {Color} color - The color to multiply.
14563	 * @return {Color} A reference to this color.
14564	 */
14565	multiply( color ) {
14566
14567		this.r *= color.r;
14568		this.g *= color.g;
14569		this.b *= color.b;
14570
14571		return this;
14572
14573	}
14574
14575	/**
14576	 * Multiplies the given scalar value with the RGB values of this color.
14577	 *
14578	 * @param {number} s - The scalar to multiply.
14579	 * @return {Color} A reference to this color.
14580	 */
14581	multiplyScalar( s ) {
14582
14583		this.r *= s;
14584		this.g *= s;
14585		this.b *= s;
14586
14587		return this;
14588
14589	}
14590
14591	/**
14592	 * Linearly interpolates this color's RGB values toward the RGB values of the
14593	 * given color. The alpha argument can be thought of as the ratio between
14594	 * the two colors, where `0.0` is this color and `1.0` is the first argument.
14595	 *
14596	 * @param {Color} color - The color to converge on.
14597	 * @param {number} alpha - The interpolation factor in the closed interval `[0,1]`.
14598	 * @return {Color} A reference to this color.
14599	 */
14600	lerp( color, alpha ) {
14601
14602		this.r += ( color.r - this.r ) * alpha;
14603		this.g += ( color.g - this.g ) * alpha;
14604		this.b += ( color.b - this.b ) * alpha;
14605
14606		return this;
14607
14608	}
14609
14610	/**
14611	 * Linearly interpolates between the given colors and stores the result in this instance.
14612	 * The alpha argument can be thought of as the ratio between the two colors, where `0.0`
14613	 * is the first and `1.0` is the second color.
14614	 *
14615	 * @param {Color} color1 - The first color.
14616	 * @param {Color} color2 - The second color.
14617	 * @param {number} alpha - The interpolation factor in the closed interval `[0,1]`.
14618	 * @return {Color} A reference to this color.
14619	 */
14620	lerpColors( color1, color2, alpha ) {
14621
14622		this.r = color1.r + ( color2.r - color1.r ) * alpha;
14623		this.g = color1.g + ( color2.g - color1.g ) * alpha;
14624		this.b = color1.b + ( color2.b - color1.b ) * alpha;
14625
14626		return this;
14627
14628	}
14629
14630	/**
14631	 * Linearly interpolates this color's HSL values toward the HSL values of the
14632	 * given color. It differs from {@link Color#lerp} by not interpolating straight
14633	 * from one color to the other, but instead going through all the hues in between
14634	 * those two colors. The alpha argument can be thought of as the ratio between
14635	 * the two colors, where 0.0 is this color and 1.0 is the first argument.
14636	 *
14637	 * @param {Color} color - The color to converge on.
14638	 * @param {number} alpha - The interpolation factor in the closed interval `[0,1]`.
14639	 * @return {Color} A reference to this color.
14640	 */
14641	lerpHSL( color, alpha ) {
14642
14643		this.getHSL( _hslA );
14644		color.getHSL( _hslB );
14645
14646		const h = lerp( _hslA.h, _hslB.h, alpha );
14647		const s = lerp( _hslA.s, _hslB.s, alpha );
14648		const l = lerp( _hslA.l, _hslB.l, alpha );
14649
14650		this.setHSL( h, s, l );
14651
14652		return this;
14653
14654	}
14655
14656	/**
14657	 * Sets the color's RGB components from the given 3D vector.
14658	 *
14659	 * @param {Vector3} v - The vector to set.
14660	 * @return {Color} A reference to this color.
14661	 */
14662	setFromVector3( v ) {
14663
14664		this.r = v.x;
14665		this.g = v.y;
14666		this.b = v.z;
14667
14668		return this;
14669
14670	}
14671
14672	/**
14673	 * Transforms this color with the given 3x3 matrix.
14674	 *
14675	 * @param {Matrix3} m - The matrix.
14676	 * @return {Color} A reference to this color.
14677	 */
14678	applyMatrix3( m ) {
14679
14680		const r = this.r, g = this.g, b = this.b;
14681		const e = m.elements;
14682
14683		this.r = e[ 0 ] * r + e[ 3 ] * g + e[ 6 ] * b;
14684		this.g = e[ 1 ] * r + e[ 4 ] * g + e[ 7 ] * b;
14685		this.b = e[ 2 ] * r + e[ 5 ] * g + e[ 8 ] * b;
14686
14687		return this;
14688
14689	}
14690
14691	/**
14692	 * Returns `true` if this color is equal with the given one.
14693	 *
14694	 * @param {Color} c - The color to test for equality.
14695	 * @return {boolean} Whether this bounding color is equal with the given one.
14696	 */
14697	equals( c ) {
14698
14699		return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b );
14700
14701	}
14702
14703	/**
14704	 * Sets this color's RGB components from the given array.
14705	 *
14706	 * @param {Array<number>} array - An array holding the RGB values.
14707	 * @param {number} [offset=0] - The offset into the array.
14708	 * @return {Color} A reference to this color.
14709	 */
14710	fromArray( array, offset = 0 ) {
14711
14712		this.r = array[ offset ];
14713		this.g = array[ offset + 1 ];
14714		this.b = array[ offset + 2 ];
14715
14716		return this;
14717
14718	}
14719
14720	/**
14721	 * Writes the RGB components of this color to the given array. If no array is provided,
14722	 * the method returns a new instance.
14723	 *
14724	 * @param {Array<number>} [array=[]] - The target array holding the color components.
14725	 * @param {number} [offset=0] - Index of the first element in the array.
14726	 * @return {Array<number>} The color components.
14727	 */
14728	toArray( array = [], offset = 0 ) {
14729
14730		array[ offset ] = this.r;
14731		array[ offset + 1 ] = this.g;
14732		array[ offset + 2 ] = this.b;
14733
14734		return array;
14735
14736	}
14737
14738	/**
14739	 * Sets the components of this color from the given buffer attribute.
14740	 *
14741	 * @param {BufferAttribute} attribute - The buffer attribute holding color data.
14742	 * @param {number} index - The index into the attribute.
14743	 * @return {Color} A reference to this color.
14744	 */
14745	fromBufferAttribute( attribute, index ) {
14746
14747		this.r = attribute.getX( index );
14748		this.g = attribute.getY( index );
14749		this.b = attribute.getZ( index );
14750
14751		return this;
14752
14753	}
14754
14755	/**
14756	 * This methods defines the serialization result of this class. Returns the color
14757	 * as a hexadecimal value.
14758	 *
14759	 * @return {number} The hexadecimal value.
14760	 */
14761	toJSON() {
14762
14763		return this.getHex();
14764
14765	}
14766
14767	*[ Symbol.iterator ]() {
14768
14769		yield this.r;
14770		yield this.g;
14771		yield this.b;
14772
14773	}
14774
14775}
14776
14777const _color = /*@__PURE__*/ new Color();
14778
14779/**
14780 * A dictionary with X11 color names.
14781 *
14782 * Note that multiple words such as Dark Orange become the string 'darkorange'.
14783 *
14784 * @static
14785 * @type {Object}
14786 */
14787Color.NAMES = _colorKeywords;
14788
14789/**
14790 * This class can be used to define an exponential squared fog,
14791 * which gives a clear view near the camera and a faster than exponentially
14792 * densening fog farther from the camera.
14793 *
14794 * ```js
14795 * const scene = new THREE.Scene();
14796 * scene.fog = new THREE.FogExp2( 0xcccccc, 0.002 );
14797 * ```
14798 */
14799class FogExp2 {
14800
14801	/**
14802	 * Constructs a new fog.
14803	 *
14804	 * @param {number|Color} color - The fog's color.
14805	 * @param {number} [density=0.00025] - Defines how fast the fog will grow dense.
14806	 */
14807	constructor( color, density = 0.00025 ) {
14808
14809		/**
14810		 * This flag can be used for type testing.
14811		 *
14812		 * @type {boolean}
14813		 * @readonly
14814		 * @default true
14815		 */
14816		this.isFogExp2 = true;
14817
14818		/**
14819		 * The name of the fog.
14820		 *
14821		 * @type {string}
14822		 */
14823		this.name = '';
14824
14825		/**
14826		 * The fog's color.
14827		 *
14828		 * @type {Color}
14829		 */
14830		this.color = new Color( color );
14831
14832		/**
14833		 *  Defines how fast the fog will grow dense.
14834		 *
14835		 * @type {number}
14836		 * @default 0.00025
14837		 */
14838		this.density = density;
14839
14840	}
14841
14842	/**
14843	 * Returns a new fog with copied values from this instance.
14844	 *
14845	 * @return {FogExp2} A clone of this instance.
14846	 */
14847	clone() {
14848
14849		return new FogExp2( this.color, this.density );
14850
14851	}
14852
14853	/**
14854	 * Serializes the fog into JSON.
14855	 *
14856	 * @param {?(Object|string)} meta - An optional value holding meta information about the serialization.
14857	 * @return {Object} A JSON object representing the serialized fog
14858	 */
14859	toJSON( /* meta */ ) {
14860
14861		return {
14862			type: 'FogExp2',
14863			name: this.name,
14864			color: this.color.getHex(),
14865			density: this.density
14866		};
14867
14868	}
14869
14870}
14871
14872/**
14873 * This class can be used to define a linear fog that grows linearly denser
14874 * with the distance.
14875 *
14876 * ```js
14877 * const scene = new THREE.Scene();
14878 * scene.fog = new THREE.Fog( 0xcccccc, 10, 15 );
14879 * ```
14880 */
14881class Fog {
14882
14883	/**
14884	 * Constructs a new fog.
14885	 *
14886	 * @param {number|Color} color - The fog's color.
14887	 * @param {number} [near=1] - The minimum distance to start applying fog.
14888	 * @param {number} [far=1000] - The maximum distance at which fog stops being calculated and applied.
14889	 */
14890	constructor( color, near = 1, far = 1000 ) {
14891
14892		/**
14893		 * This flag can be used for type testing.
14894		 *
14895		 * @type {boolean}
14896		 * @readonly
14897		 * @default true
14898		 */
14899		this.isFog = true;
14900
14901		/**
14902		 * The name of the fog.
14903		 *
14904		 * @type {string}
14905		 */
14906		this.name = '';
14907
14908		/**
14909		 * The fog's color.
14910		 *
14911		 * @type {Color}
14912		 */
14913		this.color = new Color( color );
14914
14915		/**
14916		 * The minimum distance to start applying fog. Objects that are less than
14917		 * `near` units from the active camera won't be affected by fog.
14918		 *
14919		 * @type {number}
14920		 * @default 1
14921		 */
14922		this.near = near;
14923
14924		/**
14925		 * The maximum distance at which fog stops being calculated and applied.
14926		 * Objects that are more than `far` units away from the active camera won't
14927		 * be affected by fog.
14928		 *
14929		 * @type {number}
14930		 * @default 1000
14931		 */
14932		this.far = far;
14933
14934	}
14935
14936	/**
14937	 * Returns a new fog with copied values from this instance.
14938	 *
14939	 * @return {Fog} A clone of this instance.
14940	 */
14941	clone() {
14942
14943		return new Fog( this.color, this.near, this.far );
14944
14945	}
14946
14947	/**
14948	 * Serializes the fog into JSON.
14949	 *
14950	 * @param {?(Object|string)} meta - An optional value holding meta information about the serialization.
14951	 * @return {Object} A JSON object representing the serialized fog
14952	 */
14953	toJSON( /* meta */ ) {
14954
14955		return {
14956			type: 'Fog',
14957			name: this.name,
14958			color: this.color.getHex(),
14959			near: this.near,
14960			far: this.far
14961		};
14962
14963	}
14964
14965}
14966
14967/**
14968 * Scenes allow you to set up what is to be rendered and where by three.js.
14969 * This is where you place 3D objects like meshes, lines or lights.
14970 *
14971 * @augments Object3D
14972 */
14973class Scene extends Object3D {
14974
14975	/**
14976	 * Constructs a new scene.
14977	 */
14978	constructor() {
14979
14980		super();
14981
14982		/**
14983		 * This flag can be used for type testing.
14984		 *
14985		 * @type {boolean}
14986		 * @readonly
14987		 * @default true
14988		 */
14989		this.isScene = true;
14990
14991		this.type = 'Scene';
14992
14993		/**
14994		 * Defines the background of the scene. Valid inputs are:
14995		 *
14996		 * - A color for defining a uniform colored background.
14997		 * - A texture for defining a (flat) textured background.
14998		 * - Cube textures or equirectangular textures for defining a skybox.
14999		 *
15000		 * @type {?(Color|Texture)}
15001		 * @default null
15002		 */
15003		this.background = null;
15004
15005		/**
15006		 * Sets the environment map for all physical materials in the scene. However,
15007		 * it's not possible to overwrite an existing texture assigned to the `envMap`
15008		 * material property.
15009		 *
15010		 * @type {?Texture}
15011		 * @default null
15012		 */
15013		this.environment = null;
15014
15015		/**
15016		 * A fog instance defining the type of fog that affects everything
15017		 * rendered in the scene.
15018		 *
15019		 * @type {?(Fog|FogExp2)}
15020		 * @default null
15021		 */
15022		this.fog = null;
15023
15024		/**
15025		 * Sets the blurriness of the background. Only influences environment maps
15026		 * assigned to {@link Scene#background}. Valid input is a float between `0`
15027		 * and `1`.
15028		 *
15029		 * @type {number}
15030		 * @default 0
15031		 */
15032		this.backgroundBlurriness = 0;
15033
15034		/**
15035		 * Attenuates the color of the background. Only applies to background textures.
15036		 *
15037		 * @type {number}
15038		 * @default 1
15039		 */
15040		this.backgroundIntensity = 1;
15041
15042		/**
15043		 * The rotation of the background in radians. Only influences environment maps
15044		 * assigned to {@link Scene#background}.
15045		 *
15046		 * @type {Euler}
15047		 * @default (0,0,0)
15048		 */
15049		this.backgroundRotation = new Euler();
15050
15051		/**
15052		 * Attenuates the color of the environment. Only influences environment maps
15053		 * assigned to {@link Scene#environment}.
15054		 *
15055		 * @type {number}
15056		 * @default 1
15057		 */
15058		this.environmentIntensity = 1;
15059
15060		/**
15061		 * The rotation of the environment map in radians. Only influences physical materials
15062		 * in the scene when {@link Scene#environment} is used.
15063		 *
15064		 * @type {Euler}
15065		 * @default (0,0,0)
15066		 */
15067		this.environmentRotation = new Euler();
15068
15069		/**
15070		 * Forces everything in the scene to be rendered with the defined material. It is possible
15071		 * to exclude materials from override by setting {@link Material#allowOverride} to `false`.
15072		 *
15073		 * @type {?Material}
15074		 * @default null
15075		 */
15076		this.overrideMaterial = null;
15077
15078		if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {
15079
15080			__THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) );
15081
15082		}
15083
15084	}
15085
15086	copy( source, recursive ) {
15087
15088		super.copy( source, recursive );
15089
15090		if ( source.background !== null ) this.background = source.background.clone();
15091		if ( source.environment !== null ) this.environment = source.environment.clone();
15092		if ( source.fog !== null ) this.fog = source.fog.clone();
15093
15094		this.backgroundBlurriness = source.backgroundBlurriness;
15095		this.backgroundIntensity = source.backgroundIntensity;
15096		this.backgroundRotation.copy( source.backgroundRotation );
15097
15098		this.environmentIntensity = source.environmentIntensity;
15099		this.environmentRotation.copy( source.environmentRotation );
15100
15101		if ( source.overrideMaterial !== null ) this.overrideMaterial = source.overrideMaterial.clone();
15102
15103		this.matrixAutoUpdate = source.matrixAutoUpdate;
15104
15105		return this;
15106
15107	}
15108
15109	toJSON( meta ) {
15110
15111		const data = super.toJSON( meta );
15112
15113		if ( this.fog !== null ) data.object.fog = this.fog.toJSON();
15114
15115		
vendor: 6,676 bytes, lines 15115-15339
15115if ( this.backgroundBlurriness > 0 ) data.object.backgroundBlurriness = this.backgroundBlurriness;
15116		if ( this.backgroundIntensity !== 1 ) data.object.backgroundIntensity = this.backgroundIntensity;
15117		data.object.backgroundRotation = this.backgroundRotation.toArray();
15118
15119		if ( this.environmentIntensity !== 1 ) data.object.environmentIntensity = this.environmentIntensity;
15120		data.object.environmentRotation = this.environmentRotation.toArray();
15121
15122		return data;
15123
15124	}
15125
15126}
15127
15128const _v0$2 = /*@__PURE__*/ new Vector3();
15129const _v1$5 = /*@__PURE__*/ new Vector3();
15130const _v2$4 = /*@__PURE__*/ new Vector3();
15131const _v3$2 = /*@__PURE__*/ new Vector3();
15132
15133const _vab = /*@__PURE__*/ new Vector3();
15134const _vac = /*@__PURE__*/ new Vector3();
15135const _vbc = /*@__PURE__*/ new Vector3();
15136const _vap = /*@__PURE__*/ new Vector3();
15137const _vbp = /*@__PURE__*/ new Vector3();
15138const _vcp = /*@__PURE__*/ new Vector3();
15139
15140const _v40 = /*@__PURE__*/ new Vector4();
15141const _v41 = /*@__PURE__*/ new Vector4();
15142const _v42 = /*@__PURE__*/ new Vector4();
15143
15144/**
15145 * A geometric triangle as defined by three vectors representing its three corners.
15146 */
15147class Triangle {
15148
15149	/**
15150	 * Constructs a new triangle.
15151	 *
15152	 * @param {Vector3} [a=(0,0,0)] - The first corner of the triangle.
15153	 * @param {Vector3} [b=(0,0,0)] - The second corner of the triangle.
15154	 * @param {Vector3} [c=(0,0,0)] - The third corner of the triangle.
15155	 */
15156	constructor( a = new Vector3(), b = new Vector3(), c = new Vector3() ) {
15157
15158		/**
15159		 * The first corner of the triangle.
15160		 *
15161		 * @type {Vector3}
15162		 */
15163		this.a = a;
15164
15165		/**
15166		 * The second corner of the triangle.
15167		 *
15168		 * @type {Vector3}
15169		 */
15170		this.b = b;
15171
15172		/**
15173		 * The third corner of the triangle.
15174		 *
15175		 * @type {Vector3}
15176		 */
15177		this.c = c;
15178
15179	}
15180
15181	/**
15182	 * Computes the normal vector of a triangle.
15183	 *
15184	 * @param {Vector3} a - The first corner of the triangle.
15185	 * @param {Vector3} b - The second corner of the triangle.
15186	 * @param {Vector3} c - The third corner of the triangle.
15187	 * @param {Vector3} target - The target vector that is used to store the method's result.
15188	 * @return {Vector3} The triangle's normal.
15189	 */
15190	static getNormal( a, b, c, target ) {
15191
15192		target.subVectors( c, b );
15193		_v0$2.subVectors( a, b );
15194		target.cross( _v0$2 );
15195
15196		const targetLengthSq = target.lengthSq();
15197		if ( targetLengthSq > 0 ) {
15198
15199			return target.multiplyScalar( 1 / Math.sqrt( targetLengthSq ) );
15200
15201		}
15202
15203		return target.set( 0, 0, 0 );
15204
15205	}
15206
15207	/**
15208	 * Computes a barycentric coordinates from the given vector.
15209	 * Returns `null` if the triangle is degenerate.
15210	 *
15211	 * @param {Vector3} point - A point in 3D space.
15212	 * @param {Vector3} a - The first corner of the triangle.
15213	 * @param {Vector3} b - The second corner of the triangle.
15214	 * @param {Vector3} c - The third corner of the triangle.
15215	 * @param {Vector3} target - The target vector that is used to store the method's result.
15216	 * @return {?Vector3} The barycentric coordinates for the given point
15217	 */
15218	static getBarycoord( point, a, b, c, target ) {
15219
15220		// based on: http://www.blackpawn.com/texts/pointinpoly/default.html
15221
15222		_v0$2.subVectors( c, a );
15223		_v1$5.subVectors( b, a );
15224		_v2$4.subVectors( point, a );
15225
15226		const dot00 = _v0$2.dot( _v0$2 );
15227		const dot01 = _v0$2.dot( _v1$5 );
15228		const dot02 = _v0$2.dot( _v2$4 );
15229		const dot11 = _v1$5.dot( _v1$5 );
15230		const dot12 = _v1$5.dot( _v2$4 );
15231
15232		const denom = ( dot00 * dot11 - dot01 * dot01 );
15233
15234		// collinear or singular triangle
15235		if ( denom === 0 ) {
15236
15237			target.set( 0, 0, 0 );
15238			return null;
15239
15240		}
15241
15242		const invDenom = 1 / denom;
15243		const u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;
15244		const v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;
15245
15246		// barycentric coordinates must always sum to 1
15247		return target.set( 1 - u - v, v, u );
15248
15249	}
15250
15251	/**
15252	 * Returns `true` if the given point, when projected onto the plane of the
15253	 * triangle, lies within the triangle.
15254	 *
15255	 * @param {Vector3} point - The point in 3D space to test.
15256	 * @param {Vector3} a - The first corner of the triangle.
15257	 * @param {Vector3} b - The second corner of the triangle.
15258	 * @param {Vector3} c - The third corner of the triangle.
15259	 * @return {boolean} Whether the given point, when projected onto the plane of the
15260	 * triangle, lies within the triangle or not.
15261	 */
15262	static containsPoint( point, a, b, c ) {
15263
15264		// if the triangle is degenerate then we can't contain a point
15265		if ( this.getBarycoord( point, a, b, c, _v3$2 ) === null ) {
15266
15267			return false;
15268
15269		}
15270
15271		return ( _v3$2.x >= 0 ) && ( _v3$2.y >= 0 ) && ( ( _v3$2.x + _v3$2.y ) <= 1 );
15272
15273	}
15274
15275	/**
15276	 * Computes the value barycentrically interpolated for the given point on the
15277	 * triangle. Returns `null` if the triangle is degenerate.
15278	 *
15279	 * @param {Vector3} point - Position of interpolated point.
15280	 * @param {Vector3} p1 - The first corner of the triangle.
15281	 * @param {Vector3} p2 - The second corner of the triangle.
15282	 * @param {Vector3} p3 - The third corner of the triangle.
15283	 * @param {Vector3} v1 - Value to interpolate of first vertex.
15284	 * @param {Vector3} v2 - Value to interpolate of second vertex.
15285	 * @param {Vector3} v3 - Value to interpolate of third vertex.
15286	 * @param {Vector3} target - The target vector that is used to store the method's result.
15287	 * @return {?Vector3} The interpolated value.
15288	 */
15289	static getInterpolation( point, p1, p2, p3, v1, v2, v3, target ) {
15290
15291		if ( this.getBarycoord( point, p1, p2, p3, _v3$2 ) === null ) {
15292
15293			target.x = 0;
15294			target.y = 0;
15295			if ( 'z' in target ) target.z = 0;
15296			if ( 'w' in target ) target.w = 0;
15297			return null;
15298
15299		}
15300
15301		target.setScalar( 0 );
15302		target.addScaledVector( v1, _v3$2.x );
15303		target.addScaledVector( v2, _v3$2.y );
15304		target.addScaledVector( v3, _v3$2.z );
15305
15306		return target;
15307
15308	}
15309
15310	/**
15311	 * Computes the value barycentrically interpolated for the given attribute and indices.
15312	 *
15313	 * @param {BufferAttribute} attr - The attribute to interpolate.
15314	 * @param {number} i1 - Index of first vertex.
15315	 * @param {number} i2 - Index of second vertex.
15316	 * @param {number} i3 - Index of third vertex.
15317	 * @param {Vector3} barycoord - The barycoordinate value to use to interpolate.
15318	 * @param {Vector3} target - The target vector that is used to store the method's result.
15319	 * @return {Vector3} The interpolated attribute value.
15320	 */
15321	static getInterpolatedAttribute( attr, i1, i2, i3, barycoord, target ) {
15322
15323		_v40.setScalar( 0 );
15324		_v41.setScalar( 0 );
15325		_v42.setScalar( 0 );
15326
15327		_v40.fromBufferAttribute( attr, i1 );
15328		_v41.fromBufferAttribute( attr, i2 );
15329		_v42.fromBufferAttribute( attr, i3 );
15330
15331		target.setScalar( 0 );
15332		target.addScaledVector( _v40, barycoord.x );
15333		target.addScaledVector( _v41, barycoord.y );
15334		target.addScaledVector( _v42, barycoord.z );
15335
15336		return target;
15337
15338	}
15339
vendor: 8,587 bytes, lines 15340-15648
15340	/**
15341	 * Returns `true` if the triangle is oriented towards the given direction.
15342	 *
15343	 * @param {Vector3} a - The first corner of the triangle.
15344	 * @param {Vector3} b - The second corner of the triangle.
15345	 * @param {Vector3} c - The third corner of the triangle.
15346	 * @param {Vector3} direction - The (normalized) direction vector.
15347	 * @return {boolean} Whether the triangle is oriented towards the given direction or not.
15348	 */
15349	static isFrontFacing( a, b, c, direction ) {
15350
15351		_v0$2.subVectors( c, b );
15352		_v1$5.subVectors( a, b );
15353
15354		// strictly front facing
15355		return _v0$2.cross( _v1$5 ).dot( direction ) < 0;
15356
15357	}
15358
15359	/**
15360	 * Sets the triangle's vertices by copying the given values.
15361	 *
15362	 * @param {Vector3} a - The first corner of the triangle.
15363	 * @param {Vector3} b - The second corner of the triangle.
15364	 * @param {Vector3} c - The third corner of the triangle.
15365	 * @return {Triangle} A reference to this triangle.
15366	 */
15367	set( a, b, c ) {
15368
15369		this.a.copy( a );
15370		this.b.copy( b );
15371		this.c.copy( c );
15372
15373		return this;
15374
15375	}
15376
15377	/**
15378	 * Sets the triangle's vertices by copying the given array values.
15379	 *
15380	 * @param {Array<Vector3>} points - An array with 3D points.
15381	 * @param {number} i0 - The array index representing the first corner of the triangle.
15382	 * @param {number} i1 - The array index representing the second corner of the triangle.
15383	 * @param {number} i2 - The array index representing the third corner of the triangle.
15384	 * @return {Triangle} A reference to this triangle.
15385	 */
15386	setFromPointsAndIndices( points, i0, i1, i2 ) {
15387
15388		this.a.copy( points[ i0 ] );
15389		this.b.copy( points[ i1 ] );
15390		this.c.copy( points[ i2 ] );
15391
15392		return this;
15393
15394	}
15395
15396	/**
15397	 * Sets the triangle's vertices by copying the given attribute values.
15398	 *
15399	 * @param {BufferAttribute} attribute - A buffer attribute with 3D points data.
15400	 * @param {number} i0 - The attribute index representing the first corner of the triangle.
15401	 * @param {number} i1 - The attribute index representing the second corner of the triangle.
15402	 * @param {number} i2 - The attribute index representing the third corner of the triangle.
15403	 * @return {Triangle} A reference to this triangle.
15404	 */
15405	setFromAttributeAndIndices( attribute, i0, i1, i2 ) {
15406
15407		this.a.fromBufferAttribute( attribute, i0 );
15408		this.b.fromBufferAttribute( attribute, i1 );
15409		this.c.fromBufferAttribute( attribute, i2 );
15410
15411		return this;
15412
15413	}
15414
15415	/**
15416	 * Returns a new triangle with copied values from this instance.
15417	 *
15418	 * @return {Triangle} A clone of this instance.
15419	 */
15420	clone() {
15421
15422		return new this.constructor().copy( this );
15423
15424	}
15425
15426	/**
15427	 * Copies the values of the given triangle to this instance.
15428	 *
15429	 * @param {Triangle} triangle - The triangle to copy.
15430	 * @return {Triangle} A reference to this triangle.
15431	 */
15432	copy( triangle ) {
15433
15434		this.a.copy( triangle.a );
15435		this.b.copy( triangle.b );
15436		this.c.copy( triangle.c );
15437
15438		return this;
15439
15440	}
15441
15442	/**
15443	 * Computes the area of the triangle.
15444	 *
15445	 * @return {number} The triangle's area.
15446	 */
15447	getArea() {
15448
15449		_v0$2.subVectors( this.c, this.b );
15450		_v1$5.subVectors( this.a, this.b );
15451
15452		return _v0$2.cross( _v1$5 ).length() * 0.5;
15453
15454	}
15455
15456	/**
15457	 * Computes the midpoint of the triangle.
15458	 *
15459	 * @param {Vector3} target - The target vector that is used to store the method's result.
15460	 * @return {Vector3} The triangle's midpoint.
15461	 */
15462	getMidpoint( target ) {
15463
15464		return target.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 );
15465
15466	}
15467
15468	/**
15469	 * Computes the normal of the triangle.
15470	 *
15471	 * @param {Vector3} target - The target vector that is used to store the method's result.
15472	 * @return {Vector3} The triangle's normal.
15473	 */
15474	getNormal( target ) {
15475
15476		return Triangle.getNormal( this.a, this.b, this.c, target );
15477
15478	}
15479
15480	/**
15481	 * Computes a plane the triangle lies within.
15482	 *
15483	 * @param {Plane} target - The target vector that is used to store the method's result.
15484	 * @return {Plane} The plane the triangle lies within.
15485	 */
15486	getPlane( target ) {
15487
15488		return target.setFromCoplanarPoints( this.a, this.b, this.c );
15489
15490	}
15491
15492	/**
15493	 * Computes a barycentric coordinates from the given vector.
15494	 * Returns `null` if the triangle is degenerate.
15495	 *
15496	 * @param {Vector3} point - A point in 3D space.
15497	 * @param {Vector3} target - The target vector that is used to store the method's result.
15498	 * @return {?Vector3} The barycentric coordinates for the given point
15499	 */
15500	getBarycoord( point, target ) {
15501
15502		return Triangle.getBarycoord( point, this.a, this.b, this.c, target );
15503
15504	}
15505
15506	/**
15507	 * Computes the value barycentrically interpolated for the given point on the
15508	 * triangle. Returns `null` if the triangle is degenerate.
15509	 *
15510	 * @param {Vector3} point - Position of interpolated point.
15511	 * @param {Vector3} v1 - Value to interpolate of first vertex.
15512	 * @param {Vector3} v2 - Value to interpolate of second vertex.
15513	 * @param {Vector3} v3 - Value to interpolate of third vertex.
15514	 * @param {Vector3} target - The target vector that is used to store the method's result.
15515	 * @return {?Vector3} The interpolated value.
15516	 */
15517	getInterpolation( point, v1, v2, v3, target ) {
15518
15519		return Triangle.getInterpolation( point, this.a, this.b, this.c, v1, v2, v3, target );
15520
15521	}
15522
15523	/**
15524	 * Returns `true` if the given point, when projected onto the plane of the
15525	 * triangle, lies within the triangle.
15526	 *
15527	 * @param {Vector3} point - The point in 3D space to test.
15528	 * @return {boolean} Whether the given point, when projected onto the plane of the
15529	 * triangle, lies within the triangle or not.
15530	 */
15531	containsPoint( point ) {
15532
15533		return Triangle.containsPoint( point, this.a, this.b, this.c );
15534
15535	}
15536
15537	/**
15538	 * Returns `true` if the triangle is oriented towards the given direction.
15539	 *
15540	 * @param {Vector3} direction - The (normalized) direction vector.
15541	 * @return {boolean} Whether the triangle is oriented towards the given direction or not.
15542	 */
15543	isFrontFacing( direction ) {
15544
15545		return Triangle.isFrontFacing( this.a, this.b, this.c, direction );
15546
15547	}
15548
15549	/**
15550	 * Returns `true` if this triangle intersects with the given box.
15551	 *
15552	 * @param {Box3} box - The box to intersect.
15553	 * @return {boolean} Whether this triangle intersects with the given box or not.
15554	 */
15555	intersectsBox( box ) {
15556
15557		return box.intersectsTriangle( this );
15558
15559	}
15560
15561	/**
15562	 * Returns the closest point on the triangle to the given point.
15563	 *
15564	 * @param {Vector3} p - The point to compute the closest point for.
15565	 * @param {Vector3} target - The target vector that is used to store the method's result.
15566	 * @return {Vector3} The closest point on the triangle.
15567	 */
15568	closestPointToPoint( p, target ) {
15569
15570		const a = this.a, b = this.b, c = this.c;
15571		let v, w;
15572
15573		// algorithm thanks to Real-Time Collision Detection by Christer Ericson,
15574		// published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc.,
15575		// under the accompanying license; see chapter 5.1.5 for detailed explanation.
15576		// basically, we're distinguishing which of the voronoi regions of the triangle
15577		// the point lies in with the minimum amount of redundant computation.
15578
15579		_vab.subVectors( b, a );
15580		_vac.subVectors( c, a );
15581		_vap.subVectors( p, a );
15582		const d1 = _vab.dot( _vap );
15583		const d2 = _vac.dot( _vap );
15584		if ( d1 <= 0 && d2 <= 0 ) {
15585
15586			// vertex region of A; barycentric coords (1, 0, 0)
15587			return target.copy( a );
15588
15589		}
15590
15591		_vbp.subVectors( p, b );
15592		const d3 = _vab.dot( _vbp );
15593		const d4 = _vac.dot( _vbp );
15594		if ( d3 >= 0 && d4 <= d3 ) {
15595
15596			// vertex region of B; barycentric coords (0, 1, 0)
15597			return target.copy( b );
15598
15599		}
15600
15601		const vc = d1 * d4 - d3 * d2;
15602		if ( vc <= 0 && d1 >= 0 && d3 <= 0 ) {
15603
15604			v = d1 / ( d1 - d3 );
15605			// edge region of AB; barycentric coords (1-v, v, 0)
15606			return target.copy( a ).addScaledVector( _vab, v );
15607
15608		}
15609
15610		_vcp.subVectors( p, c );
15611		const d5 = _vab.dot( _vcp );
15612		const d6 = _vac.dot( _vcp );
15613		if ( d6 >= 0 && d5 <= d6 ) {
15614
15615			// vertex region of C; barycentric coords (0, 0, 1)
15616			return target.copy( c );
15617
15618		}
15619
15620		const vb = d5 * d2 - d1 * d6;
15621		if ( vb <= 0 && d2 >= 0 && d6 <= 0 ) {
15622
15623			w = d2 / ( d2 - d6 );
15624			// edge region of AC; barycentric coords (1-w, 0, w)
15625			return target.copy( a ).addScaledVector( _vac, w );
15626
15627		}
15628
15629		const va = d3 * d6 - d5 * d4;
15630		if ( va <= 0 && ( d4 - d3 ) >= 0 && ( d5 - d6 ) >= 0 ) {
15631
15632			_vbc.subVectors( c, b );
15633			w = ( d4 - d3 ) / ( ( d4 - d3 ) + ( d5 - d6 ) );
15634			// edge region of BC; barycentric coords (0, 1-w, w)
15635			return target.copy( b ).addScaledVector( _vbc, w ); // edge region of BC
15636
15637		}
15638
15639		// face region
15640		const denom = 1 / ( va + vb + vc );
15641		// u = va * denom
15642		v = vb * denom;
15643		w = vc * denom;
15644
15645		return target.copy( a ).addScaledVector( _vab, v ).addScaledVector( _vac, w );
15646
15647	}
15648
vendor: 8,739 bytes, lines 15649-15987
15649	/**
15650	 * Returns `true` if this triangle is equal with the given one.
15651	 *
15652	 * @param {Triangle} triangle - The triangle to test for equality.
15653	 * @return {boolean} Whether this triangle is equal with the given one.
15654	 */
15655	equals( triangle ) {
15656
15657		return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c );
15658
15659	}
15660
15661}
15662
15663/**
15664 * Represents an axis-aligned bounding box (AABB) in 3D space.
15665 */
15666class Box3 {
15667
15668	/**
15669	 * Constructs a new bounding box.
15670	 *
15671	 * @param {Vector3} [min=(Infinity,Infinity,Infinity)] - A vector representing the lower boundary of the box.
15672	 * @param {Vector3} [max=(-Infinity,-Infinity,-Infinity)] - A vector representing the upper boundary of the box.
15673	 */
15674	constructor( min = new Vector3( + Infinity, + Infinity, + Infinity ), max = new Vector3( - Infinity, - Infinity, - Infinity ) ) {
15675
15676		/**
15677		 * This flag can be used for type testing.
15678		 *
15679		 * @type {boolean}
15680		 * @readonly
15681		 * @default true
15682		 */
15683		this.isBox3 = true;
15684
15685		/**
15686		 * The lower boundary of the box.
15687		 *
15688		 * @type {Vector3}
15689		 */
15690		this.min = min;
15691
15692		/**
15693		 * The upper boundary of the box.
15694		 *
15695		 * @type {Vector3}
15696		 */
15697		this.max = max;
15698
15699	}
15700
15701	/**
15702	 * Sets the lower and upper boundaries of this box.
15703	 * Please note that this method only copies the values from the given objects.
15704	 *
15705	 * @param {Vector3} min - The lower boundary of the box.
15706	 * @param {Vector3} max - The upper boundary of the box.
15707	 * @return {Box3} A reference to this bounding box.
15708	 */
15709	set( min, max ) {
15710
15711		this.min.copy( min );
15712		this.max.copy( max );
15713
15714		return this;
15715
15716	}
15717
15718	/**
15719	 * Sets the upper and lower bounds of this box so it encloses the position data
15720	 * in the given array.
15721	 *
15722	 * @param {Array<number>} array - An array holding 3D position data.
15723	 * @return {Box3} A reference to this bounding box.
15724	 */
15725	setFromArray( array ) {
15726
15727		this.makeEmpty();
15728
15729		for ( let i = 0, il = array.length; i < il; i += 3 ) {
15730
15731			this.expandByPoint( _vector$b.fromArray( array, i ) );
15732
15733		}
15734
15735		return this;
15736
15737	}
15738
15739	/**
15740	 * Sets the upper and lower bounds of this box so it encloses the position data
15741	 * in the given buffer attribute.
15742	 *
15743	 * @param {BufferAttribute} attribute - A buffer attribute holding 3D position data.
15744	 * @return {Box3} A reference to this bounding box.
15745	 */
15746	setFromBufferAttribute( attribute ) {
15747
15748		this.makeEmpty();
15749
15750		for ( let i = 0, il = attribute.count; i < il; i ++ ) {
15751
15752			this.expandByPoint( _vector$b.fromBufferAttribute( attribute, i ) );
15753
15754		}
15755
15756		return this;
15757
15758	}
15759
15760	/**
15761	 * Sets the upper and lower bounds of this box so it encloses the position data
15762	 * in the given array.
15763	 *
15764	 * @param {Array<Vector3>} points - An array holding 3D position data as instances of {@link Vector3}.
15765	 * @return {Box3} A reference to this bounding box.
15766	 */
15767	setFromPoints( points ) {
15768
15769		this.makeEmpty();
15770
15771		for ( let i = 0, il = points.length; i < il; i ++ ) {
15772
15773			this.expandByPoint( points[ i ] );
15774
15775		}
15776
15777		return this;
15778
15779	}
15780
15781	/**
15782	 * Centers this box on the given center vector and sets this box's width, height and
15783	 * depth to the given size values.
15784	 *
15785	 * @param {Vector3} center - The center of the box.
15786	 * @param {Vector3} size - The x, y and z dimensions of the box.
15787	 * @return {Box3} A reference to this bounding box.
15788	 */
15789	setFromCenterAndSize( center, size ) {
15790
15791		const halfSize = _vector$b.copy( size ).multiplyScalar( 0.5 );
15792
15793		this.min.copy( center ).sub( halfSize );
15794		this.max.copy( center ).add( halfSize );
15795
15796		return this;
15797
15798	}
15799
15800	/**
15801	 * Computes the world-axis-aligned bounding box for the given 3D object
15802	 * (including its children), accounting for the object's, and children's,
15803	 * world transforms. The function may result in a larger box than strictly necessary.
15804	 *
15805	 * @param {Object3D} object - The 3D object to compute the bounding box for.
15806	 * @param {boolean} [precise=false] - If set to `true`, the method computes the smallest
15807	 * world-axis-aligned bounding box at the expense of more computation.
15808	 * @return {Box3} A reference to this bounding box.
15809	 */
15810	setFromObject( object, precise = false ) {
15811
15812		this.makeEmpty();
15813
15814		return this.expandByObject( object, precise );
15815
15816	}
15817
15818	/**
15819	 * Returns a new box with copied values from this instance.
15820	 *
15821	 * @return {Box3} A clone of this instance.
15822	 */
15823	clone() {
15824
15825		return new this.constructor().copy( this );
15826
15827	}
15828
15829	/**
15830	 * Copies the values of the given box to this instance.
15831	 *
15832	 * @param {Box3} box - The box to copy.
15833	 * @return {Box3} A reference to this bounding box.
15834	 */
15835	copy( box ) {
15836
15837		this.min.copy( box.min );
15838		this.max.copy( box.max );
15839
15840		return this;
15841
15842	}
15843
15844	/**
15845	 * Makes this box empty which means in encloses a zero space in 3D.
15846	 *
15847	 * @return {Box3} A reference to this bounding box.
15848	 */
15849	makeEmpty() {
15850
15851		this.min.x = this.min.y = this.min.z = + Infinity;
15852		this.max.x = this.max.y = this.max.z = - Infinity;
15853
15854		return this;
15855
15856	}
15857
15858	/**
15859	 * Returns true if this box includes zero points within its bounds.
15860	 * Note that a box with equal lower and upper bounds still includes one
15861	 * point, the one both bounds share.
15862	 *
15863	 * @return {boolean} Whether this box is empty or not.
15864	 */
15865	isEmpty() {
15866
15867		// this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
15868
15869		return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ) || ( this.max.z < this.min.z );
15870
15871	}
15872
15873	/**
15874	 * Returns the center point of this box.
15875	 *
15876	 * @param {Vector3} target - The target vector that is used to store the method's result.
15877	 * @return {Vector3} The center point.
15878	 */
15879	getCenter( target ) {
15880
15881		return this.isEmpty() ? target.set( 0, 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 );
15882
15883	}
15884
15885	/**
15886	 * Returns the dimensions of this box.
15887	 *
15888	 * @param {Vector3} target - The target vector that is used to store the method's result.
15889	 * @return {Vector3} The size.
15890	 */
15891	getSize( target ) {
15892
15893		return this.isEmpty() ? target.set( 0, 0, 0 ) : target.subVectors( this.max, this.min );
15894
15895	}
15896
15897	/**
15898	 * Expands the boundaries of this box to include the given point.
15899	 *
15900	 * @param {Vector3} point - The point that should be included by the bounding box.
15901	 * @return {Box3} A reference to this bounding box.
15902	 */
15903	expandByPoint( point ) {
15904
15905		this.min.min( point );
15906		this.max.max( point );
15907
15908		return this;
15909
15910	}
15911
15912	/**
15913	 * Expands this box equilaterally by the given vector. The width of this
15914	 * box will be expanded by the x component of the vector in both
15915	 * directions. The height of this box will be expanded by the y component of
15916	 * the vector in both directions. The depth of this box will be
15917	 * expanded by the z component of the vector in both directions.
15918	 *
15919	 * @param {Vector3} vector - The vector that should expand the bounding box.
15920	 * @return {Box3} A reference to this bounding box.
15921	 */
15922	expandByVector( vector ) {
15923
15924		this.min.sub( vector );
15925		this.max.add( vector );
15926
15927		return this;
15928
15929	}
15930
15931	/**
15932	 * Expands each dimension of the box by the given scalar. If negative, the
15933	 * dimensions of the box will be contracted.
15934	 *
15935	 * @param {number} scalar - The scalar value that should expand the bounding box.
15936	 * @return {Box3} A reference to this bounding box.
15937	 */
15938	expandByScalar( scalar ) {
15939
15940		this.min.addScalar( - scalar );
15941		this.max.addScalar( scalar );
15942
15943		return this;
15944
15945	}
15946
15947	/**
15948	 * Expands the boundaries of this box to include the given 3D object and
15949	 * its children, accounting for the object's, and children's, world
15950	 * transforms. The function may result in a larger box than strictly
15951	 * necessary (unless the precise parameter is set to true).
15952	 *
15953	 * @param {Object3D} object - The 3D object that should expand the bounding box.
15954	 * @param {boolean} precise - If set to `true`, the method expands the bounding box
15955	 * as little as necessary at the expense of more computation.
15956	 * @return {Box3} A reference to this bounding box.
15957	 */
15958	expandByObject( object, precise = false ) {
15959
15960		// Computes the world-axis-aligned bounding box of an object (including its children),
15961		// accounting for both the object's, and children's, world transforms
15962
15963		object.updateWorldMatrix( false, false );
15964
15965		const geometry = object.geometry;
15966
15967		if ( geometry !== undefined ) {
15968
15969			const positionAttribute = geometry.getAttribute( 'position' );
15970
15971			// precise AABB computation based on vertex data requires at least a position attribute.
15972			// instancing isn't supported so far and uses the normal (conservative) code path.
15973
15974			if ( precise === true && positionAttribute !== undefined && object.isInstancedMesh !== true ) {
15975
15976				for ( let i = 0, l = positionAttribute.count; i < l; i ++ ) {
15977
15978					if ( object.isMesh === true ) {
15979
15980						object.getVertexPosition( i, _vector$b );
15981
15982					} else {
15983
15984						_vector$b.fromBufferAttribute( positionAttribute, i );
15985
15986					}
15987
vendor: 33,436 bytes, lines 15988-17339
15988					_vector$b.applyMatrix4( object.matrixWorld );
15989					this.expandByPoint( _vector$b );
15990
15991				}
15992
15993			} else {
15994
15995				if ( object.boundingBox !== undefined ) {
15996
15997					// object-level bounding box
15998
15999					if ( object.boundingBox === null ) {
16000
16001						object.computeBoundingBox();
16002
16003					}
16004
16005					_box$4.copy( object.boundingBox );
16006
16007
16008				} else {
16009
16010					// geometry-level bounding box
16011
16012					if ( geometry.boundingBox === null ) {
16013
16014						geometry.computeBoundingBox();
16015
16016					}
16017
16018					_box$4.copy( geometry.boundingBox );
16019
16020				}
16021
16022				_box$4.applyMatrix4( object.matrixWorld );
16023
16024				this.union( _box$4 );
16025
16026			}
16027
16028		}
16029
16030		const children = object.children;
16031
16032		for ( let i = 0, l = children.length; i < l; i ++ ) {
16033
16034			this.expandByObject( children[ i ], precise );
16035
16036		}
16037
16038		return this;
16039
16040	}
16041
16042	/**
16043	 * Returns `true` if the given point lies within or on the boundaries of this box.
16044	 *
16045	 * @param {Vector3} point - The point to test.
16046	 * @return {boolean} Whether the bounding box contains the given point or not.
16047	 */
16048	containsPoint( point ) {
16049
16050		return point.x >= this.min.x && point.x <= this.max.x &&
16051			point.y >= this.min.y && point.y <= this.max.y &&
16052			point.z >= this.min.z && point.z <= this.max.z;
16053
16054	}
16055
16056	/**
16057	 * Returns `true` if this bounding box includes the entirety of the given bounding box.
16058	 * If this box and the given one are identical, this function also returns `true`.
16059	 *
16060	 * @param {Box3} box - The bounding box to test.
16061	 * @return {boolean} Whether the bounding box contains the given bounding box or not.
16062	 */
16063	containsBox( box ) {
16064
16065		return this.min.x <= box.min.x && box.max.x <= this.max.x &&
16066			this.min.y <= box.min.y && box.max.y <= this.max.y &&
16067			this.min.z <= box.min.z && box.max.z <= this.max.z;
16068
16069	}
16070
16071	/**
16072	 * Returns a point as a proportion of this box's width, height and depth.
16073	 *
16074	 * @param {Vector3} point - A point in 3D space.
16075	 * @param {Vector3} target - The target vector that is used to store the method's result.
16076	 * @return {Vector3} A point as a proportion of this box's width, height and depth.
16077	 */
16078	getParameter( point, target ) {
16079
16080		// This can potentially have a divide by zero if the box
16081		// has a size dimension of 0.
16082
16083		return target.set(
16084			( point.x - this.min.x ) / ( this.max.x - this.min.x ),
16085			( point.y - this.min.y ) / ( this.max.y - this.min.y ),
16086			( point.z - this.min.z ) / ( this.max.z - this.min.z )
16087		);
16088
16089	}
16090
16091	/**
16092	 * Returns `true` if the given bounding box intersects with this bounding box.
16093	 *
16094	 * @param {Box3} box - The bounding box to test.
16095	 * @return {boolean} Whether the given bounding box intersects with this bounding box.
16096	 */
16097	intersectsBox( box ) {
16098
16099		// using 6 splitting planes to rule out intersections.
16100		return box.max.x >= this.min.x && box.min.x <= this.max.x &&
16101			box.max.y >= this.min.y && box.min.y <= this.max.y &&
16102			box.max.z >= this.min.z && box.min.z <= this.max.z;
16103
16104	}
16105
16106	/**
16107	 * Returns `true` if the given bounding sphere intersects with this bounding box.
16108	 *
16109	 * @param {Sphere} sphere - The bounding sphere to test.
16110	 * @return {boolean} Whether the given bounding sphere intersects with this bounding box.
16111	 */
16112	intersectsSphere( sphere ) {
16113
16114		// Find the point on the AABB closest to the sphere center.
16115		this.clampPoint( sphere.center, _vector$b );
16116
16117		// If that point is inside the sphere, the AABB and sphere intersect.
16118		return _vector$b.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius );
16119
16120	}
16121
16122	/**
16123	 * Returns `true` if the given plane intersects with this bounding box.
16124	 *
16125	 * @param {Plane} plane - The plane to test.
16126	 * @return {boolean} Whether the given plane intersects with this bounding box.
16127	 */
16128	intersectsPlane( plane ) {
16129
16130		// We compute the minimum and maximum dot product values. If those values
16131		// are on the same side (back or front) of the plane, then there is no intersection.
16132
16133		let min, max;
16134
16135		if ( plane.normal.x > 0 ) {
16136
16137			min = plane.normal.x * this.min.x;
16138			max = plane.normal.x * this.max.x;
16139
16140		} else {
16141
16142			min = plane.normal.x * this.max.x;
16143			max = plane.normal.x * this.min.x;
16144
16145		}
16146
16147		if ( plane.normal.y > 0 ) {
16148
16149			min += plane.normal.y * this.min.y;
16150			max += plane.normal.y * this.max.y;
16151
16152		} else {
16153
16154			min += plane.normal.y * this.max.y;
16155			max += plane.normal.y * this.min.y;
16156
16157		}
16158
16159		if ( plane.normal.z > 0 ) {
16160
16161			min += plane.normal.z * this.min.z;
16162			max += plane.normal.z * this.max.z;
16163
16164		} else {
16165
16166			min += plane.normal.z * this.max.z;
16167			max += plane.normal.z * this.min.z;
16168
16169		}
16170
16171		return ( min <= - plane.constant && max >= - plane.constant );
16172
16173	}
16174
16175	/**
16176	 * Returns `true` if the given triangle intersects with this bounding box.
16177	 *
16178	 * @param {Triangle} triangle - The triangle to test.
16179	 * @return {boolean} Whether the given triangle intersects with this bounding box.
16180	 */
16181	intersectsTriangle( triangle ) {
16182
16183		if ( this.isEmpty() ) {
16184
16185			return false;
16186
16187		}
16188
16189		// compute box center and extents
16190		this.getCenter( _center );
16191		_extents.subVectors( this.max, _center );
16192
16193		// translate triangle to aabb origin
16194		_v0$1.subVectors( triangle.a, _center );
16195		_v1$4.subVectors( triangle.b, _center );
16196		_v2$3.subVectors( triangle.c, _center );
16197
16198		// compute edge vectors for triangle
16199		_f0.subVectors( _v1$4, _v0$1 );
16200		_f1.subVectors( _v2$3, _v1$4 );
16201		_f2.subVectors( _v0$1, _v2$3 );
16202
16203		// test against axes that are given by cross product combinations of the edges of the triangle and the edges of the aabb
16204		// 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
16205		// axis_ij = u_i x f_j (u0, u1, u2 = face normals of aabb = x,y,z axes vectors since aabb is axis aligned)
16206		let axes = [
16207			0, - _f0.z, _f0.y, 0, - _f1.z, _f1.y, 0, - _f2.z, _f2.y,
16208			_f0.z, 0, - _f0.x, _f1.z, 0, - _f1.x, _f2.z, 0, - _f2.x,
16209			- _f0.y, _f0.x, 0, - _f1.y, _f1.x, 0, - _f2.y, _f2.x, 0
16210		];
16211		if ( ! satForAxes( axes, _v0$1, _v1$4, _v2$3, _extents ) ) {
16212
16213			return false;
16214
16215		}
16216
16217		// test 3 face normals from the aabb
16218		axes = [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ];
16219		if ( ! satForAxes( axes, _v0$1, _v1$4, _v2$3, _extents ) ) {
16220
16221			return false;
16222
16223		}
16224
16225		// finally testing the face normal of the triangle
16226		// use already existing triangle edge vectors here
16227		_triangleNormal.crossVectors( _f0, _f1 );
16228		axes = [ _triangleNormal.x, _triangleNormal.y, _triangleNormal.z ];
16229
16230		return satForAxes( axes, _v0$1, _v1$4, _v2$3, _extents );
16231
16232	}
16233
16234	/**
16235	 * Clamps the given point within the bounds of this box.
16236	 *
16237	 * @param {Vector3} point - The point to clamp.
16238	 * @param {Vector3} target - The target vector that is used to store the method's result.
16239	 * @return {Vector3} The clamped point.
16240	 */
16241	clampPoint( point, target ) {
16242
16243		return target.copy( point ).clamp( this.min, this.max );
16244
16245	}
16246
16247	/**
16248	 * Returns the euclidean distance from any edge of this box to the specified point. If
16249	 * the given point lies inside of this box, the distance will be `0`.
16250	 *
16251	 * @param {Vector3} point - The point to compute the distance to.
16252	 * @return {number} The euclidean distance.
16253	 */
16254	distanceToPoint( point ) {
16255
16256		return this.clampPoint( point, _vector$b ).distanceTo( point );
16257
16258	}
16259
16260	/**
16261	 * Returns a bounding sphere that encloses this bounding box.
16262	 *
16263	 * @param {Sphere} target - The target sphere that is used to store the method's result.
16264	 * @return {Sphere} The bounding sphere that encloses this bounding box.
16265	 */
16266	getBoundingSphere( target ) {
16267
16268		if ( this.isEmpty() ) {
16269
16270			target.makeEmpty();
16271
16272		} else {
16273
16274			this.getCenter( target.center );
16275
16276			target.radius = this.getSize( _vector$b ).length() * 0.5;
16277
16278		}
16279
16280		return target;
16281
16282	}
16283
16284	/**
16285	 * Computes the intersection of this bounding box and the given one, setting the upper
16286	 * bound of this box to the lesser of the two boxes' upper bounds and the
16287	 * lower bound of this box to the greater of the two boxes' lower bounds. If
16288	 * there's no overlap, makes this box empty.
16289	 *
16290	 * @param {Box3} box - The bounding box to intersect with.
16291	 * @return {Box3} A reference to this bounding box.
16292	 */
16293	intersect( box ) {
16294
16295		this.min.max( box.min );
16296		this.max.min( box.max );
16297
16298		// 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.
16299		if ( this.isEmpty() ) this.makeEmpty();
16300
16301		return this;
16302
16303	}
16304
16305	/**
16306	 * Computes the union of this box and another and the given one, setting the upper
16307	 * bound of this box to the greater of the two boxes' upper bounds and the
16308	 * lower bound of this box to the lesser of the two boxes' lower bounds.
16309	 *
16310	 * @param {Box3} box - The bounding box that will be unioned with this instance.
16311	 * @return {Box3} A reference to this bounding box.
16312	 */
16313	union( box ) {
16314
16315		this.min.min( box.min );
16316		this.max.max( box.max );
16317
16318		return this;
16319
16320	}
16321
16322	/**
16323	 * Transforms this bounding box by the given 4x4 transformation matrix.
16324	 *
16325	 * @param {Matrix4} matrix - The transformation matrix.
16326	 * @return {Box3} A reference to this bounding box.
16327	 */
16328	applyMatrix4( matrix ) {
16329
16330		// transform of empty box is an empty box.
16331		if ( this.isEmpty() ) return this;
16332
16333		// NOTE: I am using a binary pattern to specify all 2^3 combinations below
16334		_points[ 0 ].set( this.min.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 000
16335		_points[ 1 ].set( this.min.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 001
16336		_points[ 2 ].set( this.min.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 010
16337		_points[ 3 ].set( this.min.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 011
16338		_points[ 4 ].set( this.max.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 100
16339		_points[ 5 ].set( this.max.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 101
16340		_points[ 6 ].set( this.max.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 110
16341		_points[ 7 ].set( this.max.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 111
16342
16343		this.setFromPoints( _points );
16344
16345		return this;
16346
16347	}
16348
16349	/**
16350	 * Adds the given offset to both the upper and lower bounds of this bounding box,
16351	 * effectively moving it in 3D space.
16352	 *
16353	 * @param {Vector3} offset - The offset that should be used to translate the bounding box.
16354	 * @return {Box3} A reference to this bounding box.
16355	 */
16356	translate( offset ) {
16357
16358		this.min.add( offset );
16359		this.max.add( offset );
16360
16361		return this;
16362
16363	}
16364
16365	/**
16366	 * Returns `true` if this bounding box is equal with the given one.
16367	 *
16368	 * @param {Box3} box - The box to test for equality.
16369	 * @return {boolean} Whether this bounding box is equal with the given one.
16370	 */
16371	equals( box ) {
16372
16373		return box.min.equals( this.min ) && box.max.equals( this.max );
16374
16375	}
16376
16377	/**
16378	 * Returns a serialized structure of the bounding box.
16379	 *
16380	 * @return {Object} Serialized structure with fields representing the object state.
16381	 */
16382	toJSON() {
16383
16384		return {
16385			min: this.min.toArray(),
16386			max: this.max.toArray()
16387		};
16388
16389	}
16390
16391	/**
16392	 * Returns a serialized structure of the bounding box.
16393	 *
16394	 * @param {Object} json - The serialized json to set the box from.
16395	 * @return {Box3} A reference to this bounding box.
16396	 */
16397	fromJSON( json ) {
16398
16399		this.min.fromArray( json.min );
16400		this.max.fromArray( json.max );
16401		return this;
16402
16403	}
16404
16405}
16406
16407const _points = [
16408	/*@__PURE__*/ new Vector3(),
16409	/*@__PURE__*/ new Vector3(),
16410	/*@__PURE__*/ new Vector3(),
16411	/*@__PURE__*/ new Vector3(),
16412	/*@__PURE__*/ new Vector3(),
16413	/*@__PURE__*/ new Vector3(),
16414	/*@__PURE__*/ new Vector3(),
16415	/*@__PURE__*/ new Vector3()
16416];
16417
16418const _vector$b = /*@__PURE__*/ new Vector3();
16419
16420const _box$4 = /*@__PURE__*/ new Box3();
16421
16422// triangle centered vertices
16423
16424const _v0$1 = /*@__PURE__*/ new Vector3();
16425const _v1$4 = /*@__PURE__*/ new Vector3();
16426const _v2$3 = /*@__PURE__*/ new Vector3();
16427
16428// triangle edge vectors
16429
16430const _f0 = /*@__PURE__*/ new Vector3();
16431const _f1 = /*@__PURE__*/ new Vector3();
16432const _f2 = /*@__PURE__*/ new Vector3();
16433
16434const _center = /*@__PURE__*/ new Vector3();
16435const _extents = /*@__PURE__*/ new Vector3();
16436const _triangleNormal = /*@__PURE__*/ new Vector3();
16437const _testAxis = /*@__PURE__*/ new Vector3();
16438
16439function satForAxes( axes, v0, v1, v2, extents ) {
16440
16441	for ( let i = 0, j = axes.length - 3; i <= j; i += 3 ) {
16442
16443		_testAxis.fromArray( axes, i );
16444		// project the aabb onto the separating axis
16445		const r = extents.x * Math.abs( _testAxis.x ) + extents.y * Math.abs( _testAxis.y ) + extents.z * Math.abs( _testAxis.z );
16446		// project all 3 vertices of the triangle onto the separating axis
16447		const p0 = v0.dot( _testAxis );
16448		const p1 = v1.dot( _testAxis );
16449		const p2 = v2.dot( _testAxis );
16450		// actual test, basically see if either of the most extreme of the triangle points intersects r
16451		if ( Math.max( - Math.max( p0, p1, p2 ), Math.min( p0, p1, p2 ) ) > r ) {
16452
16453			// points of the projected triangle are outside the projected half-length of the aabb
16454			// the axis is separating and we can exit
16455			return false;
16456
16457		}
16458
16459	}
16460
16461	return true;
16462
16463}
16464
16465// Fast Half Float Conversions, http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf
16466
16467const _tables = /*@__PURE__*/ _generateTables();
16468
16469function _generateTables() {
16470
16471	// float32 to float16 helpers
16472
16473	const buffer = new ArrayBuffer( 4 );
16474	const floatView = new Float32Array( buffer );
16475	const uint32View = new Uint32Array( buffer );
16476
16477	const baseTable = new Uint32Array( 512 );
16478	const shiftTable = new Uint32Array( 512 );
16479
16480	for ( let i = 0; i < 256; ++ i ) {
16481
16482		const e = i - 127;
16483
16484		// very small number (0, -0)
16485
16486		if ( e < -27 ) {
16487
16488			baseTable[ i ] = 0x0000;
16489			baseTable[ i | 0x100 ] = 0x8000;
16490			shiftTable[ i ] = 24;
16491			shiftTable[ i | 0x100 ] = 24;
16492
16493			// small number (denorm)
16494
16495		} else if ( e < -14 ) {
16496
16497			baseTable[ i ] = 0x0400 >> ( - e - 14 );
16498			baseTable[ i | 0x100 ] = ( 0x0400 >> ( - e - 14 ) ) | 0x8000;
16499			shiftTable[ i ] = - e - 1;
16500			shiftTable[ i | 0x100 ] = - e - 1;
16501
16502			// normal number
16503
16504		} else if ( e <= 15 ) {
16505
16506			baseTable[ i ] = ( e + 15 ) << 10;
16507			baseTable[ i | 0x100 ] = ( ( e + 15 ) << 10 ) | 0x8000;
16508			shiftTable[ i ] = 13;
16509			shiftTable[ i | 0x100 ] = 13;
16510
16511			// large number (Infinity, -Infinity)
16512
16513		} else if ( e < 128 ) {
16514
16515			baseTable[ i ] = 0x7c00;
16516			baseTable[ i | 0x100 ] = 0xfc00;
16517			shiftTable[ i ] = 24;
16518			shiftTable[ i | 0x100 ] = 24;
16519
16520			// stay (NaN, Infinity, -Infinity)
16521
16522		} else {
16523
16524			baseTable[ i ] = 0x7c00;
16525			baseTable[ i | 0x100 ] = 0xfc00;
16526			shiftTable[ i ] = 13;
16527			shiftTable[ i | 0x100 ] = 13;
16528
16529		}
16530
16531	}
16532
16533	// float16 to float32 helpers
16534
16535	const mantissaTable = new Uint32Array( 2048 );
16536	const exponentTable = new Uint32Array( 64 );
16537	const offsetTable = new Uint32Array( 64 );
16538
16539	for ( let i = 1; i < 1024; ++ i ) {
16540
16541		let m = i << 13; // zero pad mantissa bits
16542		let e = 0; // zero exponent
16543
16544		// normalized
16545		while ( ( m & 0x00800000 ) === 0 ) {
16546
16547			m <<= 1;
16548			e -= 0x00800000; // decrement exponent
16549
16550		}
16551
16552		m &= -8388609; // clear leading 1 bit
16553		e += 0x38800000; // adjust bias
16554
16555		mantissaTable[ i ] = m | e;
16556
16557	}
16558
16559	for ( let i = 1024; i < 2048; ++ i ) {
16560
16561		mantissaTable[ i ] = 0x38000000 + ( ( i - 1024 ) << 13 );
16562
16563	}
16564
16565	for ( let i = 1; i < 31; ++ i ) {
16566
16567		exponentTable[ i ] = i << 23;
16568
16569	}
16570
16571	exponentTable[ 31 ] = 0x47800000;
16572	exponentTable[ 32 ] = 0x80000000;
16573
16574	for ( let i = 33; i < 63; ++ i ) {
16575
16576		exponentTable[ i ] = 0x80000000 + ( ( i - 32 ) << 23 );
16577
16578	}
16579
16580	exponentTable[ 63 ] = 0xc7800000;
16581
16582	for ( let i = 1; i < 64; ++ i ) {
16583
16584		if ( i !== 32 ) {
16585
16586			offsetTable[ i ] = 1024;
16587
16588		}
16589
16590	}
16591
16592	return {
16593		floatView: floatView,
16594		uint32View: uint32View,
16595		baseTable: baseTable,
16596		shiftTable: shiftTable,
16597		mantissaTable: mantissaTable,
16598		exponentTable: exponentTable,
16599		offsetTable: offsetTable
16600	};
16601
16602}
16603
16604/**
16605 * Returns a half precision floating point value (FP16) from the given single
16606 * precision floating point value (FP32).
16607 *
16608 * @param {number} val - A single precision floating point value.
16609 * @return {number} The FP16 value.
16610 */
16611function toHalfFloat( val ) {
16612
16613	if ( Math.abs( val ) > 65504 ) warn( 'DataUtils.toHalfFloat(): Value out of range.' );
16614
16615	val = clamp( val, -65504, 65504 );
16616
16617	_tables.floatView[ 0 ] = val;
16618	const f = _tables.uint32View[ 0 ];
16619	const e = ( f >> 23 ) & 0x1ff;
16620	return _tables.baseTable[ e ] + ( ( f & 0x007fffff ) >> _tables.shiftTable[ e ] );
16621
16622}
16623
16624/**
16625 * Returns a single precision floating point value (FP32) from the given half
16626 * precision floating point value (FP16).
16627 *
16628 * @param {number} val - A half precision floating point value.
16629 * @return {number} The FP32 value.
16630 */
16631function fromHalfFloat( val ) {
16632
16633	const m = val >> 10;
16634	_tables.uint32View[ 0 ] = _tables.mantissaTable[ _tables.offsetTable[ m ] + ( val & 0x3ff ) ] + _tables.exponentTable[ m ];
16635	return _tables.floatView[ 0 ];
16636
16637}
16638
16639/**
16640 * A class containing utility functions for data.
16641 *
16642 * @hideconstructor
16643 */
16644class DataUtils {
16645
16646	/**
16647	 * Returns a half precision floating point value (FP16) from the given single
16648	 * precision floating point value (FP32).
16649	 *
16650	 * @param {number} val - A single precision floating point value.
16651	 * @return {number} The FP16 value.
16652	 */
16653	static toHalfFloat( val ) {
16654
16655		return toHalfFloat( val );
16656
16657	}
16658
16659	/**
16660	 * Returns a single precision floating point value (FP32) from the given half
16661	 * precision floating point value (FP16).
16662	 *
16663	 * @param {number} val - A half precision floating point value.
16664	 * @return {number} The FP32 value.
16665	 */
16666	static fromHalfFloat( val ) {
16667
16668		return fromHalfFloat( val );
16669
16670	}
16671
16672}
16673
16674const _vector$a = /*@__PURE__*/ new Vector3();
16675const _vector2$1 = /*@__PURE__*/ new Vector2();
16676
16677let _id$2 = 0;
16678
16679/**
16680 * This class stores data for an attribute (such as vertex positions, face
16681 * indices, normals, colors, UVs, and any custom attributes ) associated with
16682 * a geometry, which allows for more efficient passing of data to the GPU.
16683 *
16684 * When working with vector-like data, the `fromBufferAttribute( attribute, index )`
16685 * helper methods on vector and color class might be helpful. E.g. {@link Vector3#fromBufferAttribute}.
16686 */
16687class BufferAttribute extends EventDispatcher {
16688
16689	/**
16690	 * Constructs a new buffer attribute.
16691	 *
16692	 * @param {TypedArray} array - The array holding the attribute data.
16693	 * @param {number} itemSize - The item size.
16694	 * @param {boolean} [normalized=false] - Whether the data are normalized or not.
16695	 */
16696	constructor( array, itemSize, normalized = false ) {
16697
16698		super();
16699
16700		if ( Array.isArray( array ) ) {
16701
16702			throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' );
16703
16704		}
16705
16706		/**
16707		 * This flag can be used for type testing.
16708		 *
16709		 * @type {boolean}
16710		 * @readonly
16711		 * @default true
16712		 */
16713		this.isBufferAttribute = true;
16714
16715		/**
16716		 * The ID of the buffer attribute.
16717		 *
16718		 * @name BufferAttribute#id
16719		 * @type {number}
16720		 * @readonly
16721		 */
16722		Object.defineProperty( this, 'id', { value: _id$2 ++ } );
16723
16724		/**
16725		 * The name of the buffer attribute.
16726		 *
16727		 * @type {string}
16728		 */
16729		this.name = '';
16730
16731		/**
16732		 * The array holding the attribute data. It should have `itemSize * numVertices`
16733		 * elements, where `numVertices` is the number of vertices in the associated geometry.
16734		 *
16735		 * @type {TypedArray}
16736		 */
16737		this.array = array;
16738
16739		/**
16740		 * The number of values of the array that should be associated with a particular vertex.
16741		 * For instance, if this attribute is storing a 3-component vector (such as a position,
16742		 * normal, or color), then the value should be `3`.
16743		 *
16744		 * @type {number}
16745		 */
16746		this.itemSize = itemSize;
16747
16748		/**
16749		 * Represents the number of items this buffer attribute stores. It is internally computed
16750		 * by dividing the `array` length by the `itemSize`.
16751		 *
16752		 * @type {number}
16753		 * @readonly
16754		 */
16755		this.count = array !== undefined ? array.length / itemSize : 0;
16756
16757		/**
16758		 * Applies to integer data only. Indicates how the underlying data in the buffer maps to
16759		 * the values in the GLSL code. For instance, if `array` is an instance of `UInt16Array`,
16760		 * and `normalized` is `true`, the values `0 - +65535` in the array data will be mapped to
16761		 * `0.0f - +1.0f` in the GLSL attribute. If `normalized` is `false`, the values will be converted
16762		 * to floats unmodified, i.e. `65535` becomes `65535.0f`.
16763		 *
16764		 * @type {boolean}
16765		 */
16766		this.normalized = normalized;
16767
16768		/**
16769		 * Defines the intended usage pattern of the data store for optimization purposes.
16770		 *
16771		 * Note: After the initial use of a buffer, its usage cannot be changed. Instead,
16772		 * instantiate a new one and set the desired usage before the next render.
16773		 *
16774		 * @type {(StaticDrawUsage|DynamicDrawUsage|StreamDrawUsage|StaticReadUsage|DynamicReadUsage|StreamReadUsage|StaticCopyUsage|DynamicCopyUsage|StreamCopyUsage)}
16775		 * @default StaticDrawUsage
16776		 */
16777		this.usage = StaticDrawUsage;
16778
16779		/**
16780		 * This can be used to only update some components of stored vectors (for example, just the
16781		 * component related to color). Use the `addUpdateRange()` function to add ranges to this array.
16782		 *
16783		 * @type {Array<Object>}
16784		 */
16785		this.updateRanges = [];
16786
16787		/**
16788		 * Configures the bound GPU type for use in shaders.
16789		 *
16790		 * Note: this only has an effect for integer arrays and is not configurable for float arrays.
16791		 * For lower precision float types, use `Float16BufferAttribute`.
16792		 *
16793		 * @type {(FloatType|IntType)}
16794		 * @default FloatType
16795		 */
16796		this.gpuType = FloatType;
16797
16798		/**
16799		 * A version number, incremented every time the `needsUpdate` is set to `true`.
16800		 *
16801		 * @type {number}
16802		 */
16803		this.version = 0;
16804
16805	}
16806
16807	/**
16808	 * A callback function that is executed after the renderer has transferred the attribute
16809	 * array data to the GPU.
16810	 */
16811	onUploadCallback() {}
16812
16813	/**
16814	 * Flag to indicate that this attribute has changed and should be re-sent to
16815	 * the GPU. Set this to `true` when you modify the value of the array.
16816	 *
16817	 * @type {number}
16818	 * @default false
16819	 * @param {boolean} value
16820	 */
16821	set needsUpdate( value ) {
16822
16823		if ( value === true ) this.version ++;
16824
16825	}
16826
16827	/**
16828	 * Sets the usage of this buffer attribute.
16829	 *
16830	 * @param {(StaticDrawUsage|DynamicDrawUsage|StreamDrawUsage|StaticReadUsage|DynamicReadUsage|StreamReadUsage|StaticCopyUsage|DynamicCopyUsage|StreamCopyUsage)} value - The usage to set.
16831	 * @return {BufferAttribute} A reference to this buffer attribute.
16832	 */
16833	setUsage( value ) {
16834
16835		this.usage = value;
16836
16837		return this;
16838
16839	}
16840
16841	/**
16842	 * Adds a range of data in the data array to be updated on the GPU.
16843	 *
16844	 * @param {number} start - Position at which to start update.
16845	 * @param {number} count - The number of components to update.
16846	 */
16847	addUpdateRange( start, count ) {
16848
16849		this.updateRanges.push( { start, count } );
16850
16851	}
16852
16853	/**
16854	 * Clears the update ranges.
16855	 */
16856	clearUpdateRanges() {
16857
16858		this.updateRanges.length = 0;
16859
16860	}
16861
16862	/**
16863	 * Copies the values of the given buffer attribute to this instance.
16864	 *
16865	 * @param {BufferAttribute} source - The buffer attribute to copy.
16866	 * @return {BufferAttribute} A reference to this instance.
16867	 */
16868	copy( source ) {
16869
16870		this.name = source.name;
16871		this.array = new source.array.constructor( source.array );
16872		this.itemSize = source.itemSize;
16873		this.count = source.count;
16874		this.normalized = source.normalized;
16875
16876		this.usage = source.usage;
16877		this.gpuType = source.gpuType;
16878
16879		return this;
16880
16881	}
16882
16883	/**
16884	 * Copies a vector from the given buffer attribute to this one. The start
16885	 * and destination position in the attribute buffers are represented by the
16886	 * given indices.
16887	 *
16888	 * @param {number} index1 - The destination index into this buffer attribute.
16889	 * @param {BufferAttribute} attribute - The buffer attribute to copy from.
16890	 * @param {number} index2 - The source index into the given buffer attribute.
16891	 * @return {BufferAttribute} A reference to this instance.
16892	 */
16893	copyAt( index1, attribute, index2 ) {
16894
16895		index1 *= this.itemSize;
16896		index2 *= attribute.itemSize;
16897
16898		for ( let i = 0, l = this.itemSize; i < l; i ++ ) {
16899
16900			this.array[ index1 + i ] = attribute.array[ index2 + i ];
16901
16902		}
16903
16904		return this;
16905
16906	}
16907
16908	/**
16909	 * Copies the given array data into this buffer attribute.
16910	 *
16911	 * @param {(TypedArray|Array)} array - The array to copy.
16912	 * @return {BufferAttribute} A reference to this instance.
16913	 */
16914	copyArray( array ) {
16915
16916		this.array.set( array );
16917
16918		return this;
16919
16920	}
16921
16922	/**
16923	 * Applies the given 3x3 matrix to the given attribute. Works with
16924	 * item size `2` and `3`.
16925	 *
16926	 * @param {Matrix3} m - The matrix to apply.
16927	 * @return {BufferAttribute} A reference to this instance.
16928	 */
16929	applyMatrix3( m ) {
16930
16931		if ( this.itemSize === 2 ) {
16932
16933			for ( let i = 0, l = this.count; i < l; i ++ ) {
16934
16935				_vector2$1.fromBufferAttribute( this, i );
16936				_vector2$1.applyMatrix3( m );
16937
16938				this.setXY( i, _vector2$1.x, _vector2$1.y );
16939
16940			}
16941
16942		} else if ( this.itemSize === 3 ) {
16943
16944			for ( let i = 0, l = this.count; i < l; i ++ ) {
16945
16946				_vector$a.fromBufferAttribute( this, i );
16947				_vector$a.applyMatrix3( m );
16948
16949				this.setXYZ( i, _vector$a.x, _vector$a.y, _vector$a.z );
16950
16951			}
16952
16953		}
16954
16955		return this;
16956
16957	}
16958
16959	/**
16960	 * Applies the given 4x4 matrix to the given attribute. Only works with
16961	 * item size `3`.
16962	 *
16963	 * @param {Matrix4} m - The matrix to apply.
16964	 * @return {BufferAttribute} A reference to this instance.
16965	 */
16966	applyMatrix4( m ) {
16967
16968		for ( let i = 0, l = this.count; i < l; i ++ ) {
16969
16970			_vector$a.fromBufferAttribute( this, i );
16971
16972			_vector$a.applyMatrix4( m );
16973
16974			this.setXYZ( i, _vector$a.x, _vector$a.y, _vector$a.z );
16975
16976		}
16977
16978		return this;
16979
16980	}
16981
16982	/**
16983	 * Applies the given 3x3 normal matrix to the given attribute. Only works with
16984	 * item size `3`.
16985	 *
16986	 * @param {Matrix3} m - The normal matrix to apply.
16987	 * @return {BufferAttribute} A reference to this instance.
16988	 */
16989	applyNormalMatrix( m ) {
16990
16991		for ( let i = 0, l = this.count; i < l; i ++ ) {
16992
16993			_vector$a.fromBufferAttribute( this, i );
16994
16995			_vector$a.applyNormalMatrix( m );
16996
16997			this.setXYZ( i, _vector$a.x, _vector$a.y, _vector$a.z );
16998
16999		}
17000
17001		return this;
17002
17003	}
17004
17005	/**
17006	 * Applies the given 4x4 matrix to the given attribute. Only works with
17007	 * item size `3` and with direction vectors.
17008	 *
17009	 * @param {Matrix4} m - The matrix to apply.
17010	 * @return {BufferAttribute} A reference to this instance.
17011	 */
17012	transformDirection( m ) {
17013
17014		for ( let i = 0, l = this.count; i < l; i ++ ) {
17015
17016			_vector$a.fromBufferAttribute( this, i );
17017
17018			_vector$a.transformDirection( m );
17019
17020			this.setXYZ( i, _vector$a.x, _vector$a.y, _vector$a.z );
17021
17022		}
17023
17024		return this;
17025
17026	}
17027
17028	/**
17029	 * Sets the given array data in the buffer attribute.
17030	 *
17031	 * @param {(TypedArray|Array)} value - The array data to set.
17032	 * @param {number} [offset=0] - The offset in this buffer attribute's array.
17033	 * @return {BufferAttribute} A reference to this instance.
17034	 */
17035	set( value, offset = 0 ) {
17036
17037		// Matching BufferAttribute constructor, do not normalize the array.
17038		this.array.set( value, offset );
17039
17040		return this;
17041
17042	}
17043
17044	/**
17045	 * Returns the given component of the vector at the given index.
17046	 *
17047	 * @param {number} index - The index into the buffer attribute.
17048	 * @param {number} component - The component index.
17049	 * @return {number} The returned value.
17050	 */
17051	getComponent( index, component ) {
17052
17053		let value = this.array[ index * this.itemSize + component ];
17054
17055		if ( this.normalized ) value = denormalize( value, this.array );
17056
17057		return value;
17058
17059	}
17060
17061	/**
17062	 * Sets the given value to the given component of the vector at the given index.
17063	 *
17064	 * @param {number} index - The index into the buffer attribute.
17065	 * @param {number} component - The component index.
17066	 * @param {number} value - The value to set.
17067	 * @return {BufferAttribute} A reference to this instance.
17068	 */
17069	setComponent( index, component, value ) {
17070
17071		if ( this.normalized ) value = normalize( value, this.array );
17072
17073		this.array[ index * this.itemSize + component ] = value;
17074
17075		return this;
17076
17077	}
17078
17079	/**
17080	 * Returns the x component of the vector at the given index.
17081	 *
17082	 * @param {number} index - The index into the buffer attribute.
17083	 * @return {number} The x component.
17084	 */
17085	getX( index ) {
17086
17087		let x = this.array[ index * this.itemSize ];
17088
17089		if ( this.normalized ) x = denormalize( x, this.array );
17090
17091		return x;
17092
17093	}
17094
17095	/**
17096	 * Sets the x component of the vector at the given index.
17097	 *
17098	 * @param {number} index - The index into the buffer attribute.
17099	 * @param {number} x - The value to set.
17100	 * @return {BufferAttribute} A reference to this instance.
17101	 */
17102	setX( index, x ) {
17103
17104		if ( this.normalized ) x = normalize( x, this.array );
17105
17106		this.array[ index * this.itemSize ] = x;
17107
17108		return this;
17109
17110	}
17111
17112	/**
17113	 * Returns the y component of the vector at the given index.
17114	 *
17115	 * @param {number} index - The index into the buffer attribute.
17116	 * @return {number} The y component.
17117	 */
17118	getY( index ) {
17119
17120		let y = this.array[ index * this.itemSize + 1 ];
17121
17122		if ( this.normalized ) y = denormalize( y, this.array );
17123
17124		return y;
17125
17126	}
17127
17128	/**
17129	 * Sets the y component of the vector at the given index.
17130	 *
17131	 * @param {number} index - The index into the buffer attribute.
17132	 * @param {number} y - The value to set.
17133	 * @return {BufferAttribute} A reference to this instance.
17134	 */
17135	setY( index, y ) {
17136
17137		if ( this.normalized ) y = normalize( y, this.array );
17138
17139		this.array[ index * this.itemSize + 1 ] = y;
17140
17141		return this;
17142
17143	}
17144
17145	/**
17146	 * Returns the z component of the vector at the given index.
17147	 *
17148	 * @param {number} index - The index into the buffer attribute.
17149	 * @return {number} The z component.
17150	 */
17151	getZ( index ) {
17152
17153		let z = this.array[ index * this.itemSize + 2 ];
17154
17155		if ( this.normalized ) z = denormalize( z, this.array );
17156
17157		return z;
17158
17159	}
17160
17161	/**
17162	 * Sets the z component of the vector at the given index.
17163	 *
17164	 * @param {number} index - The index into the buffer attribute.
17165	 * @param {number} z - The value to set.
17166	 * @return {BufferAttribute} A reference to this instance.
17167	 */
17168	setZ( index, z ) {
17169
17170		if ( this.normalized ) z = normalize( z, this.array );
17171
17172		this.array[ index * this.itemSize + 2 ] = z;
17173
17174		return this;
17175
17176	}
17177
17178	/**
17179	 * Returns the w component of the vector at the given index.
17180	 *
17181	 * @param {number} index - The index into the buffer attribute.
17182	 * @return {number} The w component.
17183	 */
17184	getW( index ) {
17185
17186		let w = this.array[ index * this.itemSize + 3 ];
17187
17188		if ( this.normalized ) w = denormalize( w, this.array );
17189
17190		return w;
17191
17192	}
17193
17194	/**
17195	 * Sets the w component of the vector at the given index.
17196	 *
17197	 * @param {number} index - The index into the buffer attribute.
17198	 * @param {number} w - The value to set.
17199	 * @return {BufferAttribute} A reference to this instance.
17200	 */
17201	setW( index, w ) {
17202
17203		if ( this.normalized ) w = normalize( w, this.array );
17204
17205		this.array[ index * this.itemSize + 3 ] = w;
17206
17207		return this;
17208
17209	}
17210
17211	/**
17212	 * Sets the x and y component of the vector at the given index.
17213	 *
17214	 * @param {number} index - The index into the buffer attribute.
17215	 * @param {number} x - The value for the x component to set.
17216	 * @param {number} y - The value for the y component to set.
17217	 * @return {BufferAttribute} A reference to this instance.
17218	 */
17219	setXY( index, x, y ) {
17220
17221		index *= this.itemSize;
17222
17223		if ( this.normalized ) {
17224
17225			x = normalize( x, this.array );
17226			y = normalize( y, this.array );
17227
17228		}
17229
17230		this.array[ index + 0 ] = x;
17231		this.array[ index + 1 ] = y;
17232
17233		return this;
17234
17235	}
17236
17237	/**
17238	 * Sets the x, y and z component of the vector at the given index.
17239	 *
17240	 * @param {number} index - The index into the buffer attribute.
17241	 * @param {number} x - The value for the x component to set.
17242	 * @param {number} y - The value for the y component to set.
17243	 * @param {number} z - The value for the z component to set.
17244	 * @return {BufferAttribute} A reference to this instance.
17245	 */
17246	setXYZ( index, x, y, z ) {
17247
17248		index *= this.itemSize;
17249
17250		if ( this.normalized ) {
17251
17252			x = normalize( x, this.array );
17253			y = normalize( y, this.array );
17254			z = normalize( z, this.array );
17255
17256		}
17257
17258		this.array[ index + 0 ] = x;
17259		this.array[ index + 1 ] = y;
17260		this.array[ index + 2 ] = z;
17261
17262		return this;
17263
17264	}
17265
17266	/**
17267	 * Sets the x, y, z and w component of the vector at the given index.
17268	 *
17269	 * @param {number} index - The index into the buffer attribute.
17270	 * @param {number} x - The value for the x component to set.
17271	 * @param {number} y - The value for the y component to set.
17272	 * @param {number} z - The value for the z component to set.
17273	 * @param {number} w - The value for the w component to set.
17274	 * @return {BufferAttribute} A reference to this instance.
17275	 */
17276	setXYZW( index, x, y, z, w ) {
17277
17278		index *= this.itemSize;
17279
17280		if ( this.normalized ) {
17281
17282			x = normalize( x, this.array );
17283			y = normalize( y, this.array );
17284			z = normalize( z, this.array );
17285			w = normalize( w, this.array );
17286
17287		}
17288
17289		this.array[ index + 0 ] = x;
17290		this.array[ index + 1 ] = y;
17291		this.array[ index + 2 ] = z;
17292		this.array[ index + 3 ] = w;
17293
17294		return this;
17295
17296	}
17297
17298	/**
17299	 * Sets the given callback function that is executed after the Renderer has transferred
17300	 * the attribute array data to the GPU. Can be used to perform clean-up operations after
17301	 * the upload when attribute data are not needed anymore on the CPU side.
17302	 *
17303	 * @param {Function} callback - The `onUpload()` callback.
17304	 * @return {BufferAttribute} A reference to this instance.
17305	 */
17306	onUpload( callback ) {
17307
17308		this.onUploadCallback = callback;
17309
17310		return this;
17311
17312	}
17313
17314	/**
17315	 * Returns a new buffer attribute with copied values from this instance.
17316	 *
17317	 * @return {BufferAttribute} A clone of this instance.
17318	 */
17319	clone() {
17320
17321		return new this.constructor( this.array, this.itemSize ).copy( this );
17322
17323	}
17324
17325	/**
17326	 * Serializes the buffer attribute into JSON.
17327	 *
17328	 * @return {Object} A JSON object representing the serialized buffer attribute.
17329	 */
17330	toJSON() {
17331
17332		const data = {
17333			itemSize: this.itemSize,
17334			type: this.array.constructor.name,
17335			array: Array.from( this.array ),
17336			normalized: this.normalized
17337		};
17338
17339		
17339if ( this.name !== '' ) data.name = this.name;
17340		if ( this.usage !== StaticDrawUsage ) data.usage = this.usag
vendor: 19,224 bytes, lines 17340-18215
17340e;
17341
17342		return data;
17343
17344	}
17345
17346	/**
17347	 * Disposes of the buffer attribute. Available only in {@link WebGPURenderer}.
17348	 */
17349	dispose() {
17350
17351		this.dispatchEvent( { type: 'dispose' } );
17352
17353	}
17354
17355}
17356
17357/**
17358 * Convenient class that can be used when creating a `Int8` buffer attribute with
17359 * a plain `Array` instance.
17360 *
17361 * @augments BufferAttribute
17362 */
17363class Int8BufferAttribute extends BufferAttribute {
17364
17365	/**
17366	 * Constructs a new buffer attribute.
17367	 *
17368	 * @param {(Array<number>|Int8Array)} array - The array holding the attribute data.
17369	 * @param {number} itemSize - The item size.
17370	 * @param {boolean} [normalized=false] - Whether the data are normalized or not.
17371	 */
17372	constructor( array, itemSize, normalized ) {
17373
17374		super( new Int8Array( array ), itemSize, normalized );
17375
17376	}
17377
17378}
17379
17380/**
17381 * Convenient class that can be used when creating a `UInt8` buffer attribute with
17382 * a plain `Array` instance.
17383 *
17384 * @augments BufferAttribute
17385 */
17386class Uint8BufferAttribute extends BufferAttribute {
17387
17388	/**
17389	 * Constructs a new buffer attribute.
17390	 *
17391	 * @param {(Array<number>|Uint8Array)} array - The array holding the attribute data.
17392	 * @param {number} itemSize - The item size.
17393	 * @param {boolean} [normalized=false] - Whether the data are normalized or not.
17394	 */
17395	constructor( array, itemSize, normalized ) {
17396
17397		super( new Uint8Array( array ), itemSize, normalized );
17398
17399	}
17400
17401}
17402
17403/**
17404 * Convenient class that can be used when creating a `UInt8Clamped` buffer attribute with
17405 * a plain `Array` instance.
17406 *
17407 * @augments BufferAttribute
17408 */
17409class Uint8ClampedBufferAttribute extends BufferAttribute {
17410
17411	/**
17412	 * Constructs a new buffer attribute.
17413	 *
17414	 * @param {(Array<number>|Uint8ClampedArray)} array - The array holding the attribute data.
17415	 * @param {number} itemSize - The item size.
17416	 * @param {boolean} [normalized=false] - Whether the data are normalized or not.
17417	 */
17418	constructor( array, itemSize, normalized ) {
17419
17420		super( new Uint8ClampedArray( array ), itemSize, normalized );
17421
17422	}
17423
17424}
17425
17426/**
17427 * Convenient class that can be used when creating a `Int16` buffer attribute with
17428 * a plain `Array` instance.
17429 *
17430 * @augments BufferAttribute
17431 */
17432class Int16BufferAttribute extends BufferAttribute {
17433
17434	/**
17435	 * Constructs a new buffer attribute.
17436	 *
17437	 * @param {(Array<number>|Int16Array)} array - The array holding the attribute data.
17438	 * @param {number} itemSize - The item size.
17439	 * @param {boolean} [normalized=false] - Whether the data are normalized or not.
17440	 */
17441	constructor( array, itemSize, normalized ) {
17442
17443		super( new Int16Array( array ), itemSize, normalized );
17444
17445	}
17446
17447}
17448
17449/**
17450 * Convenient class that can be used when creating a `UInt16` buffer attribute with
17451 * a plain `Array` instance.
17452 *
17453 * @augments BufferAttribute
17454 */
17455class Uint16BufferAttribute extends BufferAttribute {
17456
17457	/**
17458	 * Constructs a new buffer attribute.
17459	 *
17460	 * @param {(Array<number>|Uint16Array)} array - The array holding the attribute data.
17461	 * @param {number} itemSize - The item size.
17462	 * @param {boolean} [normalized=false] - Whether the data are normalized or not.
17463	 */
17464	constructor( array, itemSize, normalized ) {
17465
17466		super( new Uint16Array( array ), itemSize, normalized );
17467
17468	}
17469
17470}
17471
17472/**
17473 * Convenient class that can be used when creating a `Int32` buffer attribute with
17474 * a plain `Array` instance.
17475 *
17476 * @augments BufferAttribute
17477 */
17478class Int32BufferAttribute extends BufferAttribute {
17479
17480	/**
17481	 * Constructs a new buffer attribute.
17482	 *
17483	 * @param {(Array<number>|Int32Array)} array - The array holding the attribute data.
17484	 * @param {number} itemSize - The item size.
17485	 * @param {boolean} [normalized=false] - Whether the data are normalized or not.
17486	 */
17487	constructor( array, itemSize, normalized ) {
17488
17489		super( new Int32Array( array ), itemSize, normalized );
17490
17491	}
17492
17493}
17494
17495/**
17496 * Convenient class that can be used when creating a `UInt32` buffer attribute with
17497 * a plain `Array` instance.
17498 *
17499 * @augments BufferAttribute
17500 */
17501class Uint32BufferAttribute extends BufferAttribute {
17502
17503	/**
17504	 * Constructs a new buffer attribute.
17505	 *
17506	 * @param {(Array<number>|Uint32Array)} array - The array holding the attribute data.
17507	 * @param {number} itemSize - The item size.
17508	 * @param {boolean} [normalized=false] - Whether the data are normalized or not.
17509	 */
17510	constructor( array, itemSize, normalized ) {
17511
17512		super( new Uint32Array( array ), itemSize, normalized );
17513
17514	}
17515
17516}
17517
17518/**
17519 * Convenient class that can be used when creating a `Float16` buffer attribute with
17520 * a plain `Array` instance.
17521 *
17522 * This class automatically converts to and from FP16 via `Uint16Array` since `Float16Array`
17523 * browser support is still problematic.
17524 *
17525 * @augments BufferAttribute
17526 */
17527class Float16BufferAttribute extends BufferAttribute {
17528
17529	/**
17530	 * Constructs a new buffer attribute.
17531	 *
17532	 * @param {(Array<number>|Uint16Array)} array - The array holding the attribute data.
17533	 * @param {number} itemSize - The item size.
17534	 * @param {boolean} [normalized=false] - Whether the data are normalized or not.
17535	 */
17536	constructor( array, itemSize, normalized ) {
17537
17538		super( new Uint16Array( array ), itemSize, normalized );
17539
17540		this.isFloat16BufferAttribute = true;
17541
17542	}
17543
17544	getX( index ) {
17545
17546		let x = fromHalfFloat( this.array[ index * this.itemSize ] );
17547
17548		if ( this.normalized ) x = denormalize( x, this.array );
17549
17550		return x;
17551
17552	}
17553
17554	setX( index, x ) {
17555
17556		if ( this.normalized ) x = normalize( x, this.array );
17557
17558		this.array[ index * this.itemSize ] = toHalfFloat( x );
17559
17560		return this;
17561
17562	}
17563
17564	getY( index ) {
17565
17566		let y = fromHalfFloat( this.array[ index * this.itemSize + 1 ] );
17567
17568		if ( this.normalized ) y = denormalize( y, this.array );
17569
17570		return y;
17571
17572	}
17573
17574	setY( index, y ) {
17575
17576		if ( this.normalized ) y = normalize( y, this.array );
17577
17578		this.array[ index * this.itemSize + 1 ] = toHalfFloat( y );
17579
17580		return this;
17581
17582	}
17583
17584	getZ( index ) {
17585
17586		let z = fromHalfFloat( this.array[ index * this.itemSize + 2 ] );
17587
17588		if ( this.normalized ) z = denormalize( z, this.array );
17589
17590		return z;
17591
17592	}
17593
17594	setZ( index, z ) {
17595
17596		if ( this.normalized ) z = normalize( z, this.array );
17597
17598		this.array[ index * this.itemSize + 2 ] = toHalfFloat( z );
17599
17600		return this;
17601
17602	}
17603
17604	getW( index ) {
17605
17606		let w = fromHalfFloat( this.array[ index * this.itemSize + 3 ] );
17607
17608		if ( this.normalized ) w = denormalize( w, this.array );
17609
17610		return w;
17611
17612	}
17613
17614	setW( index, w ) {
17615
17616		if ( this.normalized ) w = normalize( w, this.array );
17617
17618		this.array[ index * this.itemSize + 3 ] = toHalfFloat( w );
17619
17620		return this;
17621
17622	}
17623
17624	setXY( index, x, y ) {
17625
17626		index *= this.itemSize;
17627
17628		if ( this.normalized ) {
17629
17630			x = normalize( x, this.array );
17631			y = normalize( y, this.array );
17632
17633		}
17634
17635		this.array[ index + 0 ] = toHalfFloat( x );
17636		this.array[ index + 1 ] = toHalfFloat( y );
17637
17638		return this;
17639
17640	}
17641
17642	setXYZ( index, x, y, z ) {
17643
17644		index *= this.itemSize;
17645
17646		if ( this.normalized ) {
17647
17648			x = normalize( x, this.array );
17649			y = normalize( y, this.array );
17650			z = normalize( z, this.array );
17651
17652		}
17653
17654		this.array[ index + 0 ] = toHalfFloat( x );
17655		this.array[ index + 1 ] = toHalfFloat( y );
17656		this.array[ index + 2 ] = toHalfFloat( z );
17657
17658		return this;
17659
17660	}
17661
17662	setXYZW( index, x, y, z, w ) {
17663
17664		index *= this.itemSize;
17665
17666		if ( this.normalized ) {
17667
17668			x = normalize( x, this.array );
17669			y = normalize( y, this.array );
17670			z = normalize( z, this.array );
17671			w = normalize( w, this.array );
17672
17673		}
17674
17675		this.array[ index + 0 ] = toHalfFloat( x );
17676		this.array[ index + 1 ] = toHalfFloat( y );
17677		this.array[ index + 2 ] = toHalfFloat( z );
17678		this.array[ index + 3 ] = toHalfFloat( w );
17679
17680		return this;
17681
17682	}
17683
17684}
17685
17686/**
17687 * Convenient class that can be used when creating a `Float32` buffer attribute with
17688 * a plain `Array` instance.
17689 *
17690 * @augments BufferAttribute
17691 */
17692class Float32BufferAttribute extends BufferAttribute {
17693
17694	/**
17695	 * Constructs a new buffer attribute.
17696	 *
17697	 * @param {(Array<number>|Float32Array)} array - The array holding the attribute data.
17698	 * @param {number} itemSize - The item size.
17699	 * @param {boolean} [normalized=false] - Whether the data are normalized or not.
17700	 */
17701	constructor( array, itemSize, normalized ) {
17702
17703		super( new Float32Array( array ), itemSize, normalized );
17704
17705	}
17706
17707}
17708
17709const _box$3 = /*@__PURE__*/ new Box3();
17710const _v1$3 = /*@__PURE__*/ new Vector3();
17711const _v2$2 = /*@__PURE__*/ new Vector3();
17712
17713/**
17714 * An analytical 3D sphere defined by a center and radius. This class is mainly
17715 * used as a Bounding Sphere for 3D objects.
17716 */
17717class Sphere {
17718
17719	/**
17720	 * Constructs a new sphere.
17721	 *
17722	 * @param {Vector3} [center=(0,0,0)] - The center of the sphere
17723	 * @param {number} [radius=-1] - The radius of the sphere.
17724	 */
17725	constructor( center = new Vector3(), radius = -1 ) {
17726
17727		/**
17728		 * This flag can be used for type testing.
17729		 *
17730		 * @type {boolean}
17731		 * @readonly
17732		 * @default true
17733		 */
17734		this.isSphere = true;
17735
17736		/**
17737		 * The center of the sphere
17738		 *
17739		 * @type {Vector3}
17740		 */
17741		this.center = center;
17742
17743		/**
17744		 * The radius of the sphere.
17745		 *
17746		 * @type {number}
17747		 */
17748		this.radius = radius;
17749
17750	}
17751
17752	/**
17753	 * Sets the sphere's components by copying the given values.
17754	 *
17755	 * @param {Vector3} center - The center.
17756	 * @param {number} radius - The radius.
17757	 * @return {Sphere} A reference to this sphere.
17758	 */
17759	set( center, radius ) {
17760
17761		this.center.copy( center );
17762		this.radius = radius;
17763
17764		return this;
17765
17766	}
17767
17768	/**
17769	 * Computes the minimum bounding sphere for list of points.
17770	 * If the optional center point is given, it is used as the sphere's
17771	 * center. Otherwise, the center of the axis-aligned bounding box
17772	 * encompassing the points is calculated.
17773	 *
17774	 * @param {Array<Vector3>} points - A list of points in 3D space.
17775	 * @param {Vector3} [optionalCenter] - The center of the sphere.
17776	 * @return {Sphere} A reference to this sphere.
17777	 */
17778	setFromPoints( points, optionalCenter ) {
17779
17780		const center = this.center;
17781
17782		if ( optionalCenter !== undefined ) {
17783
17784			center.copy( optionalCenter );
17785
17786		} else {
17787
17788			_box$3.setFromPoints( points ).getCenter( center );
17789
17790		}
17791
17792		let maxRadiusSq = 0;
17793
17794		for ( let i = 0, il = points.length; i < il; i ++ ) {
17795
17796			maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( points[ i ] ) );
17797
17798		}
17799
17800		this.radius = Math.sqrt( maxRadiusSq );
17801
17802		return this;
17803
17804	}
17805
17806	/**
17807	 * Copies the values of the given sphere to this instance.
17808	 *
17809	 * @param {Sphere} sphere - The sphere to copy.
17810	 * @return {Sphere} A reference to this sphere.
17811	 */
17812	copy( sphere ) {
17813
17814		this.center.copy( sphere.center );
17815		this.radius = sphere.radius;
17816
17817		return this;
17818
17819	}
17820
17821	/**
17822	 * Returns `true` if the sphere is empty (the radius set to a negative number).
17823	 *
17824	 * Spheres with a radius of `0` contain only their center point and are not
17825	 * considered to be empty.
17826	 *
17827	 * @return {boolean} Whether this sphere is empty or not.
17828	 */
17829	isEmpty() {
17830
17831		return ( this.radius < 0 );
17832
17833	}
17834
17835	/**
17836	 * Makes this sphere empty which means in encloses a zero space in 3D.
17837	 *
17838	 * @return {Sphere} A reference to this sphere.
17839	 */
17840	makeEmpty() {
17841
17842		this.center.set( 0, 0, 0 );
17843		this.radius = -1;
17844
17845		return this;
17846
17847	}
17848
17849	/**
17850	 * Returns `true` if this sphere contains the given point inclusive of
17851	 * the surface of the sphere.
17852	 *
17853	 * @param {Vector3} point - The point to check.
17854	 * @return {boolean} Whether this sphere contains the given point or not.
17855	 */
17856	containsPoint( point ) {
17857
17858		return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) );
17859
17860	}
17861
17862	/**
17863	 * Returns the closest distance from the boundary of the sphere to the
17864	 * given point. If the sphere contains the point, the distance will
17865	 * be negative.
17866	 *
17867	 * @param {Vector3} point - The point to compute the distance to.
17868	 * @return {number} The distance to the point.
17869	 */
17870	distanceToPoint( point ) {
17871
17872		return ( point.distanceTo( this.center ) - this.radius );
17873
17874	}
17875
17876	/**
17877	 * Returns `true` if this sphere intersects with the given one.
17878	 *
17879	 * @param {Sphere} sphere - The sphere to test.
17880	 * @return {boolean} Whether this sphere intersects with the given one or not.
17881	 */
17882	intersectsSphere( sphere ) {
17883
17884		const radiusSum = this.radius + sphere.radius;
17885
17886		return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum );
17887
17888	}
17889
17890	/**
17891	 * Returns `true` if this sphere intersects with the given box.
17892	 *
17893	 * @param {Box3} box - The box to test.
17894	 * @return {boolean} Whether this sphere intersects with the given box or not.
17895	 */
17896	intersectsBox( box ) {
17897
17898		return box.intersectsSphere( this );
17899
17900	}
17901
17902	/**
17903	 * Returns `true` if this sphere intersects with the given plane.
17904	 *
17905	 * @param {Plane} plane - The plane to test.
17906	 * @return {boolean} Whether this sphere intersects with the given plane or not.
17907	 */
17908	intersectsPlane( plane ) {
17909
17910		return Math.abs( plane.distanceToPoint( this.center ) ) <= this.radius;
17911
17912	}
17913
17914	/**
17915	 * Clamps a point within the sphere. If the point is outside the sphere, it
17916	 * will clamp it to the closest point on the edge of the sphere. Points
17917	 * already inside the sphere will not be affected.
17918	 *
17919	 * @param {Vector3} point - The plane to clamp.
17920	 * @param {Vector3} target - The target vector that is used to store the method's result.
17921	 * @return {Vector3} The clamped point.
17922	 */
17923	clampPoint( point, target ) {
17924
17925		const deltaLengthSq = this.center.distanceToSquared( point );
17926
17927		target.copy( point );
17928
17929		if ( deltaLengthSq > ( this.radius * this.radius ) ) {
17930
17931			target.sub( this.center ).normalize();
17932			target.multiplyScalar( this.radius ).add( this.center );
17933
17934		}
17935
17936		return target;
17937
17938	}
17939
17940	/**
17941	 * Returns a bounding box that encloses this sphere.
17942	 *
17943	 * @param {Box3} target - The target box that is used to store the method's result.
17944	 * @return {Box3} The bounding box that encloses this sphere.
17945	 */
17946	getBoundingBox( target ) {
17947
17948		if ( this.isEmpty() ) {
17949
17950			// Empty sphere produces empty bounding box
17951			target.makeEmpty();
17952			return target;
17953
17954		}
17955
17956		target.set( this.center, this.center );
17957		target.expandByScalar( this.radius );
17958
17959		return target;
17960
17961	}
17962
17963	/**
17964	 * Transforms this sphere with the given 4x4 transformation matrix.
17965	 *
17966	 * @param {Matrix4} matrix - The transformation matrix.
17967	 * @return {Sphere} A reference to this sphere.
17968	 */
17969	applyMatrix4( matrix ) {
17970
17971		this.center.applyMatrix4( matrix );
17972		this.radius = this.radius * matrix.getMaxScaleOnAxis();
17973
17974		return this;
17975
17976	}
17977
17978	/**
17979	 * Translates the sphere's center by the given offset.
17980	 *
17981	 * @param {Vector3} offset - The offset.
17982	 * @return {Sphere} A reference to this sphere.
17983	 */
17984	translate( offset ) {
17985
17986		this.center.add( offset );
17987
17988		return this;
17989
17990	}
17991
17992	/**
17993	 * Expands the boundaries of this sphere to include the given point.
17994	 *
17995	 * @param {Vector3} point - The point to include.
17996	 * @return {Sphere} A reference to this sphere.
17997	 */
17998	expandByPoint( point ) {
17999
18000		if ( this.isEmpty() ) {
18001
18002			this.center.copy( point );
18003
18004			this.radius = 0;
18005
18006			return this;
18007
18008		}
18009
18010		_v1$3.subVectors( point, this.center );
18011
18012		const lengthSq = _v1$3.lengthSq();
18013
18014		if ( lengthSq > ( this.radius * this.radius ) ) {
18015
18016			// calculate the minimal sphere
18017
18018			const length = Math.sqrt( lengthSq );
18019
18020			const delta = ( length - this.radius ) * 0.5;
18021
18022			this.center.addScaledVector( _v1$3, delta / length );
18023
18024			this.radius += delta;
18025
18026		}
18027
18028		return this;
18029
18030	}
18031
18032	/**
18033	 * Expands this sphere to enclose both the original sphere and the given sphere.
18034	 *
18035	 * @param {Sphere} sphere - The sphere to include.
18036	 * @return {Sphere} A reference to this sphere.
18037	 */
18038	union( sphere ) {
18039
18040		if ( sphere.isEmpty() ) {
18041
18042			return this;
18043
18044		}
18045
18046		if ( this.isEmpty() ) {
18047
18048			this.copy( sphere );
18049
18050			return this;
18051
18052		}
18053
18054		if ( this.center.equals( sphere.center ) === true ) {
18055
18056			 this.radius = Math.max( this.radius, sphere.radius );
18057
18058		} else {
18059
18060			_v2$2.subVectors( sphere.center, this.center ).setLength( sphere.radius );
18061
18062			this.expandByPoint( _v1$3.copy( sphere.center ).add( _v2$2 ) );
18063
18064			this.expandByPoint( _v1$3.copy( sphere.center ).sub( _v2$2 ) );
18065
18066		}
18067
18068		return this;
18069
18070	}
18071
18072	/**
18073	 * Returns `true` if this sphere is equal with the given one.
18074	 *
18075	 * @param {Sphere} sphere - The sphere to test for equality.
18076	 * @return {boolean} Whether this bounding sphere is equal with the given one.
18077	 */
18078	equals( sphere ) {
18079
18080		return sphere.center.equals( this.center ) && ( sphere.radius === this.radius );
18081
18082	}
18083
18084	/**
18085	 * Returns a new sphere with copied values from this instance.
18086	 *
18087	 * @return {Sphere} A clone of this instance.
18088	 */
18089	clone() {
18090
18091		return new this.constructor().copy( this );
18092
18093	}
18094
18095	/**
18096	 * Returns a serialized structure of the bounding sphere.
18097	 *
18098	 * @return {Object} Serialized structure with fields representing the object state.
18099	 */
18100	toJSON() {
18101
18102		return {
18103			radius: this.radius,
18104			center: this.center.toArray()
18105		};
18106
18107	}
18108
18109	/**
18110	 * Returns a serialized structure of the bounding sphere.
18111	 *
18112	 * @param {Object} json - The serialized json to set the sphere from.
18113	 * @return {Sphere} A reference to this bounding sphere.
18114	 */
18115	fromJSON( json ) {
18116
18117		this.radius = json.radius;
18118		this.center.fromArray( json.center );
18119		return this;
18120
18121	}
18122
18123}
18124
18125let _id$1 = 0;
18126
18127const _m1 = /*@__PURE__*/ new Matrix4();
18128const _obj = /*@__PURE__*/ new Object3D();
18129const _offset = /*@__PURE__*/ new Vector3();
18130const _box$2 = /*@__PURE__*/ new Box3();
18131const _boxMorphTargets = /*@__PURE__*/ new Box3();
18132const _vector$9 = /*@__PURE__*/ new Vector3();
18133
18134/**
18135 * A representation of mesh, line, or point geometry. Includes vertex
18136 * positions, face indices, normals, colors, UVs, and custom attributes
18137 * within buffers, reducing the cost of passing all this data to the GPU.
18138 *
18139 * ```js
18140 * const geometry = new THREE.BufferGeometry();
18141 * // create a simple square shape. We duplicate the top left and bottom right
18142 * // vertices because each vertex needs to appear once per triangle.
18143 * const vertices = new Float32Array( [
18144 * 	-1.0, -1.0,  1.0, // v0
18145 * 	 1.0, -1.0,  1.0, // v1
18146 * 	 1.0,  1.0,  1.0, // v2
18147 *
18148 * 	 1.0,  1.0,  1.0, // v3
18149 * 	-1.0,  1.0,  1.0, // v4
18150 * 	-1.0, -1.0,  1.0  // v5
18151 * ] );
18152 * // itemSize = 3 because there are 3 values (components) per vertex
18153 * geometry.setAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
18154 * const material = new THREE.MeshBasicMaterial( { color: 0xff0000 } );
18155 * const mesh = new THREE.Mesh( geometry, material );
18156 * ```
18157 *
18158 * @augments EventDispatcher
18159 */
18160class BufferGeometry extends EventDispatcher {
18161
18162	/**
18163	 * Constructs a new geometry.
18164	 */
18165	constructor() {
18166
18167		super();
18168
18169		/**
18170		 * This flag can be used for type testing.
18171		 *
18172		 * @type {boolean}
18173		 * @readonly
18174		 * @default true
18175		 */
18176		this.isBufferGeometry = true;
18177
18178		/**
18179		 * The ID of the geometry.
18180		 *
18181		 * @name BufferGeometry#id
18182		 * @type {number}
18183		 * @readonly
18184		 */
18185		Object.defineProperty( this, 'id', { value: _id$1 ++ } );
18186
18187		/**
18188		 * The UUID of the geometry.
18189		 *
18190		 * @type {string}
18191		 * @readonly
18192		 */
18193		this.uuid = generateUUID();
18194
18195		/**
18196		 * The name of the geometry.
18197		 *
18198		 * @type {string}
18199		 */
18200		this.name = '';
18201		this.type = 'BufferGeometry';
18202
18203		/**
18204		 * Allows for vertices to be re-used across multiple triangles; this is
18205		 * called using "indexed triangles". Each triangle is associated with the
18206		 * indices of three vertices. This attribute therefore stores the index of
18207		 * each vertex for each triangular face. If this attribute is not set, the
18208		 * renderer assumes that each three contiguous positions represent a single triangle.
18209		 *
18210		 * @type {?BufferAttribute}
18211		 * @default null
18212		 */
18213		this.index = null;
18214
18215		/**
vendor: 7,679 bytes, lines 18216-18533
18216		 * A (storage) buffer attribute which was generated with a compute shader and
18217		 * now defines indirect draw calls.
18218		 *
18219		 * Can only be used with {@link WebGPURenderer} and a WebGPU backend.
18220		 *
18221		 * @type {?BufferAttribute}
18222		 * @default null
18223		 */
18224		this.indirect = null;
18225
18226		/**
18227		 * 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.
18228		 *
18229		 * Can only be used with {@link WebGPURenderer} and a WebGPU backend.
18230		 *
18231		 * @type {number|Array<number>}
18232		 * @default 0
18233		 */
18234		this.indirectOffset = 0;
18235
18236		/**
18237		 * This dictionary has as id the name of the attribute to be set and as value
18238		 * the buffer attribute to set it to. Rather than accessing this property directly,
18239		 * use `setAttribute()` and `getAttribute()` to access attributes of this geometry.
18240		 *
18241		 * @type {Object<string,(BufferAttribute|InterleavedBufferAttribute)>}
18242		 */
18243		this.attributes = {};
18244
18245		/**
18246		 * This dictionary holds the morph targets of the geometry.
18247		 *
18248		 * Note: Once the geometry has been rendered, the morph attribute data cannot
18249		 * be changed. You will have to call `dispose()`, and create a new geometry instance.
18250		 *
18251		 * @type {Object}
18252		 */
18253		this.morphAttributes = {};
18254
18255		/**
18256		 * Used to control the morph target behavior; when set to `true`, the morph
18257		 * target data is treated as relative offsets, rather than as absolute
18258		 * positions/normals.
18259		 *
18260		 * @type {boolean}
18261		 * @default false
18262		 */
18263		this.morphTargetsRelative = false;
18264
18265		/**
18266		 * Split the geometry into groups, each of which will be rendered in a
18267		 * separate draw call. This allows an array of materials to be used with the geometry.
18268		 *
18269		 * Use `addGroup()` and `clearGroups()` to edit groups, rather than modifying this array directly.
18270		 *
18271		 * Every vertex and index must belong to exactly one group — groups must not share vertices or
18272		 * indices, and must not leave vertices or indices unused.
18273		 *
18274		 * @type {Array<Object>}
18275		 */
18276		this.groups = [];
18277
18278		/**
18279		 * Bounding box for the geometry which can be calculated with `computeBoundingBox()`.
18280		 *
18281		 * @type {?Box3}
18282		 * @default null
18283		 */
18284		this.boundingBox = null;
18285
18286		/**
18287		 * Bounding sphere for the geometry which can be calculated with `computeBoundingSphere()`.
18288		 *
18289		 * @type {?Sphere}
18290		 * @default null
18291		 */
18292		this.boundingSphere = null;
18293
18294		/**
18295		 * Determines the part of the geometry to render. This should not be set directly,
18296		 * instead use `setDrawRange()`.
18297		 *
18298		 * @type {{start:number,count:number}}
18299		 */
18300		this.drawRange = { start: 0, count: Infinity };
18301
18302		/**
18303		 * An object that can be used to store custom data about the geometry.
18304		 * It should not hold references to functions as these will not be cloned.
18305		 *
18306		 * @type {Object}
18307		 */
18308		this.userData = {};
18309
18310	}
18311
18312	/**
18313	 * Returns the index of this geometry.
18314	 *
18315	 * @return {?BufferAttribute} The index. Returns `null` if no index is defined.
18316	 */
18317	getIndex() {
18318
18319		return this.index;
18320
18321	}
18322
18323	/**
18324	 * Sets the given index to this geometry.
18325	 *
18326	 * @param {Array<number>|BufferAttribute} index - The index to set.
18327	 * @return {BufferGeometry} A reference to this instance.
18328	 */
18329	setIndex( index ) {
18330
18331		if ( Array.isArray( index ) ) {
18332
18333			this.index = new ( arrayNeedsUint32( index ) ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 );
18334
18335		} else {
18336
18337			this.index = index;
18338
18339		}
18340
18341		return this;
18342
18343	}
18344
18345	/**
18346	 * Sets the given indirect attribute to this geometry.
18347	 *
18348	 * @param {BufferAttribute} indirect - The attribute holding indirect draw calls.
18349	 * @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.
18350	 * @return {BufferGeometry} A reference to this instance.
18351	 */
18352	setIndirect( indirect, indirectOffset = 0 ) {
18353
18354		this.indirect = indirect;
18355		this.indirectOffset = indirectOffset;
18356
18357		return this;
18358
18359	}
18360
18361	/**
18362	 * Returns the indirect attribute of this geometry.
18363	 *
18364	 * @return {?BufferAttribute} The indirect attribute. Returns `null` if no indirect attribute is defined.
18365	 */
18366	getIndirect() {
18367
18368		return this.indirect;
18369
18370	}
18371
18372	/**
18373	 * Returns the buffer attribute for the given name.
18374	 *
18375	 * @param {string} name - The attribute name.
18376	 * @return {BufferAttribute|InterleavedBufferAttribute|undefined} The buffer attribute.
18377	 * Returns `undefined` if not attribute has been found.
18378	 */
18379	getAttribute( name ) {
18380
18381		return this.attributes[ name ];
18382
18383	}
18384
18385	/**
18386	 * Sets the given attribute for the given name.
18387	 *
18388	 * @param {string} name - The attribute name.
18389	 * @param {BufferAttribute|InterleavedBufferAttribute} attribute - The attribute to set.
18390	 * @return {BufferGeometry} A reference to this instance.
18391	 */
18392	setAttribute( name, attribute ) {
18393
18394		this.attributes[ name ] = attribute;
18395
18396		return this;
18397
18398	}
18399
18400	/**
18401	 * Deletes the attribute for the given name.
18402	 *
18403	 * @param {string} name - The attribute name to delete.
18404	 * @return {BufferGeometry} A reference to this instance.
18405	 */
18406	deleteAttribute( name ) {
18407
18408		delete this.attributes[ name ];
18409
18410		return this;
18411
18412	}
18413
18414	/**
18415	 * Returns `true` if this geometry has an attribute for the given name.
18416	 *
18417	 * @param {string} name - The attribute name.
18418	 * @return {boolean} Whether this geometry has an attribute for the given name or not.
18419	 */
18420	hasAttribute( name ) {
18421
18422		return this.attributes[ name ] !== undefined;
18423
18424	}
18425
18426	/**
18427	 * Adds a group to this geometry.
18428	 *
18429	 * @param {number} start - The first element in this draw call. That is the first
18430	 * vertex for non-indexed geometry, otherwise the first triangle index.
18431	 * @param {number} count - Specifies how many vertices (or indices) are part of this group.
18432	 * @param {number} [materialIndex=0] - The material array index to use.
18433	 */
18434	addGroup( start, count, materialIndex = 0 ) {
18435
18436		this.groups.push( {
18437
18438			start: start,
18439			count: count,
18440			materialIndex: materialIndex
18441
18442		} );
18443
18444	}
18445
18446	/**
18447	 * Clears all groups.
18448	 */
18449	clearGroups() {
18450
18451		this.groups = [];
18452
18453	}
18454
18455	/**
18456	 * Sets the draw range for this geometry.
18457	 *
18458	 * @param {number} start - The first vertex for non-indexed geometry, otherwise the first triangle index.
18459	 * @param {number} count - For non-indexed BufferGeometry, `count` is the number of vertices to render.
18460	 * For indexed BufferGeometry, `count` is the number of indices to render.
18461	 */
18462	setDrawRange( start, count ) {
18463
18464		this.drawRange.start = start;
18465		this.drawRange.count = count;
18466
18467	}
18468
18469	/**
18470	 * Applies the given 4x4 transformation matrix to the geometry.
18471	 *
18472	 * @param {Matrix4} matrix - The matrix to apply.
18473	 * @return {BufferGeometry} A reference to this instance.
18474	 */
18475	applyMatrix4( matrix ) {
18476
18477		const position = this.attributes.position;
18478
18479		if ( position !== undefined ) {
18480
18481			position.applyMatrix4( matrix );
18482
18483			position.needsUpdate = true;
18484
18485		}
18486
18487		const normal = this.attributes.normal;
18488
18489		if ( normal !== undefined ) {
18490
18491			const normalMatrix = new Matrix3().getNormalMatrix( matrix );
18492
18493			normal.applyNormalMatrix( normalMatrix );
18494
18495			normal.needsUpdate = true;
18496
18497		}
18498
18499		const tangent = this.attributes.tangent;
18500
18501		if ( tangent !== undefined ) {
18502
18503			tangent.transformDirection( matrix );
18504
18505			tangent.needsUpdate = true;
18506
18507		}
18508
18509		if ( this.boundingBox !== null ) {
18510
18511			this.computeBoundingBox();
18512
18513		}
18514
18515		if ( this.boundingSphere !== null ) {
18516
18517			this.computeBoundingSphere();
18518
18519		}
18520
18521		return this;
18522
18523	}
18524
18525	/**
18526	 * Applies the rotation represented by the Quaternion to the geometry.
18527	 *
18528	 * @param {Quaternion} q - The Quaternion to apply.
18529	 * @return {BufferGeometry} A reference to this instance.
18530	 */
18531	applyQuaternion( q ) {
18532
18533		_m1
vendor: 8,143 bytes, lines 18533-18873
18533.makeRotationFromQuaternion( q );
18534
18535		this.applyMatrix4( _m1 );
18536
18537		return this;
18538
18539	}
18540
18541	/**
18542	 * Rotates the geometry about the X axis. This is typically done as a one time
18543	 * operation, and not during a loop. Use {@link Object3D#rotation} for typical
18544	 * real-time mesh rotation.
18545	 *
18546	 * @param {number} angle - The angle in radians.
18547	 * @return {BufferGeometry} A reference to this instance.
18548	 */
18549	rotateX( angle ) {
18550
18551		// rotate geometry around world x-axis
18552
18553		_m1.makeRotationX( angle );
18554
18555		this.applyMatrix4( _m1 );
18556
18557		return this;
18558
18559	}
18560
18561	/**
18562	 * Rotates the geometry about the Y axis. This is typically done as a one time
18563	 * operation, and not during a loop. Use {@link Object3D#rotation} for typical
18564	 * real-time mesh rotation.
18565	 *
18566	 * @param {number} angle - The angle in radians.
18567	 * @return {BufferGeometry} A reference to this instance.
18568	 */
18569	rotateY( angle ) {
18570
18571		// rotate geometry around world y-axis
18572
18573		_m1.makeRotationY( angle );
18574
18575		this.applyMatrix4( _m1 );
18576
18577		return this;
18578
18579	}
18580
18581	/**
18582	 * Rotates the geometry about the Z axis. This is typically done as a one time
18583	 * operation, and not during a loop. Use {@link Object3D#rotation} for typical
18584	 * real-time mesh rotation.
18585	 *
18586	 * @param {number} angle - The angle in radians.
18587	 * @return {BufferGeometry} A reference to this instance.
18588	 */
18589	rotateZ( angle ) {
18590
18591		// rotate geometry around world z-axis
18592
18593		_m1.makeRotationZ( angle );
18594
18595		this.applyMatrix4( _m1 );
18596
18597		return this;
18598
18599	}
18600
18601	/**
18602	 * Translates the geometry. This is typically done as a one time
18603	 * operation, and not during a loop. Use {@link Object3D#position} for typical
18604	 * real-time mesh rotation.
18605	 *
18606	 * @param {number} x - The x offset.
18607	 * @param {number} y - The y offset.
18608	 * @param {number} z - The z offset.
18609	 * @return {BufferGeometry} A reference to this instance.
18610	 */
18611	translate( x, y, z ) {
18612
18613		// translate geometry
18614
18615		_m1.makeTranslation( x, y, z );
18616
18617		this.applyMatrix4( _m1 );
18618
18619		return this;
18620
18621	}
18622
18623	/**
18624	 * Scales the geometry. This is typically done as a one time
18625	 * operation, and not during a loop. Use {@link Object3D#scale} for typical
18626	 * real-time mesh rotation.
18627	 *
18628	 * @param {number} x - The x scale.
18629	 * @param {number} y - The y scale.
18630	 * @param {number} z - The z scale.
18631	 * @return {BufferGeometry} A reference to this instance.
18632	 */
18633	scale( x, y, z ) {
18634
18635		// scale geometry
18636
18637		_m1.makeScale( x, y, z );
18638
18639		this.applyMatrix4( _m1 );
18640
18641		return this;
18642
18643	}
18644
18645	/**
18646	 * Rotates the geometry to face a point in 3D space. This is typically done as a one time
18647	 * operation, and not during a loop. Use {@link Object3D#lookAt} for typical
18648	 * real-time mesh rotation.
18649	 *
18650	 * @param {Vector3} vector - The target point.
18651	 * @return {BufferGeometry} A reference to this instance.
18652	 */
18653	lookAt( vector ) {
18654
18655		_obj.lookAt( vector );
18656
18657		_obj.updateMatrix();
18658
18659		this.applyMatrix4( _obj.matrix );
18660
18661		return this;
18662
18663	}
18664
18665	/**
18666	 * Center the geometry based on its bounding box.
18667	 *
18668	 * @return {BufferGeometry} A reference to this instance.
18669	 */
18670	center() {
18671
18672		this.computeBoundingBox();
18673
18674		this.boundingBox.getCenter( _offset ).negate();
18675
18676		this.translate( _offset.x, _offset.y, _offset.z );
18677
18678		return this;
18679
18680	}
18681
18682	/**
18683	 * Defines a geometry by creating a `position` attribute based on the given array of points. The array
18684	 * can hold 2D or 3D vectors. When using two-dimensional data, the `z` coordinate for all vertices is
18685	 * set to `0`.
18686	 *
18687	 * If the method is used with an existing `position` attribute, the vertex data are overwritten with the
18688	 * data from the array. The length of the array must match the vertex count.
18689	 *
18690	 * @param {Array<Vector2>|Array<Vector3>} points - The points.
18691	 * @return {BufferGeometry} A reference to this instance.
18692	 */
18693	setFromPoints( points ) {
18694
18695		const positionAttribute = this.getAttribute( 'position' );
18696
18697		if ( positionAttribute === undefined ) {
18698
18699			const position = [];
18700
18701			for ( let i = 0, l = points.length; i < l; i ++ ) {
18702
18703				const point = points[ i ];
18704				position.push( point.x, point.y, point.z || 0 );
18705
18706			}
18707
18708			this.setAttribute( 'position', new Float32BufferAttribute( position, 3 ) );
18709
18710		} else {
18711
18712			const l = Math.min( points.length, positionAttribute.count ); // make sure data do not exceed buffer size
18713
18714			for ( let i = 0; i < l; i ++ ) {
18715
18716				const point = points[ i ];
18717				positionAttribute.setXYZ( i, point.x, point.y, point.z || 0 );
18718
18719			}
18720
18721			if ( points.length > positionAttribute.count ) {
18722
18723				warn( 'BufferGeometry: Buffer size too small for points data. Use .dispose() and create a new geometry.' );
18724
18725			}
18726
18727			positionAttribute.needsUpdate = true;
18728
18729		}
18730
18731		return this;
18732
18733	}
18734
18735	/**
18736	 * Computes the bounding box of the geometry, and updates the `boundingBox` member.
18737	 * The bounding box is not computed by the engine; it must be computed by your app.
18738	 * You may need to recompute the bounding box if the geometry vertices are modified.
18739	 */
18740	computeBoundingBox() {
18741
18742		if ( this.boundingBox === null ) {
18743
18744			this.boundingBox = new Box3();
18745
18746		}
18747
18748		const position = this.attributes.position;
18749		const morphAttributesPosition = this.morphAttributes.position;
18750
18751		if ( position && position.isGLBufferAttribute ) {
18752
18753			error( 'BufferGeometry.computeBoundingBox(): GLBufferAttribute requires a manual bounding box.', this );
18754
18755			this.boundingBox.set(
18756				new Vector3( - Infinity, - Infinity, - Infinity ),
18757				new Vector3( + Infinity, + Infinity, + Infinity )
18758			);
18759
18760			return;
18761
18762		}
18763
18764		if ( position !== undefined ) {
18765
18766			this.boundingBox.setFromBufferAttribute( position );
18767
18768			// process morph attributes if present
18769
18770			if ( morphAttributesPosition ) {
18771
18772				for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {
18773
18774					const morphAttribute = morphAttributesPosition[ i ];
18775					_box$2.setFromBufferAttribute( morphAttribute );
18776
18777					if ( this.morphTargetsRelative ) {
18778
18779						_vector$9.addVectors( this.boundingBox.min, _box$2.min );
18780						this.boundingBox.expandByPoint( _vector$9 );
18781
18782						_vector$9.addVectors( this.boundingBox.max, _box$2.max );
18783						this.boundingBox.expandByPoint( _vector$9 );
18784
18785					} else {
18786
18787						this.boundingBox.expandByPoint( _box$2.min );
18788						this.boundingBox.expandByPoint( _box$2.max );
18789
18790					}
18791
18792				}
18793
18794			}
18795
18796		} else {
18797
18798			this.boundingBox.makeEmpty();
18799
18800		}
18801
18802		if ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) {
18803
18804			error( 'BufferGeometry.computeBoundingBox(): Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this );
18805
18806		}
18807
18808	}
18809
18810	/**
18811	 * Computes the bounding sphere of the geometry, and updates the `boundingSphere` member.
18812	 * The engine automatically computes the bounding sphere when it is needed, e.g., for ray casting or view frustum culling.
18813	 * You may need to recompute the bounding sphere if the geometry vertices are modified.
18814	 */
18815	computeBoundingSphere() {
18816
18817		if ( this.boundingSphere === null ) {
18818
18819			this.boundingSphere = new Sphere();
18820
18821		}
18822
18823		const position = this.attributes.position;
18824		const morphAttributesPosition = this.morphAttributes.position;
18825
18826		if ( position && position.isGLBufferAttribute ) {
18827
18828			error( 'BufferGeometry.computeBoundingSphere(): GLBufferAttribute requires a manual bounding sphere.', this );
18829
18830			this.boundingSphere.set( new Vector3(), Infinity );
18831
18832			return;
18833
18834		}
18835
18836		if ( position ) {
18837
18838			// first, find the center of the bounding sphere
18839
18840			const center = this.boundingSphere.center;
18841
18842			_box$2.setFromBufferAttribute( position );
18843
18844			// process morph attributes if present
18845
18846			if ( morphAttributesPosition ) {
18847
18848				for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {
18849
18850					const morphAttribute = morphAttributesPosition[ i ];
18851					_boxMorphTargets.setFromBufferAttribute( morphAttribute );
18852
18853					if ( this.morphTargetsRelative ) {
18854
18855						_vector$9.addVectors( _box$2.min, _boxMorphTargets.min );
18856						_box$2.expandByPoint( _vector$9 );
18857
18858						_vector$9.addVectors( _box$2.max, _boxMorphTargets.max );
18859						_box$2.expandByPoint( _vector$9 );
18860
18861					} else {
18862
18863						_box$2.expandByPoint( _boxMorphTargets.min );
18864						_box$2.expandByPoint( _boxMorphTargets.max );
18865
18866					}
18867
18868				}
18869
18870			}
18871
18872			_box$2.getCenter( center );
18873
vendor: 9,252 bytes, lines 18874-19264
18874			// second, try to find a boundingSphere with a radius smaller than the
18875			// boundingSphere of the boundingBox: sqrt(3) smaller in the best case
18876
18877			let maxRadiusSq = 0;
18878
18879			for ( let i = 0, il = position.count; i < il; i ++ ) {
18880
18881				_vector$9.fromBufferAttribute( position, i );
18882
18883				maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$9 ) );
18884
18885			}
18886
18887			// process morph attributes if present
18888
18889			if ( morphAttributesPosition ) {
18890
18891				for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {
18892
18893					const morphAttribute = morphAttributesPosition[ i ];
18894					const morphTargetsRelative = this.morphTargetsRelative;
18895
18896					for ( let j = 0, jl = morphAttribute.count; j < jl; j ++ ) {
18897
18898						_vector$9.fromBufferAttribute( morphAttribute, j );
18899
18900						if ( morphTargetsRelative ) {
18901
18902							_offset.fromBufferAttribute( position, j );
18903							_vector$9.add( _offset );
18904
18905						}
18906
18907						maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$9 ) );
18908
18909					}
18910
18911				}
18912
18913			}
18914
18915			this.boundingSphere.radius = Math.sqrt( maxRadiusSq );
18916
18917			if ( isNaN( this.boundingSphere.radius ) ) {
18918
18919				error( 'BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this );
18920
18921			}
18922
18923		}
18924
18925	}
18926
18927	/**
18928	 * Calculates and adds a tangent attribute to this geometry.
18929	 *
18930	 * The computation is only supported for indexed geometries and if position, normal, and uv attributes
18931	 * are defined. When using a tangent space normal map, prefer the MikkTSpace algorithm provided by
18932	 * {@link BufferGeometryUtils#computeMikkTSpaceTangents} instead.
18933	 */
18934	computeTangents() {
18935
18936		const index = this.index;
18937		const attributes = this.attributes;
18938
18939		// based on http://www.terathon.com/code/tangent.html
18940		// (per vertex tangents)
18941
18942		if ( index === null ||
18943			 attributes.position === undefined ||
18944			 attributes.normal === undefined ||
18945			 attributes.uv === undefined ) {
18946
18947			error( 'BufferGeometry: .computeTangents() failed. Missing required attributes (index, position, normal or uv)' );
18948			return;
18949
18950		}
18951
18952		const positionAttribute = attributes.position;
18953		const normalAttribute = attributes.normal;
18954		const uvAttribute = attributes.uv;
18955
18956		if ( this.hasAttribute( 'tangent' ) === false ) {
18957
18958			this.setAttribute( 'tangent', new BufferAttribute( new Float32Array( 4 * positionAttribute.count ), 4 ) );
18959
18960		}
18961
18962		const tangentAttribute = this.getAttribute( 'tangent' );
18963
18964		const tan1 = [], tan2 = [];
18965
18966		for ( let i = 0; i < positionAttribute.count; i ++ ) {
18967
18968			tan1[ i ] = new Vector3();
18969			tan2[ i ] = new Vector3();
18970
18971		}
18972
18973		const vA = new Vector3(),
18974			vB = new Vector3(),
18975			vC = new Vector3(),
18976
18977			uvA = new Vector2(),
18978			uvB = new Vector2(),
18979			uvC = new Vector2(),
18980
18981			sdir = new Vector3(),
18982			tdir = new Vector3();
18983
18984		function handleTriangle( a, b, c ) {
18985
18986			vA.fromBufferAttribute( positionAttribute, a );
18987			vB.fromBufferAttribute( positionAttribute, b );
18988			vC.fromBufferAttribute( positionAttribute, c );
18989
18990			uvA.fromBufferAttribute( uvAttribute, a );
18991			uvB.fromBufferAttribute( uvAttribute, b );
18992			uvC.fromBufferAttribute( uvAttribute, c );
18993
18994			vB.sub( vA );
18995			vC.sub( vA );
18996
18997			uvB.sub( uvA );
18998			uvC.sub( uvA );
18999
19000			const r = 1.0 / ( uvB.x * uvC.y - uvC.x * uvB.y );
19001
19002			// silently ignore degenerate uv triangles having coincident or colinear vertices
19003
19004			if ( ! isFinite( r ) ) return;
19005
19006			sdir.copy( vB ).multiplyScalar( uvC.y ).addScaledVector( vC, - uvB.y ).multiplyScalar( r );
19007			tdir.copy( vC ).multiplyScalar( uvB.x ).addScaledVector( vB, - uvC.x ).multiplyScalar( r );
19008
19009			tan1[ a ].add( sdir );
19010			tan1[ b ].add( sdir );
19011			tan1[ c ].add( sdir );
19012
19013			tan2[ a ].add( tdir );
19014			tan2[ b ].add( tdir );
19015			tan2[ c ].add( tdir );
19016
19017		}
19018
19019		let groups = this.groups;
19020
19021		if ( groups.length === 0 ) {
19022
19023			groups = [ {
19024				start: 0,
19025				count: index.count
19026			} ];
19027
19028		}
19029
19030		for ( let i = 0, il = groups.length; i < il; ++ i ) {
19031
19032			const group = groups[ i ];
19033
19034			const start = group.start;
19035			const count = group.count;
19036
19037			for ( let j = start, jl = start + count; j < jl; j += 3 ) {
19038
19039				handleTriangle(
19040					index.getX( j + 0 ),
19041					index.getX( j + 1 ),
19042					index.getX( j + 2 )
19043				);
19044
19045			}
19046
19047		}
19048
19049		const tmp = new Vector3(), tmp2 = new Vector3();
19050		const n = new Vector3(), n2 = new Vector3();
19051
19052		function handleVertex( v ) {
19053
19054			n.fromBufferAttribute( normalAttribute, v );
19055			n2.copy( n );
19056
19057			const t = tan1[ v ];
19058
19059			// Gram-Schmidt orthogonalize
19060
19061			tmp.copy( t );
19062			tmp.sub( n.multiplyScalar( n.dot( t ) ) ).normalize();
19063
19064			// Calculate handedness
19065
19066			tmp2.crossVectors( n2, t );
19067			const test = tmp2.dot( tan2[ v ] );
19068			const w = ( test < 0.0 ) ? -1 : 1.0;
19069
19070			tangentAttribute.setXYZW( v, tmp.x, tmp.y, tmp.z, w );
19071
19072		}
19073
19074		for ( let i = 0, il = groups.length; i < il; ++ i ) {
19075
19076			const group = groups[ i ];
19077
19078			const start = group.start;
19079			const count = group.count;
19080
19081			for ( let j = start, jl = start + count; j < jl; j += 3 ) {
19082
19083				handleVertex( index.getX( j + 0 ) );
19084				handleVertex( index.getX( j + 1 ) );
19085				handleVertex( index.getX( j + 2 ) );
19086
19087			}
19088
19089		}
19090
19091	}
19092
19093	/**
19094	 * Computes vertex normals for the given vertex data. For indexed geometries, the method sets
19095	 * each vertex normal to be the average of the face normals of the faces that share that vertex.
19096	 * For non-indexed geometries, vertices are not shared, and the method sets each vertex normal
19097	 * to be the same as the face normal.
19098	 */
19099	computeVertexNormals() {
19100
19101		const index = this.index;
19102		const positionAttribute = this.getAttribute( 'position' );
19103
19104		if ( positionAttribute !== undefined ) {
19105
19106			let normalAttribute = this.getAttribute( 'normal' );
19107
19108			if ( normalAttribute === undefined ) {
19109
19110				normalAttribute = new BufferAttribute( new Float32Array( positionAttribute.count * 3 ), 3 );
19111				this.setAttribute( 'normal', normalAttribute );
19112
19113			} else {
19114
19115				// reset existing normals to zero
19116
19117				for ( let i = 0, il = normalAttribute.count; i < il; i ++ ) {
19118
19119					normalAttribute.setXYZ( i, 0, 0, 0 );
19120
19121				}
19122
19123			}
19124
19125			const pA = new Vector3(), pB = new Vector3(), pC = new Vector3();
19126			const nA = new Vector3(), nB = new Vector3(), nC = new Vector3();
19127			const cb = new Vector3(), ab = new Vector3();
19128
19129			// indexed elements
19130
19131			if ( index ) {
19132
19133				for ( let i = 0, il = index.count; i < il; i += 3 ) {
19134
19135					const vA = index.getX( i + 0 );
19136					const vB = index.getX( i + 1 );
19137					const vC = index.getX( i + 2 );
19138
19139					pA.fromBufferAttribute( positionAttribute, vA );
19140					pB.fromBufferAttribute( positionAttribute, vB );
19141					pC.fromBufferAttribute( positionAttribute, vC );
19142
19143					cb.subVectors( pC, pB );
19144					ab.subVectors( pA, pB );
19145					cb.cross( ab );
19146
19147					nA.fromBufferAttribute( normalAttribute, vA );
19148					nB.fromBufferAttribute( normalAttribute, vB );
19149					nC.fromBufferAttribute( normalAttribute, vC );
19150
19151					nA.add( cb );
19152					nB.add( cb );
19153					nC.add( cb );
19154
19155					normalAttribute.setXYZ( vA, nA.x, nA.y, nA.z );
19156					normalAttribute.setXYZ( vB, nB.x, nB.y, nB.z );
19157					normalAttribute.setXYZ( vC, nC.x, nC.y, nC.z );
19158
19159				}
19160
19161			} else {
19162
19163				// non-indexed elements (unconnected triangle soup)
19164
19165				for ( let i = 0, il = positionAttribute.count; i < il; i += 3 ) {
19166
19167					pA.fromBufferAttribute( positionAttribute, i + 0 );
19168					pB.fromBufferAttribute( positionAttribute, i + 1 );
19169					pC.fromBufferAttribute( positionAttribute, i + 2 );
19170
19171					cb.subVectors( pC, pB );
19172					ab.subVectors( pA, pB );
19173					cb.cross( ab );
19174
19175					normalAttribute.setXYZ( i + 0, cb.x, cb.y, cb.z );
19176					normalAttribute.setXYZ( i + 1, cb.x, cb.y, cb.z );
19177					normalAttribute.setXYZ( i + 2, cb.x, cb.y, cb.z );
19178
19179				}
19180
19181			}
19182
19183			this.normalizeNormals();
19184
19185			normalAttribute.needsUpdate = true;
19186
19187		}
19188
19189	}
19190
19191	/**
19192	 * Ensures every normal vector in a geometry will have a magnitude of `1`. This will
19193	 * correct lighting on the geometry surfaces.
19194	 */
19195	normalizeNormals() {
19196
19197		const normals = this.attributes.normal;
19198
19199		for ( let i = 0, il = normals.count; i < il; i ++ ) {
19200
19201			_vector$9.fromBufferAttribute( normals, i );
19202
19203			_vector$9.normalize();
19204
19205			normals.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z );
19206
19207		}
19208
19209	}
19210
19211	/**
19212	 * Return a new non-index version of this indexed geometry. If the geometry
19213	 * is already non-indexed, the method is a NOOP.
19214	 *
19215	 * @return {BufferGeometry} The non-indexed version of this indexed geometry.
19216	 */
19217	toNonIndexed() {
19218
19219		function convertBufferAttribute( attribute, indices ) {
19220
19221			const array = attribute.array;
19222			const itemSize = attribute.itemSize;
19223			const normalized = attribute.normalized;
19224
19225			const array2 = new array.constructor( indices.length * itemSize );
19226
19227			let index = 0, index2 = 0;
19228
19229			for ( let i = 0, l = indices.length; i < l; i ++ ) {
19230
19231				if ( attribute.isInterleavedBufferAttribute ) {
19232
19233					index = indices[ i ] * attribute.data.stride + attribute.offset;
19234
19235				} else {
19236
19237					index = indices[ i ] * itemSize;
19238
19239				}
19240
19241				for ( let j = 0; j < itemSize; j ++ ) {
19242
19243					array2[ index2 ++ ] = array[ index ++ ];
19244
19245				}
19246
19247			}
19248
19249			return new BufferAttribute( array2, itemSize, normalized );
19250
19251		}
19252
19253		//
19254
19255		if ( this.index === null ) {
19256
19257			warn( 'BufferGeometry.toNonIndexed(): BufferGeometry is already non-indexed.' );
19258			return this;
19259
19260		}
19261
19262		const geometry2 = new BufferGeometry();
19263
19264		const indices = this.index.array;
vendor: 1,085 bytes, lines 19265-19318
19265		const attributes = this.attributes;
19266
19267		// attributes
19268
19269		for ( const name in attributes ) {
19270
19271			const attribute = attributes[ name ];
19272
19273			const newAttribute = convertBufferAttribute( attribute, indices );
19274
19275			geometry2.setAttribute( name, newAttribute );
19276
19277		}
19278
19279		// morph attributes
19280
19281		const morphAttributes = this.morphAttributes;
19282
19283		for ( const name in morphAttributes ) {
19284
19285			const morphArray = [];
19286			const morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes
19287
19288			for ( let i = 0, il = morphAttribute.length; i < il; i ++ ) {
19289
19290				const attribute = morphAttribute[ i ];
19291
19292				const newAttribute = convertBufferAttribute( attribute, indices );
19293
19294				morphArray.push( newAttribute );
19295
19296			}
19297
19298			geometry2.morphAttributes[ name ] = morphArray;
19299
19300		}
19301
19302		geometry2.morphTargetsRelative = this.morphTargetsRelative;
19303
19304		// groups
19305
19306		const groups = this.groups;
19307
19308		for ( let i = 0, l = groups.length; i < l; i ++ ) {
19309
19310			const group = groups[ i ];
19311			geometry2.addGroup( group.start, group.count, group.materialIndex );
19312
19313		}
19314
19315		return geometry2;
19316
19317	}
19318
vendor: 6,721 bytes, lines 19319-19652
19319	/**
19320	 * Serializes the geometry into JSON.
19321	 *
19322	 * @return {Object} A JSON object representing the serialized geometry.
19323	 */
19324	toJSON() {
19325
19326		const data = {
19327			metadata: {
19328				version: 4.7,
19329				type: 'BufferGeometry',
19330				generator: 'BufferGeometry.toJSON'
19331			}
19332		};
19333
19334		// standard BufferGeometry serialization
19335
19336		data.uuid = this.uuid;
19337		data.type = this.type;
19338		if ( this.name !== '' ) data.name = this.name;
19339		if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData;
19340
19341		if ( this.parameters !== undefined ) {
19342
19343			const parameters = this.parameters;
19344
19345			for ( const key in parameters ) {
19346
19347				if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ];
19348
19349			}
19350
19351			return data;
19352
19353		}
19354
19355		// for simplicity the code assumes attributes are not shared across geometries, see #15811
19356
19357		data.data = { attributes: {} };
19358
19359		const index = this.index;
19360
19361		if ( index !== null ) {
19362
19363			data.data.index = {
19364				type: index.array.constructor.name,
19365				array: Array.prototype.slice.call( index.array )
19366			};
19367
19368		}
19369
19370		const attributes = this.attributes;
19371
19372		for ( const key in attributes ) {
19373
19374			const attribute = attributes[ key ];
19375
19376			data.data.attributes[ key ] = attribute.toJSON( data.data );
19377
19378		}
19379
19380		const morphAttributes = {};
19381		let hasMorphAttributes = false;
19382
19383		for ( const key in this.morphAttributes ) {
19384
19385			const attributeArray = this.morphAttributes[ key ];
19386
19387			const array = [];
19388
19389			for ( let i = 0, il = attributeArray.length; i < il; i ++ ) {
19390
19391				const attribute = attributeArray[ i ];
19392
19393				array.push( attribute.toJSON( data.data ) );
19394
19395			}
19396
19397			if ( array.length > 0 ) {
19398
19399				morphAttributes[ key ] = array;
19400
19401				hasMorphAttributes = true;
19402
19403			}
19404
19405		}
19406
19407		if ( hasMorphAttributes ) {
19408
19409			data.data.morphAttributes = morphAttributes;
19410			data.data.morphTargetsRelative = this.morphTargetsRelative;
19411
19412		}
19413
19414		const groups = this.groups;
19415
19416		if ( groups.length > 0 ) {
19417
19418			data.data.groups = JSON.parse( JSON.stringify( groups ) );
19419
19420		}
19421
19422		const boundingSphere = this.boundingSphere;
19423
19424		if ( boundingSphere !== null ) {
19425
19426			data.data.boundingSphere = boundingSphere.toJSON();
19427
19428		}
19429
19430		return data;
19431
19432	}
19433
19434	/**
19435	 * Returns a new geometry with copied values from this instance.
19436	 *
19437	 * @return {BufferGeometry} A clone of this instance.
19438	 */
19439	clone() {
19440
19441		return new this.constructor().copy( this );
19442
19443	}
19444
19445	/**
19446	 * Copies the values of the given geometry to this instance.
19447	 *
19448	 * @param {BufferGeometry} source - The geometry to copy.
19449	 * @return {BufferGeometry} A reference to this instance.
19450	 */
19451	copy( source ) {
19452
19453		// reset
19454
19455		this.index = null;
19456		this.attributes = {};
19457		this.morphAttributes = {};
19458		this.groups = [];
19459		this.boundingBox = null;
19460		this.boundingSphere = null;
19461
19462		// used for storing cloned, shared data
19463
19464		const data = {};
19465
19466		// name
19467
19468		this.name = source.name;
19469
19470		// index
19471
19472		const index = source.index;
19473
19474		if ( index !== null ) {
19475
19476			this.setIndex( index.clone() );
19477
19478		}
19479
19480		// attributes
19481
19482		const attributes = source.attributes;
19483
19484		for ( const name in attributes ) {
19485
19486			const attribute = attributes[ name ];
19487			this.setAttribute( name, attribute.clone( data ) );
19488
19489		}
19490
19491		// morph attributes
19492
19493		const morphAttributes = source.morphAttributes;
19494
19495		for ( const name in morphAttributes ) {
19496
19497			const array = [];
19498			const morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes
19499
19500			for ( let i = 0, l = morphAttribute.length; i < l; i ++ ) {
19501
19502				array.push( morphAttribute[ i ].clone( data ) );
19503
19504			}
19505
19506			this.morphAttributes[ name ] = array;
19507
19508		}
19509
19510		this.morphTargetsRelative = source.morphTargetsRelative;
19511
19512		// groups
19513
19514		const groups = source.groups;
19515
19516		for ( let i = 0, l = groups.length; i < l; i ++ ) {
19517
19518			const group = groups[ i ];
19519			this.addGroup( group.start, group.count, group.materialIndex );
19520
19521		}
19522
19523		// bounding box
19524
19525		const boundingBox = source.boundingBox;
19526
19527		if ( boundingBox !== null ) {
19528
19529			this.boundingBox = boundingBox.clone();
19530
19531		}
19532
19533		// bounding sphere
19534
19535		const boundingSphere = source.boundingSphere;
19536
19537		if ( boundingSphere !== null ) {
19538
19539			this.boundingSphere = boundingSphere.clone();
19540
19541		}
19542
19543		// draw range
19544
19545		this.drawRange.start = source.drawRange.start;
19546		this.drawRange.count = source.drawRange.count;
19547
19548		// user data
19549
19550		this.userData = source.userData;
19551
19552		return this;
19553
19554	}
19555
19556	/**
19557	 * Frees the GPU-related resources allocated by this instance. Call this
19558	 * method whenever this instance is no longer used in your app.
19559	 *
19560	 * @fires BufferGeometry#dispose
19561	 */
19562	dispose() {
19563
19564		this.dispatchEvent( { type: 'dispose' } );
19565
19566	}
19567
19568}
19569
19570/**
19571 * "Interleaved" means that multiple attributes, possibly of different types,
19572 * (e.g., position, normal, uv, color) are packed into a single array buffer.
19573 *
19574 * An introduction into interleaved arrays can be found here: [Interleaved array basics](https://blog.tojicode.com/2011/05/interleaved-array-basics.html)
19575 */
19576class InterleavedBuffer {
19577
19578	/**
19579	 * Constructs a new interleaved buffer.
19580	 *
19581	 * @param {TypedArray} array - A typed array with a shared buffer storing attribute data.
19582	 * @param {number} stride - The number of typed-array elements per vertex.
19583	 */
19584	constructor( array, stride ) {
19585
19586		/**
19587		 * This flag can be used for type testing.
19588		 *
19589		 * @type {boolean}
19590		 * @readonly
19591		 * @default true
19592		 */
19593		this.isInterleavedBuffer = true;
19594
19595		/**
19596		 * A typed array with a shared buffer storing attribute data.
19597		 *
19598		 * @type {TypedArray}
19599		 */
19600		this.array = array;
19601
19602		/**
19603		 * The number of typed-array elements per vertex.
19604		 *
19605		 * @type {number}
19606		 */
19607		this.stride = stride;
19608
19609		/**
19610		 * The total number of elements in the array
19611		 *
19612		 * @type {number}
19613		 * @readonly
19614		 */
19615		this.count = array !== undefined ? array.length / stride : 0;
19616
19617		/**
19618		 * Defines the intended usage pattern of the data store for optimization purposes.
19619		 *
19620		 * Note: After the initial use of a buffer, its usage cannot be changed. Instead,
19621		 * instantiate a new one and set the desired usage before the next render.
19622		 *
19623		 * @type {(StaticDrawUsage|DynamicDrawUsage|StreamDrawUsage|StaticReadUsage|DynamicReadUsage|StreamReadUsage|StaticCopyUsage|DynamicCopyUsage|StreamCopyUsage)}
19624		 * @default StaticDrawUsage
19625		 */
19626		this.usage = StaticDrawUsage;
19627
19628		/**
19629		 * This can be used to only update some components of stored vectors (for example, just the
19630		 * component related to color). Use the `addUpdateRange()` function to add ranges to this array.
19631		 *
19632		 * @type {Array<Object>}
19633		 */
19634		this.updateRanges = [];
19635
19636		/**
19637		 * A version number, incremented every time the `needsUpdate` is set to `true`.
19638		 *
19639		 * @type {number}
19640		 */
19641		this.version = 0;
19642
19643		/**
19644		 * The UUID of the interleaved buffer.
19645		 *
19646		 * @type {string}
19647		 * @readonly
19648		 */
19649		this.uuid = generateUUID();
19650
19651	}
19652
vendor: 3,573 bytes, lines 19653-19799
19653	/**
19654	 * A callback function that is executed after the renderer has transferred the attribute array
19655	 * data to the GPU.
19656	 */
19657	onUploadCallback() {}
19658
19659	/**
19660	 * Flag to indicate that this attribute has changed and should be re-sent to
19661	 * the GPU. Set this to `true` when you modify the value of the array.
19662	 *
19663	 * @type {number}
19664	 * @default false
19665	 * @param {boolean} value
19666	 */
19667	set needsUpdate( value ) {
19668
19669		if ( value === true ) this.version ++;
19670
19671	}
19672
19673	/**
19674	 * Sets the usage of this interleaved buffer.
19675	 *
19676	 * @param {(StaticDrawUsage|DynamicDrawUsage|StreamDrawUsage|StaticReadUsage|DynamicReadUsage|StreamReadUsage|StaticCopyUsage|DynamicCopyUsage|StreamCopyUsage)} value - The usage to set.
19677	 * @return {InterleavedBuffer} A reference to this interleaved buffer.
19678	 */
19679	setUsage( value ) {
19680
19681		this.usage = value;
19682
19683		return this;
19684
19685	}
19686
19687	/**
19688	 * Adds a range of data in the data array to be updated on the GPU.
19689	 *
19690	 * @param {number} start - Position at which to start update.
19691	 * @param {number} count - The number of components to update.
19692	 */
19693	addUpdateRange( start, count ) {
19694
19695		this.updateRanges.push( { start, count } );
19696
19697	}
19698
19699	/**
19700	 * Clears the update ranges.
19701	 */
19702	clearUpdateRanges() {
19703
19704		this.updateRanges.length = 0;
19705
19706	}
19707
19708	/**
19709	 * Copies the values of the given interleaved buffer to this instance.
19710	 *
19711	 * @param {InterleavedBuffer} source - The interleaved buffer to copy.
19712	 * @return {InterleavedBuffer} A reference to this instance.
19713	 */
19714	copy( source ) {
19715
19716		this.array = new source.array.constructor( source.array );
19717		this.count = source.count;
19718		this.stride = source.stride;
19719		this.usage = source.usage;
19720
19721		return this;
19722
19723	}
19724
19725	/**
19726	 * Copies a vector from the given interleaved buffer to this one. The start
19727	 * and destination position in the attribute buffers are represented by the
19728	 * given indices.
19729	 *
19730	 * @param {number} index1 - The destination index into this interleaved buffer.
19731	 * @param {InterleavedBuffer} interleavedBuffer - The interleaved buffer to copy from.
19732	 * @param {number} index2 - The source index into the given interleaved buffer.
19733	 * @return {InterleavedBuffer} A reference to this instance.
19734	 */
19735	copyAt( index1, interleavedBuffer, index2 ) {
19736
19737		index1 *= this.stride;
19738		index2 *= interleavedBuffer.stride;
19739
19740		for ( let i = 0, l = this.stride; i < l; i ++ ) {
19741
19742			this.array[ index1 + i ] = interleavedBuffer.array[ index2 + i ];
19743
19744		}
19745
19746		return this;
19747
19748	}
19749
19750	/**
19751	 * Sets the given array data in the interleaved buffer.
19752	 *
19753	 * @param {(TypedArray|Array)} value - The array data to set.
19754	 * @param {number} [offset=0] - The offset in this interleaved buffer's array.
19755	 * @return {InterleavedBuffer} A reference to this instance.
19756	 */
19757	set( value, offset = 0 ) {
19758
19759		this.array.set( value, offset );
19760
19761		return this;
19762
19763	}
19764
19765	/**
19766	 * Returns a new interleaved buffer with copied values from this instance.
19767	 *
19768	 * @param {Object} [data] - An object with shared array buffers that allows to retain shared structures.
19769	 * @return {InterleavedBuffer} A clone of this instance.
19770	 */
19771	clone( data ) {
19772
19773		if ( data.arrayBuffers === undefined ) {
19774
19775			data.arrayBuffers = {};
19776
19777		}
19778
19779		if ( this.array.buffer._uuid === undefined ) {
19780
19781			this.array.buffer._uuid = generateUUID();
19782
19783		}
19784
19785		if ( data.arrayBuffers[ this.array.buffer._uuid ] === undefined ) {
19786
19787			data.arrayBuffers[ this.array.buffer._uuid ] = this.array.slice( 0 ).buffer;
19788
19789		}
19790
19791		const array = new this.array.constructor( data.arrayBuffers[ this.array.buffer._uuid ] );
19792
19793		const ib = new this.constructor( array, this.stride );
19794		ib.setUsage( this.usage );
19795
19796		return ib;
19797
19798	}
19799
vendor: 2,927 bytes, lines 19800-19933
19800	/**
19801	 * Sets the given callback function that is executed after the Renderer has transferred
19802	 * the array data to the GPU. Can be used to perform clean-up operations after
19803	 * the upload when data are not needed anymore on the CPU side.
19804	 *
19805	 * @param {Function} callback - The `onUpload()` callback.
19806	 * @return {InterleavedBuffer} A reference to this instance.
19807	 */
19808	onUpload( callback ) {
19809
19810		this.onUploadCallback = callback;
19811
19812		return this;
19813
19814	}
19815
19816	/**
19817	 * Serializes the interleaved buffer into JSON.
19818	 *
19819	 * @param {Object} [data] - An optional value holding meta information about the serialization.
19820	 * @return {Object} A JSON object representing the serialized interleaved buffer.
19821	 */
19822	toJSON( data ) {
19823
19824		if ( data.arrayBuffers === undefined ) {
19825
19826			data.arrayBuffers = {};
19827
19828		}
19829
19830		// generate UUID for array buffer if necessary
19831
19832		if ( this.array.buffer._uuid === undefined ) {
19833
19834			this.array.buffer._uuid = generateUUID();
19835
19836		}
19837
19838		if ( data.arrayBuffers[ this.array.buffer._uuid ] === undefined ) {
19839
19840			data.arrayBuffers[ this.array.buffer._uuid ] = Array.from( new Uint32Array( this.array.buffer ) );
19841
19842		}
19843
19844		//
19845
19846		return {
19847			uuid: this.uuid,
19848			buffer: this.array.buffer._uuid,
19849			type: this.array.constructor.name,
19850			stride: this.stride
19851		};
19852
19853	}
19854
19855}
19856
19857const _vector$8 = /*@__PURE__*/ new Vector3();
19858
19859/**
19860 * An alternative version of a buffer attribute with interleaved data. Interleaved
19861 * attributes share a common interleaved data storage ({@link InterleavedBuffer}) and refer with
19862 * different offsets into the buffer.
19863 */
19864class InterleavedBufferAttribute {
19865
19866	/**
19867	 * Constructs a new interleaved buffer attribute.
19868	 *
19869	 * @param {InterleavedBuffer} interleavedBuffer - The buffer holding the interleaved data.
19870	 * @param {number} itemSize - The item size.
19871	 * @param {number} offset - The attribute offset into the buffer.
19872	 * @param {boolean} [normalized=false] - Whether the data are normalized or not.
19873	 */
19874	constructor( interleavedBuffer, itemSize, offset, normalized = false ) {
19875
19876		/**
19877		 * This flag can be used for type testing.
19878		 *
19879		 * @type {boolean}
19880		 * @readonly
19881		 * @default true
19882		 */
19883		this.isInterleavedBufferAttribute = true;
19884
19885		/**
19886		 * The name of the buffer attribute.
19887		 *
19888		 * @type {string}
19889		 */
19890		this.name = '';
19891
19892		/**
19893		 * The buffer holding the interleaved data.
19894		 *
19895		 * @type {InterleavedBuffer}
19896		 */
19897		this.data = interleavedBuffer;
19898
19899		/**
19900		 * The item size, see {@link BufferAttribute#itemSize}.
19901		 *
19902		 * @type {number}
19903		 */
19904		this.itemSize = itemSize;
19905
19906		/**
19907		 * The attribute offset into the buffer.
19908		 *
19909		 * @type {number}
19910		 */
19911		this.offset = offset;
19912
19913		/**
19914		 * Whether the data are normalized or not, see {@link BufferAttribute#normalized}
19915		 *
19916		 * @type {InterleavedBuffer}
19917		 */
19918		this.normalized = normalized;
19919
19920	}
19921
19922	/**
19923	 * The item count of this buffer attribute.
19924	 *
19925	 * @type {number}
19926	 * @readonly
19927	 */
19928	get count() {
19929
19930		return this.data.count;
19931
19932	}
19933
vendor: 10,956 bytes, lines 19934-20398
19934	/**
19935	 * The array holding the interleaved buffer attribute data.
19936	 *
19937	 * @type {TypedArray}
19938	 */
19939	get array() {
19940
19941		return this.data.array;
19942
19943	}
19944
19945	/**
19946	 * Flag to indicate that this attribute has changed and should be re-sent to
19947	 * the GPU. Set this to `true` when you modify the value of the array.
19948	 *
19949	 * @type {number}
19950	 * @default false
19951	 * @param {boolean} value
19952	 */
19953	set needsUpdate( value ) {
19954
19955		this.data.needsUpdate = value;
19956
19957	}
19958
19959	/**
19960	 * Applies the given 4x4 matrix to the given attribute. Only works with
19961	 * item size `3`.
19962	 *
19963	 * @param {Matrix4} m - The matrix to apply.
19964	 * @return {InterleavedBufferAttribute} A reference to this instance.
19965	 */
19966	applyMatrix4( m ) {
19967
19968		for ( let i = 0, l = this.data.count; i < l; i ++ ) {
19969
19970			_vector$8.fromBufferAttribute( this, i );
19971
19972			_vector$8.applyMatrix4( m );
19973
19974			this.setXYZ( i, _vector$8.x, _vector$8.y, _vector$8.z );
19975
19976		}
19977
19978		return this;
19979
19980	}
19981
19982	/**
19983	 * Applies the given 3x3 normal matrix to the given attribute. Only works with
19984	 * item size `3`.
19985	 *
19986	 * @param {Matrix3} m - The normal matrix to apply.
19987	 * @return {InterleavedBufferAttribute} A reference to this instance.
19988	 */
19989	applyNormalMatrix( m ) {
19990
19991		for ( let i = 0, l = this.count; i < l; i ++ ) {
19992
19993			_vector$8.fromBufferAttribute( this, i );
19994
19995			_vector$8.applyNormalMatrix( m );
19996
19997			this.setXYZ( i, _vector$8.x, _vector$8.y, _vector$8.z );
19998
19999		}
20000
20001		return this;
20002
20003	}
20004
20005	/**
20006	 * Applies the given 4x4 matrix to the given attribute. Only works with
20007	 * item size `3` and with direction vectors.
20008	 *
20009	 * @param {Matrix4} m - The matrix to apply.
20010	 * @return {InterleavedBufferAttribute} A reference to this instance.
20011	 */
20012	transformDirection( m ) {
20013
20014		for ( let i = 0, l = this.count; i < l; i ++ ) {
20015
20016			_vector$8.fromBufferAttribute( this, i );
20017
20018			_vector$8.transformDirection( m );
20019
20020			this.setXYZ( i, _vector$8.x, _vector$8.y, _vector$8.z );
20021
20022		}
20023
20024		return this;
20025
20026	}
20027
20028	/**
20029	 * Returns the given component of the vector at the given index.
20030	 *
20031	 * @param {number} index - The index into the buffer attribute.
20032	 * @param {number} component - The component index.
20033	 * @return {number} The returned value.
20034	 */
20035	getComponent( index, component ) {
20036
20037		let value = this.array[ index * this.data.stride + this.offset + component ];
20038
20039		if ( this.normalized ) value = denormalize( value, this.array );
20040
20041		return value;
20042
20043	}
20044
20045	/**
20046	 * Sets the given value to the given component of the vector at the given index.
20047	 *
20048	 * @param {number} index - The index into the buffer attribute.
20049	 * @param {number} component - The component index.
20050	 * @param {number} value - The value to set.
20051	 * @return {InterleavedBufferAttribute} A reference to this instance.
20052	 */
20053	setComponent( index, component, value ) {
20054
20055		if ( this.normalized ) value = normalize( value, this.array );
20056
20057		this.data.array[ index * this.data.stride + this.offset + component ] = value;
20058
20059		return this;
20060
20061	}
20062
20063	/**
20064	 * Sets the x component of the vector at the given index.
20065	 *
20066	 * @param {number} index - The index into the buffer attribute.
20067	 * @param {number} x - The value to set.
20068	 * @return {InterleavedBufferAttribute} A reference to this instance.
20069	 */
20070	setX( index, x ) {
20071
20072		if ( this.normalized ) x = normalize( x, this.array );
20073
20074		this.data.array[ index * this.data.stride + this.offset ] = x;
20075
20076		return this;
20077
20078	}
20079
20080	/**
20081	 * Sets the y component of the vector at the given index.
20082	 *
20083	 * @param {number} index - The index into the buffer attribute.
20084	 * @param {number} y - The value to set.
20085	 * @return {InterleavedBufferAttribute} A reference to this instance.
20086	 */
20087	setY( index, y ) {
20088
20089		if ( this.normalized ) y = normalize( y, this.array );
20090
20091		this.data.array[ index * this.data.stride + this.offset + 1 ] = y;
20092
20093		return this;
20094
20095	}
20096
20097	/**
20098	 * Sets the z component of the vector at the given index.
20099	 *
20100	 * @param {number} index - The index into the buffer attribute.
20101	 * @param {number} z - The value to set.
20102	 * @return {InterleavedBufferAttribute} A reference to this instance.
20103	 */
20104	setZ( index, z ) {
20105
20106		if ( this.normalized ) z = normalize( z, this.array );
20107
20108		this.data.array[ index * this.data.stride + this.offset + 2 ] = z;
20109
20110		return this;
20111
20112	}
20113
20114	/**
20115	 * Sets the w component of the vector at the given index.
20116	 *
20117	 * @param {number} index - The index into the buffer attribute.
20118	 * @param {number} w - The value to set.
20119	 * @return {InterleavedBufferAttribute} A reference to this instance.
20120	 */
20121	setW( index, w ) {
20122
20123		if ( this.normalized ) w = normalize( w, this.array );
20124
20125		this.data.array[ index * this.data.stride + this.offset + 3 ] = w;
20126
20127		return this;
20128
20129	}
20130
20131	/**
20132	 * Returns the x component of the vector at the given index.
20133	 *
20134	 * @param {number} index - The index into the buffer attribute.
20135	 * @return {number} The x component.
20136	 */
20137	getX( index ) {
20138
20139		let x = this.data.array[ index * this.data.stride + this.offset ];
20140
20141		if ( this.normalized ) x = denormalize( x, this.array );
20142
20143		return x;
20144
20145	}
20146
20147	/**
20148	 * Returns the y component of the vector at the given index.
20149	 *
20150	 * @param {number} index - The index into the buffer attribute.
20151	 * @return {number} The y component.
20152	 */
20153	getY( index ) {
20154
20155		let y = this.data.array[ index * this.data.stride + this.offset + 1 ];
20156
20157		if ( this.normalized ) y = denormalize( y, this.array );
20158
20159		return y;
20160
20161	}
20162
20163	/**
20164	 * Returns the z component of the vector at the given index.
20165	 *
20166	 * @param {number} index - The index into the buffer attribute.
20167	 * @return {number} The z component.
20168	 */
20169	getZ( index ) {
20170
20171		let z = this.data.array[ index * this.data.stride + this.offset + 2 ];
20172
20173		if ( this.normalized ) z = denormalize( z, this.array );
20174
20175		return z;
20176
20177	}
20178
20179	/**
20180	 * Returns the w component of the vector at the given index.
20181	 *
20182	 * @param {number} index - The index into the buffer attribute.
20183	 * @return {number} The w component.
20184	 */
20185	getW( index ) {
20186
20187		let w = this.data.array[ index * this.data.stride + this.offset + 3 ];
20188
20189		if ( this.normalized ) w = denormalize( w, this.array );
20190
20191		return w;
20192
20193	}
20194
20195	/**
20196	 * Sets the x and y component of the vector at the given index.
20197	 *
20198	 * @param {number} index - The index into the buffer attribute.
20199	 * @param {number} x - The value for the x component to set.
20200	 * @param {number} y - The value for the y component to set.
20201	 * @return {InterleavedBufferAttribute} A reference to this instance.
20202	 */
20203	setXY( index, x, y ) {
20204
20205		index = index * this.data.stride + this.offset;
20206
20207		if ( this.normalized ) {
20208
20209			x = normalize( x, this.array );
20210			y = normalize( y, this.array );
20211
20212		}
20213
20214		this.data.array[ index + 0 ] = x;
20215		this.data.array[ index + 1 ] = y;
20216
20217		return this;
20218
20219	}
20220
20221	/**
20222	 * Sets the x, y and z component of the vector at the given index.
20223	 *
20224	 * @param {number} index - The index into the buffer attribute.
20225	 * @param {number} x - The value for the x component to set.
20226	 * @param {number} y - The value for the y component to set.
20227	 * @param {number} z - The value for the z component to set.
20228	 * @return {InterleavedBufferAttribute} A reference to this instance.
20229	 */
20230	setXYZ( index, x, y, z ) {
20231
20232		index = index * this.data.stride + this.offset;
20233
20234		if ( this.normalized ) {
20235
20236			x = normalize( x, this.array );
20237			y = normalize( y, this.array );
20238			z = normalize( z, this.array );
20239
20240		}
20241
20242		this.data.array[ index + 0 ] = x;
20243		this.data.array[ index + 1 ] = y;
20244		this.data.array[ index + 2 ] = z;
20245
20246		return this;
20247
20248	}
20249
20250	/**
20251	 * Sets the x, y, z and w component of the vector at the given index.
20252	 *
20253	 * @param {number} index - The index into the buffer attribute.
20254	 * @param {number} x - The value for the x component to set.
20255	 * @param {number} y - The value for the y component to set.
20256	 * @param {number} z - The value for the z component to set.
20257	 * @param {number} w - The value for the w component to set.
20258	 * @return {InterleavedBufferAttribute} A reference to this instance.
20259	 */
20260	setXYZW( index, x, y, z, w ) {
20261
20262		index = index * this.data.stride + this.offset;
20263
20264		if ( this.normalized ) {
20265
20266			x = normalize( x, this.array );
20267			y = normalize( y, this.array );
20268			z = normalize( z, this.array );
20269			w = normalize( w, this.array );
20270
20271		}
20272
20273		this.data.array[ index + 0 ] = x;
20274		this.data.array[ index + 1 ] = y;
20275		this.data.array[ index + 2 ] = z;
20276		this.data.array[ index + 3 ] = w;
20277
20278		return this;
20279
20280	}
20281
20282	/**
20283	 * Returns a new buffer attribute with copied values from this instance.
20284	 *
20285	 * If no parameter is provided, cloning an interleaved buffer attribute will de-interleave buffer data.
20286	 *
20287	 * @param {Object} [data] - An object with interleaved buffers that allows to retain the interleaved property.
20288	 * @return {BufferAttribute|InterleavedBufferAttribute} A clone of this instance.
20289	 */
20290	clone( data ) {
20291
20292		if ( data === undefined ) {
20293
20294			log( 'InterleavedBufferAttribute.clone(): Cloning an interleaved buffer attribute will de-interleave buffer data.' );
20295
20296			const array = [];
20297
20298			for ( let i = 0; i < this.count; i ++ ) {
20299
20300				const index = i * this.data.stride + this.offset;
20301
20302				for ( let j = 0; j < this.itemSize; j ++ ) {
20303
20304					array.push( this.data.array[ index + j ] );
20305
20306				}
20307
20308			}
20309
20310			return new BufferAttribute( new this.array.constructor( array ), this.itemSize, this.normalized );
20311
20312		} else {
20313
20314			if ( data.interleavedBuffers === undefined ) {
20315
20316				data.interleavedBuffers = {};
20317
20318			}
20319
20320			if ( data.interleavedBuffers[ this.data.uuid ] === undefined ) {
20321
20322				data.interleavedBuffers[ this.data.uuid ] = this.data.clone( data );
20323
20324			}
20325
20326			return new InterleavedBufferAttribute( data.interleavedBuffers[ this.data.uuid ], this.itemSize, this.offset, this.normalized );
20327
20328		}
20329
20330	}
20331
20332	/**
20333	 * Serializes the buffer attribute into JSON.
20334	 *
20335	 * If no parameter is provided, cloning an interleaved buffer attribute will de-interleave buffer data.
20336	 *
20337	 * @param {Object} [data] - An optional value holding meta information about the serialization.
20338	 * @return {Object} A JSON object representing the serialized buffer attribute.
20339	 */
20340	toJSON( data ) {
20341
20342		if ( data === undefined ) {
20343
20344			log( 'InterleavedBufferAttribute.toJSON(): Serializing an interleaved buffer attribute will de-interleave buffer data.' );
20345
20346			const array = [];
20347
20348			for ( let i = 0; i < this.count; i ++ ) {
20349
20350				const index = i * this.data.stride + this.offset;
20351
20352				for ( let j = 0; j < this.itemSize; j ++ ) {
20353
20354					array.push( this.data.array[ index + j ] );
20355
20356				}
20357
20358			}
20359
20360			// de-interleave data and save it as an ordinary buffer attribute for now
20361
20362			return {
20363				itemSize: this.itemSize,
20364				type: this.array.constructor.name,
20365				array: array,
20366				normalized: this.normalized
20367			};
20368
20369		} else {
20370
20371			// save as true interleaved attribute
20372
20373			if ( data.interleavedBuffers === undefined ) {
20374
20375				data.interleavedBuffers = {};
20376
20377			}
20378
20379			if ( data.interleavedBuffers[ this.data.uuid ] === undefined ) {
20380
20381				data.interleavedBuffers[ this.data.uuid ] = this.data.toJSON( data );
20382
20383			}
20384
20385			return {
20386				isInterleavedBufferAttribute: true,
20387				itemSize: this.itemSize,
20388				data: this.data.uuid,
20389				offset: this.offset,
20390				normalized: this.normalized
20391			};
20392
20393		}
20394
20395	}
20396
20397}
20398
20399let _materialId = 0;
20400
20401/**
20402 * Abstract base class for materials.
20403 *
20404 * Materials define the appearance of renderable 3D objects.
20405 *
20406 * @abstract
20407 * @augments EventDispatcher
20408 */
vendor: 8,504 bytes, lines 20409-20689
20409class Material extends EventDispatcher {
20410
20411	/**
20412	 * Constructs a new material.
20413	 */
20414	constructor() {
20415
20416		super();
20417
20418		/**
20419		 * This flag can be used for type testing.
20420		 *
20421		 * @type {boolean}
20422		 * @readonly
20423		 * @default true
20424		 */
20425		this.isMaterial = true;
20426
20427		/**
20428		 * The ID of the material.
20429		 *
20430		 * @name Material#id
20431		 * @type {number}
20432		 * @readonly
20433		 */
20434		Object.defineProperty( this, 'id', { value: _materialId ++ } );
20435
20436		/**
20437		 * The UUID of the material.
20438		 *
20439		 * @type {string}
20440		 * @readonly
20441		 */
20442		this.uuid = generateUUID();
20443
20444		/**
20445		 * The name of the material.
20446		 *
20447		 * @type {string}
20448		 */
20449		this.name = '';
20450
20451		/**
20452		 * The type property is used for detecting the object type
20453		 * in context of serialization/deserialization.
20454		 *
20455		 * @type {string}
20456		 * @readonly
20457		 */
20458		this.type = 'Material';
20459
20460		/**
20461		 * Defines the blending type of the material.
20462		 *
20463		 * It must be set to `CustomBlending` if custom blending properties like
20464		 * {@link Material#blendSrc}, {@link Material#blendDst} or {@link Material#blendEquation}
20465		 * should have any effect.
20466		 *
20467		 * @type {(NoBlending|NormalBlending|AdditiveBlending|SubtractiveBlending|MultiplyBlending|CustomBlending)}
20468		 * @default NormalBlending
20469		 */
20470		this.blending = NormalBlending;
20471
20472		/**
20473		 * Defines which side of faces will be rendered - front, back or both.
20474		 *
20475		 * @type {(FrontSide|BackSide|DoubleSide)}
20476		 * @default FrontSide
20477		 */
20478		this.side = FrontSide;
20479
20480		/**
20481		 * If set to `true`, vertex colors should be used.
20482		 *
20483		 * The engine supports RGB and RGBA vertex colors depending on whether a three (RGB) or
20484		 * four (RGBA) component color buffer attribute is used.
20485		 *
20486		 * @type {boolean}
20487		 * @default false
20488		 */
20489		this.vertexColors = false;
20490
20491		/**
20492		 * Defines how transparent the material is.
20493		 * A value of `0.0` indicates fully transparent, `1.0` is fully opaque.
20494		 *
20495		 * If the {@link Material#transparent} is not set to `true`,
20496		 * the material will remain fully opaque and this value will only affect its color.
20497		 *
20498		 * @type {number}
20499		 * @default 1
20500		 */
20501		this.opacity = 1;
20502
20503		/**
20504		 * Defines whether this material is transparent. This has an effect on
20505		 * rendering as transparent objects need special treatment and are rendered
20506		 * after non-transparent objects.
20507		 *
20508		 * When set to true, the extent to which the material is transparent is
20509		 * controlled by {@link Material#opacity}.
20510		 *
20511		 * @type {boolean}
20512		 * @default false
20513		 */
20514		this.transparent = false;
20515
20516		/**
20517		 * Enables alpha hashed transparency, an alternative to {@link Material#transparent} or
20518		 * {@link Material#alphaTest}. The material will not be rendered if opacity is lower than
20519		 * a random threshold. Randomization introduces some grain or noise, but approximates alpha
20520		 * blending without the associated problems of sorting. Using TAA can reduce the resulting noise.
20521		 *
20522		 * @type {boolean}
20523		 * @default false
20524		 */
20525		this.alphaHash = false;
20526
20527		/**
20528		 * Defines the blending source factor.
20529		 *
20530		 * @type {(ZeroFactor|OneFactor|SrcColorFactor|OneMinusSrcColorFactor|SrcAlphaFactor|OneMinusSrcAlphaFactor|DstAlphaFactor|OneMinusDstAlphaFactor|DstColorFactor|OneMinusDstColorFactor|SrcAlphaSaturateFactor|ConstantColorFactor|OneMinusConstantColorFactor|ConstantAlphaFactor|OneMinusConstantAlphaFactor)}
20531		 * @default SrcAlphaFactor
20532		 */
20533		this.blendSrc = SrcAlphaFactor;
20534
20535		/**
20536		 * Defines the blending destination factor.
20537		 *
20538		 * @type {(ZeroFactor|OneFactor|SrcColorFactor|OneMinusSrcColorFactor|SrcAlphaFactor|OneMinusSrcAlphaFactor|DstAlphaFactor|OneMinusDstAlphaFactor|DstColorFactor|OneMinusDstColorFactor|SrcAlphaSaturateFactor|ConstantColorFactor|OneMinusConstantColorFactor|ConstantAlphaFactor|OneMinusConstantAlphaFactor)}
20539		 * @default OneMinusSrcAlphaFactor
20540		 */
20541		this.blendDst = OneMinusSrcAlphaFactor;
20542
20543		/**
20544		 * Defines the blending equation.
20545		 *
20546		 * @type {(AddEquation|SubtractEquation|ReverseSubtractEquation|MinEquation|MaxEquation)}
20547		 * @default AddEquation
20548		 */
20549		this.blendEquation = AddEquation;
20550
20551		/**
20552		 * Defines the blending source alpha factor.
20553		 *
20554		 * @type {?(ZeroFactor|OneFactor|SrcColorFactor|OneMinusSrcColorFactor|SrcAlphaFactor|OneMinusSrcAlphaFactor|DstAlphaFactor|OneMinusDstAlphaFactor|DstColorFactor|OneMinusDstColorFactor|SrcAlphaSaturateFactor|ConstantColorFactor|OneMinusConstantColorFactor|ConstantAlphaFactor|OneMinusConstantAlphaFactor)}
20555		 * @default null
20556		 */
20557		this.blendSrcAlpha = null;
20558
20559		/**
20560		 * Defines the blending destination alpha factor.
20561		 *
20562		 * @type {?(ZeroFactor|OneFactor|SrcColorFactor|OneMinusSrcColorFactor|SrcAlphaFactor|OneMinusSrcAlphaFactor|DstAlphaFactor|OneMinusDstAlphaFactor|DstColorFactor|OneMinusDstColorFactor|SrcAlphaSaturateFactor|ConstantColorFactor|OneMinusConstantColorFactor|ConstantAlphaFactor|OneMinusConstantAlphaFactor)}
20563		 * @default null
20564		 */
20565		this.blendDstAlpha = null;
20566
20567		/**
20568		 * Defines the blending equation of the alpha channel.
20569		 *
20570		 * @type {?(AddEquation|SubtractEquation|ReverseSubtractEquation|MinEquation|MaxEquation)}
20571		 * @default null
20572		 */
20573		this.blendEquationAlpha = null;
20574
20575		/**
20576		 * Represents the RGB values of the constant blend color.
20577		 *
20578		 * This property has only an effect when using custom blending with `ConstantColor` or `OneMinusConstantColor`.
20579		 *
20580		 * @type {Color}
20581		 * @default (0,0,0)
20582		 */
20583		this.blendColor = new Color( 0, 0, 0 );
20584
20585		/**
20586		 * Represents the alpha value of the constant blend color.
20587		 *
20588		 * This property has only an effect when using custom blending with `ConstantAlpha` or `OneMinusConstantAlpha`.
20589		 *
20590		 * @type {number}
20591		 * @default 0
20592		 */
20593		this.blendAlpha = 0;
20594
20595		/**
20596		 * Defines the depth function.
20597		 *
20598		 * @type {(NeverDepth|AlwaysDepth|LessDepth|LessEqualDepth|EqualDepth|GreaterEqualDepth|GreaterDepth|NotEqualDepth)}
20599		 * @default LessEqualDepth
20600		 */
20601		this.depthFunc = LessEqualDepth;
20602
20603		/**
20604		 * Whether to have depth test enabled when rendering this material.
20605		 * When the depth test is disabled, the depth write will also be implicitly disabled.
20606		 *
20607		 * @type {boolean}
20608		 * @default true
20609		 */
20610		this.depthTest = true;
20611
20612		/**
20613		 * Whether rendering this material has any effect on the depth buffer.
20614		 *
20615		 * When drawing 2D overlays it can be useful to disable the depth writing in
20616		 * order to layer several things together without creating z-index artifacts.
20617		 *
20618		 * @type {boolean}
20619		 * @default true
20620		 */
20621		this.depthWrite = true;
20622
20623		/**
20624		 * The bit mask to use when writing to the stencil buffer.
20625		 *
20626		 * @type {number}
20627		 * @default 0xff
20628		 */
20629		this.stencilWriteMask = 0xff;
20630
20631		/**
20632		 * The stencil comparison function to use.
20633		 *
20634		 * @type {NeverStencilFunc|LessStencilFunc|EqualStencilFunc|LessEqualStencilFunc|GreaterStencilFunc|NotEqualStencilFunc|GreaterEqualStencilFunc|AlwaysStencilFunc}
20635		 * @default AlwaysStencilFunc
20636		 */
20637		this.stencilFunc = AlwaysStencilFunc;
20638
20639		/**
20640		 * The value to use when performing stencil comparisons or stencil operations.
20641		 *
20642		 * @type {number}
20643		 * @default 0
20644		 */
20645		this.stencilRef = 0;
20646
20647		/**
20648		 * The bit mask to use when comparing against the stencil buffer.
20649		 *
20650		 * @type {number}
20651		 * @default 0xff
20652		 */
20653		this.stencilFuncMask = 0xff;
20654
20655		/**
20656		 * Which stencil operation to perform when the comparison function returns `false`.
20657		 *
20658		 * @type {ZeroStencilOp|KeepStencilOp|ReplaceStencilOp|IncrementStencilOp|DecrementStencilOp|IncrementWrapStencilOp|DecrementWrapStencilOp|InvertStencilOp}
20659		 * @default KeepStencilOp
20660		 */
20661		this.stencilFail = KeepStencilOp;
20662
20663		/**
20664		 * Which stencil operation to perform when the comparison function returns
20665		 * `true` but the depth test fails.
20666		 *
20667		 * @type {ZeroStencilOp|KeepStencilOp|ReplaceStencilOp|IncrementStencilOp|DecrementStencilOp|IncrementWrapStencilOp|DecrementWrapStencilOp|InvertStencilOp}
20668		 * @default KeepStencilOp
20669		 */
20670		this.stencilZFail = KeepStencilOp;
20671
20672		/**
20673		 * Which stencil operation to perform when the comparison function returns
20674		 * `true` and the depth test passes.
20675		 *
20676		 * @type {ZeroStencilOp|KeepStencilOp|ReplaceStencilOp|IncrementStencilOp|DecrementStencilOp|IncrementWrapStencilOp|DecrementWrapStencilOp|InvertStencilOp}
20677		 * @default KeepStencilOp
20678		 */
20679		this.stencilZPass = KeepStencilOp;
20680
20681		/**
20682		 * Whether stencil operations are performed against the stencil buffer. In
20683		 * order to perform writes or comparisons against the stencil buffer this
20684		 * value must be `true`.
20685		 *
20686		 * @type {boolean}
20687		 * @default false
20688		 */
20689		this.stencilWrite = false;
vendor: 5,079 bytes, lines 20690-20870
20690
20691		/**
20692		 * User-defined clipping planes specified as THREE.Plane objects in world
20693		 * space. These planes apply to the objects this material is attached to.
20694		 * Points in space whose signed distance to the plane is negative are clipped
20695		 * (not rendered). This requires {@link WebGLRenderer#localClippingEnabled} to
20696		 * be `true`.
20697		 *
20698		 * @type {?Array<Plane>}
20699		 * @default null
20700		 */
20701		this.clippingPlanes = null;
20702
20703		/**
20704		 * Changes the behavior of clipping planes so that only their intersection is
20705		 * clipped, rather than their union.
20706		 *
20707		 * @type {boolean}
20708		 * @default false
20709		 */
20710		this.clipIntersection = false;
20711
20712		/**
20713		 * Defines whether to clip shadows according to the clipping planes specified
20714		 * on this material.
20715		 *
20716		 * @type {boolean}
20717		 * @default false
20718		 */
20719		this.clipShadows = false;
20720
20721		/**
20722		 * Defines which side of faces cast shadows. If `null`, the side casting shadows
20723		 * is determined as follows:
20724		 *
20725		 * - When {@link Material#side} is set to `FrontSide`, the back side cast shadows.
20726		 * - When {@link Material#side} is set to `BackSide`, the front side cast shadows.
20727		 * - When {@link Material#side} is set to `DoubleSide`, both sides cast shadows.
20728		 *
20729		 * @type {?(FrontSide|BackSide|DoubleSide)}
20730		 * @default null
20731		 */
20732		this.shadowSide = null;
20733
20734		/**
20735		 * Whether to render the material's color.
20736		 *
20737		 * This can be used in conjunction with {@link Object3D#renderOder} to create invisible
20738		 * objects that occlude other objects.
20739		 *
20740		 * @type {boolean}
20741		 * @default true
20742		 */
20743		this.colorWrite = true;
20744
20745		/**
20746		 * Override the renderer's default precision for this material.
20747		 *
20748		 * @type {?('highp'|'mediump'|'lowp')}
20749		 * @default null
20750		 */
20751		this.precision = null;
20752
20753		/**
20754		 * Whether to use polygon offset or not. When enabled, each fragment's depth value will
20755		 * be offset after it is interpolated from the depth values of the appropriate vertices.
20756		 * The offset is added before the depth test is performed and before the value is written
20757		 * into the depth buffer.
20758		 *
20759		 * Can be useful for rendering hidden-line images, for applying decals to surfaces, and for
20760		 * rendering solids with highlighted edges.
20761		 *
20762		 * @type {boolean}
20763		 * @default false
20764		 */
20765		this.polygonOffset = false;
20766
20767		/**
20768		 * Specifies a scale factor that is used to create a variable depth offset for each polygon.
20769		 *
20770		 * @type {number}
20771		 * @default 0
20772		 */
20773		this.polygonOffsetFactor = 0;
20774
20775		/**
20776		 * Is multiplied by an implementation-specific value to create a constant depth offset.
20777		 *
20778		 * @type {number}
20779		 * @default 0
20780		 */
20781		this.polygonOffsetUnits = 0;
20782
20783		/**
20784		 * Whether to apply dithering to the color to remove the appearance of banding.
20785		 *
20786		 * @type {boolean}
20787		 * @default false
20788		 */
20789		this.dithering = false;
20790
20791		/**
20792		 * Whether alpha to coverage should be enabled or not. Can only be used with MSAA-enabled contexts
20793		 * (meaning when the renderer was created with *antialias* parameter set to `true`). Enabling this
20794		 * will smooth aliasing on clip plane edges and alphaTest-clipped edges.
20795		 *
20796		 * @type {boolean}
20797		 * @default false
20798		 */
20799		this.alphaToCoverage = false;
20800
20801		/**
20802		 * Whether to premultiply the alpha (transparency) value.
20803		 *
20804		 * @type {boolean}
20805		 * @default false
20806		 */
20807		this.premultipliedAlpha = false;
20808
20809		/**
20810		 * Whether double-sided, transparent objects should be rendered with a single pass or not.
20811		 *
20812		 * The engine renders double-sided, transparent objects with two draw calls (back faces first,
20813		 * then front faces) to mitigate transparency artifacts. There are scenarios however where this
20814		 * approach produces no quality gains but still doubles draw calls e.g. when rendering flat
20815		 * vegetation like grass sprites. In these cases, set the `forceSinglePass` flag to `true` to
20816		 * disable the two pass rendering to avoid performance issues.
20817		 *
20818		 * @type {boolean}
20819		 * @default false
20820		 */
20821		this.forceSinglePass = false;
20822
20823		/**
20824		 * Whether it's possible to override the material with {@link Scene#overrideMaterial} or not.
20825		 *
20826		 * @type {boolean}
20827		 * @default true
20828		 */
20829		this.allowOverride = true;
20830
20831		/**
20832		 * Defines whether 3D objects using this material are visible.
20833		 *
20834		 * @type {boolean}
20835		 * @default true
20836		 */
20837		this.visible = true;
20838
20839		/**
20840		 * Defines whether this material is tone mapped according to the renderer's tone mapping setting.
20841		 *
20842		 * It is ignored when rendering to a render target or using post processing or when using
20843		 * `WebGPURenderer`. In all these cases, all materials are honored by tone mapping.
20844		 *
20845		 * @type {boolean}
20846		 * @default true
20847		 */
20848		this.toneMapped = true;
20849
20850		/**
20851		 * An object that can be used to store custom data about the Material. It
20852		 * should not hold references to functions as these will not be cloned.
20853		 *
20854		 * @type {Object}
20855		 */
20856		this.userData = {};
20857
20858		/**
20859		 * This starts at `0` and counts how many times {@link Material#needsUpdate} is set to `true`.
20860		 *
20861		 * @type {number}
20862		 * @readonly
20863		 * @default 0
20864		 */
20865		this.version = 0;
20866
20867		this._alphaTest = 0;
20868
20869	}
20870
vendor: 17,626 bytes, lines 20871-21407
20871	/**
20872	 * Sets the alpha value to be used when running an alpha test. The material
20873	 * will not be rendered if the opacity is lower than this value.
20874	 *
20875	 * @type {number}
20876	 * @readonly
20877	 * @default 0
20878	 */
20879	get alphaTest() {
20880
20881		return this._alphaTest;
20882
20883	}
20884
20885	set alphaTest( value ) {
20886
20887		if ( this._alphaTest > 0 !== value > 0 ) {
20888
20889			this.version ++;
20890
20891		}
20892
20893		this._alphaTest = value;
20894
20895	}
20896
20897	/**
20898	 * An optional callback that is executed immediately before the material is used to render a 3D object.
20899	 *
20900	 * This method can only be used when rendering with {@link WebGLRenderer}.
20901	 *
20902	 * @param {WebGLRenderer} renderer - The renderer.
20903	 * @param {Scene} scene - The scene.
20904	 * @param {Camera} camera - The camera that is used to render the scene.
20905	 * @param {BufferGeometry} geometry - The 3D object's geometry.
20906	 * @param {Object3D} object - The 3D object.
20907	 * @param {Object} group - The geometry group data.
20908	 */
20909	onBeforeRender( /* renderer, scene, camera, geometry, object, group */ ) {}
20910
20911	/**
20912	 * An optional callback that is executed immediately before the shader
20913	 * program is compiled. This function is called with the shader source code
20914	 * as a parameter. Useful for the modification of built-in materials.
20915	 *
20916	 * This method can only be used when rendering with {@link WebGLRenderer}. The
20917	 * recommended approach when customizing materials is to use `WebGPURenderer` with the new
20918	 * Node Material system and [TSL](https://github.com/mrdoob/three.js/wiki/Three.js-Shading-Language).
20919	 *
20920	 * @param {{vertexShader:string,fragmentShader:string,uniforms:Object}} shaderobject - The object holds the uniforms and the vertex and fragment shader source.
20921	 * @param {WebGLRenderer} renderer - A reference to the renderer.
20922	 */
20923	onBeforeCompile( /* shaderobject, renderer */ ) {}
20924
20925	/**
20926	 * In case {@link Material#onBeforeCompile} is used, this callback can be used to identify
20927	 * values of settings used in `onBeforeCompile()`, so three.js can reuse a cached
20928	 * shader or recompile the shader for this material as needed.
20929	 *
20930	 * This method can only be used when rendering with {@link WebGLRenderer}.
20931	 *
20932	 * @return {string} The custom program cache key.
20933	 */
20934	customProgramCacheKey() {
20935
20936		return this.onBeforeCompile.toString();
20937
20938	}
20939
20940	/**
20941	 * This method can be used to set default values from parameter objects.
20942	 * It is a generic implementation so it can be used with different types
20943	 * of materials.
20944	 *
20945	 * @param {Object} [values] - The material values to set.
20946	 */
20947	setValues( values ) {
20948
20949		if ( values === undefined ) return;
20950
20951		for ( const key in values ) {
20952
20953			const newValue = values[ key ];
20954
20955			if ( newValue === undefined ) {
20956
20957				warn( `Material: parameter '${ key }' has value of undefined.` );
20958				continue;
20959
20960			}
20961
20962			const currentValue = this[ key ];
20963
20964			if ( currentValue === undefined ) {
20965
20966				warn( `Material: '${ key }' is not a property of THREE.${ this.type }.` );
20967				continue;
20968
20969			}
20970
20971			if ( currentValue && currentValue.isColor ) {
20972
20973				currentValue.set( newValue );
20974
20975			} else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) {
20976
20977				currentValue.copy( newValue );
20978
20979			} else {
20980
20981				this[ key ] = newValue;
20982
20983			}
20984
20985		}
20986
20987	}
20988
20989	/**
20990	 * Serializes the material into JSON.
20991	 *
20992	 * @param {?(Object|string)} meta - An optional value holding meta information about the serialization.
20993	 * @return {Object} A JSON object representing the serialized material.
20994	 * @see {@link ObjectLoader#parse}
20995	 */
20996	toJSON( meta ) {
20997
20998		const isRootObject = ( meta === undefined || typeof meta === 'string' );
20999
21000		if ( isRootObject ) {
21001
21002			meta = {
21003				textures: {},
21004				images: {}
21005			};
21006
21007		}
21008
21009		const data = {
21010			metadata: {
21011				version: 4.7,
21012				type: 'Material',
21013				generator: 'Material.toJSON'
21014			}
21015		};
21016
21017		// standard Material serialization
21018		data.uuid = this.uuid;
21019		data.type = this.type;
21020
21021		if ( this.name !== '' ) data.name = this.name;
21022
21023		if ( this.color && this.color.isColor ) data.color = this.color.getHex();
21024
21025		if ( this.roughness !== undefined ) data.roughness = this.roughness;
21026		if ( this.metalness !== undefined ) data.metalness = this.metalness;
21027
21028		if ( this.sheen !== undefined ) data.sheen = this.sheen;
21029		if ( this.sheenColor && this.sheenColor.isColor ) data.sheenColor = this.sheenColor.getHex();
21030		if ( this.sheenRoughness !== undefined ) data.sheenRoughness = this.sheenRoughness;
21031		if ( this.emissive && this.emissive.isColor ) data.emissive = this.emissive.getHex();
21032		if ( this.emissiveIntensity !== undefined && this.emissiveIntensity !== 1 ) data.emissiveIntensity = this.emissiveIntensity;
21033
21034		if ( this.specular && this.specular.isColor ) data.specular = this.specular.getHex();
21035		if ( this.specularIntensity !== undefined ) data.specularIntensity = this.specularIntensity;
21036		if ( this.specularColor && this.specularColor.isColor ) data.specularColor = this.specularColor.getHex();
21037		if ( this.shininess !== undefined ) data.shininess = this.shininess;
21038		if ( this.clearcoat !== undefined ) data.clearcoat = this.clearcoat;
21039		if ( this.clearcoatRoughness !== undefined ) data.clearcoatRoughness = this.clearcoatRoughness;
21040
21041		if ( this.clearcoatMap && this.clearcoatMap.isTexture ) {
21042
21043			data.clearcoatMap = this.clearcoatMap.toJSON( meta ).uuid;
21044
21045		}
21046
21047		if ( this.clearcoatRoughnessMap && this.clearcoatRoughnessMap.isTexture ) {
21048
21049			data.clearcoatRoughnessMap = this.clearcoatRoughnessMap.toJSON( meta ).uuid;
21050
21051		}
21052
21053		if ( this.clearcoatNormalMap && this.clearcoatNormalMap.isTexture ) {
21054
21055			data.clearcoatNormalMap = this.clearcoatNormalMap.toJSON( meta ).uuid;
21056			data.clearcoatNormalScale = this.clearcoatNormalScale.toArray();
21057
21058		}
21059
21060		if ( this.sheenColorMap && this.sheenColorMap.isTexture ) {
21061
21062			data.sheenColorMap = this.sheenColorMap.toJSON( meta ).uuid;
21063
21064		}
21065
21066		if ( this.sheenRoughnessMap && this.sheenRoughnessMap.isTexture ) {
21067
21068			data.sheenRoughnessMap = this.sheenRoughnessMap.toJSON( meta ).uuid;
21069
21070		}
21071
21072		if ( this.dispersion !== undefined ) data.dispersion = this.dispersion;
21073
21074		if ( this.iridescence !== undefined ) data.iridescence = this.iridescence;
21075		if ( this.iridescenceIOR !== undefined ) data.iridescenceIOR = this.iridescenceIOR;
21076		if ( this.iridescenceThicknessRange !== undefined ) data.iridescenceThicknessRange = this.iridescenceThicknessRange;
21077
21078		if ( this.iridescenceMap && this.iridescenceMap.isTexture ) {
21079
21080			data.iridescenceMap = this.iridescenceMap.toJSON( meta ).uuid;
21081
21082		}
21083
21084		if ( this.iridescenceThicknessMap && this.iridescenceThicknessMap.isTexture ) {
21085
21086			data.iridescenceThicknessMap = this.iridescenceThicknessMap.toJSON( meta ).uuid;
21087
21088		}
21089
21090		if ( this.anisotropy !== undefined ) data.anisotropy = this.anisotropy;
21091		if ( this.anisotropyRotation !== undefined ) data.anisotropyRotation = this.anisotropyRotation;
21092
21093		if ( this.anisotropyMap && this.anisotropyMap.isTexture ) {
21094
21095			data.anisotropyMap = this.anisotropyMap.toJSON( meta ).uuid;
21096
21097		}
21098
21099		if ( this.map && this.map.isTexture ) data.map = this.map.toJSON( meta ).uuid;
21100		if ( this.matcap && this.matcap.isTexture ) data.matcap = this.matcap.toJSON( meta ).uuid;
21101		if ( this.alphaMap && this.alphaMap.isTexture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid;
21102
21103		if ( this.lightMap && this.lightMap.isTexture ) {
21104
21105			data.lightMap = this.lightMap.toJSON( meta ).uuid;
21106			data.lightMapIntensity = this.lightMapIntensity;
21107
21108		}
21109
21110		if ( this.aoMap && this.aoMap.isTexture ) {
21111
21112			data.aoMap = this.aoMap.toJSON( meta ).uuid;
21113			data.aoMapIntensity = this.aoMapIntensity;
21114
21115		}
21116
21117		if ( this.bumpMap && this.bumpMap.isTexture ) {
21118
21119			data.bumpMap = this.bumpMap.toJSON( meta ).uuid;
21120			data.bumpScale = this.bumpScale;
21121
21122		}
21123
21124		if ( this.normalMap && this.normalMap.isTexture ) {
21125
21126			data.normalMap = this.normalMap.toJSON( meta ).uuid;
21127			data.normalMapType = this.normalMapType;
21128			data.normalScale = this.normalScale.toArray();
21129
21130		}
21131
21132		if ( this.displacementMap && this.displacementMap.isTexture ) {
21133
21134			data.displacementMap = this.displacementMap.toJSON( meta ).uuid;
21135			data.displacementScale = this.displacementScale;
21136			data.displacementBias = this.displacementBias;
21137
21138		}
21139
21140		if ( this.roughnessMap && this.roughnessMap.isTexture ) data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid;
21141		if ( this.metalnessMap && this.metalnessMap.isTexture ) data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid;
21142
21143		if ( this.emissiveMap && this.emissiveMap.isTexture ) data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid;
21144		if ( this.specularMap && this.specularMap.isTexture ) data.specularMap = this.specularMap.toJSON( meta ).uuid;
21145		if ( this.specularIntensityMap && this.specularIntensityMap.isTexture ) data.specularIntensityMap = this.specularIntensityMap.toJSON( meta ).uuid;
21146		if ( this.specularColorMap && this.specularColorMap.isTexture ) data.specularColorMap = this.specularColorMap.toJSON( meta ).uuid;
21147
21148		if ( this.envMap && this.envMap.isTexture ) {
21149
21150			data.envMap = this.envMap.toJSON( meta ).uuid;
21151
21152			if ( this.combine !== undefined ) data.combine = this.combine;
21153
21154		}
21155
21156		if ( this.envMapRotation !== undefined ) data.envMapRotation = this.envMapRotation.toArray();
21157		if ( this.envMapIntensity !== undefined ) data.envMapIntensity = this.envMapIntensity;
21158		if ( this.reflectivity !== undefined ) data.reflectivity = this.reflectivity;
21159		if ( this.refractionRatio !== undefined ) data.refractionRatio = this.refractionRatio;
21160
21161		if ( this.gradientMap && this.gradientMap.isTexture ) {
21162
21163			data.gradientMap = this.gradientMap.toJSON( meta ).uuid;
21164
21165		}
21166
21167		if ( this.transmission !== undefined ) data.transmission = this.transmission;
21168		if ( this.transmissionMap && this.transmissionMap.isTexture ) data.transmissionMap = this.transmissionMap.toJSON( meta ).uuid;
21169		if ( this.thickness !== undefined ) data.thickness = this.thickness;
21170		if ( this.thicknessMap && this.thicknessMap.isTexture ) data.thicknessMap = this.thicknessMap.toJSON( meta ).uuid;
21171		if ( this.attenuationDistance !== undefined && this.attenuationDistance !== Infinity ) data.attenuationDistance = this.attenuationDistance;
21172		if ( this.attenuationColor !== undefined ) data.attenuationColor = this.attenuationColor.getHex();
21173
21174		if ( this.size !== undefined ) data.size = this.size;
21175		if ( this.shadowSide !== null ) data.shadowSide = this.shadowSide;
21176		if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation;
21177
21178		if ( this.blending !== NormalBlending ) data.blending = this.blending;
21179		if ( this.side !== FrontSide ) data.side = this.side;
21180		if ( this.vertexColors === true ) data.vertexColors = true;
21181
21182		if ( this.opacity < 1 ) data.opacity = this.opacity;
21183		if ( this.transparent === true ) data.transparent = true;
21184
21185		if ( this.blendSrc !== SrcAlphaFactor ) data.blendSrc = this.blendSrc;
21186		if ( this.blendDst !== OneMinusSrcAlphaFactor ) data.blendDst = this.blendDst;
21187		if ( this.blendEquation !== AddEquation ) data.blendEquation = this.blendEquation;
21188		if ( this.blendSrcAlpha !== null ) data.blendSrcAlpha = this.blendSrcAlpha;
21189		if ( this.blendDstAlpha !== null ) data.blendDstAlpha = this.blendDstAlpha;
21190		if ( this.blendEquationAlpha !== null ) data.blendEquationAlpha = this.blendEquationAlpha;
21191		if ( this.blendColor && this.blendColor.isColor ) data.blendColor = this.blendColor.getHex();
21192		if ( this.blendAlpha !== 0 ) data.blendAlpha = this.blendAlpha;
21193
21194		if ( this.depthFunc !== LessEqualDepth ) data.depthFunc = this.depthFunc;
21195		if ( this.depthTest === false ) data.depthTest = this.depthTest;
21196		if ( this.depthWrite === false ) data.depthWrite = this.depthWrite;
21197		if ( this.colorWrite === false ) data.colorWrite = this.colorWrite;
21198
21199		if ( this.stencilWriteMask !== 0xff ) data.stencilWriteMask = this.stencilWriteMask;
21200		if ( this.stencilFunc !== AlwaysStencilFunc ) data.stencilFunc = this.stencilFunc;
21201		if ( this.stencilRef !== 0 ) data.stencilRef = this.stencilRef;
21202		if ( this.stencilFuncMask !== 0xff ) data.stencilFuncMask = this.stencilFuncMask;
21203		if ( this.stencilFail !== KeepStencilOp ) data.stencilFail = this.stencilFail;
21204		if ( this.stencilZFail !== KeepStencilOp ) data.stencilZFail = this.stencilZFail;
21205		if ( this.stencilZPass !== KeepStencilOp ) data.stencilZPass = this.stencilZPass;
21206		if ( this.stencilWrite === true ) data.stencilWrite = this.stencilWrite;
21207
21208		// rotation (SpriteMaterial)
21209		if ( this.rotation !== undefined && this.rotation !== 0 ) data.rotation = this.rotation;
21210
21211		if ( this.polygonOffset === true ) data.polygonOffset = true;
21212		if ( this.polygonOffsetFactor !== 0 ) data.polygonOffsetFactor = this.polygonOffsetFactor;
21213		if ( this.polygonOffsetUnits !== 0 ) data.polygonOffsetUnits = this.polygonOffsetUnits;
21214
21215		if ( this.linewidth !== undefined && this.linewidth !== 1 ) data.linewidth = this.linewidth;
21216		if ( this.dashSize !== undefined ) data.dashSize = this.dashSize;
21217		if ( this.gapSize !== undefined ) data.gapSize = this.gapSize;
21218		if ( this.scale !== undefined ) data.scale = this.scale;
21219
21220		if ( this.dithering === true ) data.dithering = true;
21221
21222		if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest;
21223		if ( this.alphaHash === true ) data.alphaHash = true;
21224		if ( this.alphaToCoverage === true ) data.alphaToCoverage = true;
21225		if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = true;
21226		if ( this.forceSinglePass === true ) data.forceSinglePass = true;
21227		if ( this.allowOverride === false ) data.allowOverride = false;
21228
21229		if ( this.wireframe === true ) data.wireframe = true;
21230		if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth;
21231		if ( this.wireframeLinecap !== 'round' ) data.wireframeLinecap = this.wireframeLinecap;
21232		if ( this.wireframeLinejoin !== 'round' ) data.wireframeLinejoin = this.wireframeLinejoin;
21233
21234		if ( this.flatShading === true ) data.flatShading = true;
21235
21236		if ( this.visible === false ) data.visible = false;
21237
21238		if ( this.toneMapped === false ) data.toneMapped = false;
21239
21240		if ( this.fog === false ) data.fog = false;
21241
21242		if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData;
21243
21244		// TODO: Copied from Object3D.toJSON
21245
21246		function extractFromCache( cache ) {
21247
21248			const values = [];
21249
21250			for ( const key in cache ) {
21251
21252				const data = cache[ key ];
21253				delete data.metadata;
21254				values.push( data );
21255
21256			}
21257
21258			return values;
21259
21260		}
21261
21262		if ( isRootObject ) {
21263
21264			const textures = extractFromCache( meta.textures );
21265			const images = extractFromCache( meta.images );
21266
21267			if ( textures.length > 0 ) data.textures = textures;
21268			if ( images.length > 0 ) data.images = images;
21269
21270		}
21271
21272		return data;
21273
21274	}
21275
21276	/**
21277	 * Returns a new material with copied values from this instance.
21278	 *
21279	 * @return {Material} A clone of this instance.
21280	 */
21281	clone() {
21282
21283		return new this.constructor().copy( this );
21284
21285	}
21286
21287	/**
21288	 * Copies the values of the given material to this instance.
21289	 *
21290	 * @param {Material} source - The material to copy.
21291	 * @return {Material} A reference to this instance.
21292	 */
21293	copy( source ) {
21294
21295		this.name = source.name;
21296
21297		this.blending = source.blending;
21298		this.side = source.side;
21299		this.vertexColors = source.vertexColors;
21300
21301		this.opacity = source.opacity;
21302		this.transparent = source.transparent;
21303
21304		this.blendSrc = source.blendSrc;
21305		this.blendDst = source.blendDst;
21306		this.blendEquation = source.blendEquation;
21307		this.blendSrcAlpha = source.blendSrcAlpha;
21308		this.blendDstAlpha = source.blendDstAlpha;
21309		this.blendEquationAlpha = source.blendEquationAlpha;
21310		this.blendColor.copy( source.blendColor );
21311		this.blendAlpha = source.blendAlpha;
21312
21313		this.depthFunc = source.depthFunc;
21314		this.depthTest = source.depthTest;
21315		this.depthWrite = source.depthWrite;
21316
21317		this.stencilWriteMask = source.stencilWriteMask;
21318		this.stencilFunc = source.stencilFunc;
21319		this.stencilRef = source.stencilRef;
21320		this.stencilFuncMask = source.stencilFuncMask;
21321		this.stencilFail = source.stencilFail;
21322		this.stencilZFail = source.stencilZFail;
21323		this.stencilZPass = source.stencilZPass;
21324		this.stencilWrite = source.stencilWrite;
21325
21326		const srcPlanes = source.clippingPlanes;
21327		let dstPlanes = null;
21328
21329		if ( srcPlanes !== null ) {
21330
21331			const n = srcPlanes.length;
21332			dstPlanes = new Array( n );
21333
21334			for ( let i = 0; i !== n; ++ i ) {
21335
21336				dstPlanes[ i ] = srcPlanes[ i ].clone();
21337
21338			}
21339
21340		}
21341
21342		this.clippingPlanes = dstPlanes;
21343		this.clipIntersection = source.clipIntersection;
21344		this.clipShadows = source.clipShadows;
21345
21346		this.shadowSide = source.shadowSide;
21347
21348		this.colorWrite = source.colorWrite;
21349
21350		this.precision = source.precision;
21351
21352		this.polygonOffset = source.polygonOffset;
21353		this.polygonOffsetFactor = source.polygonOffsetFactor;
21354		this.polygonOffsetUnits = source.polygonOffsetUnits;
21355
21356		this.dithering = source.dithering;
21357
21358		this.alphaTest = source.alphaTest;
21359		this.alphaHash = source.alphaHash;
21360		this.alphaToCoverage = source.alphaToCoverage;
21361		this.premultipliedAlpha = source.premultipliedAlpha;
21362		this.forceSinglePass = source.forceSinglePass;
21363		this.allowOverride = source.allowOverride;
21364
21365		this.visible = source.visible;
21366
21367		this.toneMapped = source.toneMapped;
21368
21369		this.userData = JSON.parse( JSON.stringify( source.userData ) );
21370
21371		return this;
21372
21373	}
21374
21375	/**
21376	 * Frees the GPU-related resources allocated by this instance. Call this
21377	 * method whenever this instance is no longer used in your app.
21378	 *
21379	 * @fires Material#dispose
21380	 */
21381	dispose() {
21382
21383		/**
21384		 * Fires when the material has been disposed of.
21385		 *
21386		 * @event Material#dispose
21387		 * @type {Object}
21388		 */
21389		this.dispatchEvent( { type: 'dispose' } );
21390
21391	}
21392
21393	/**
21394	 * Setting this property to `true` indicates the engine the material
21395	 * needs to be recompiled.
21396	 *
21397	 * @type {boolean}
21398	 * @default false
21399	 * @param {boolean} value
21400	 */
21401	set needsUpdate( value ) {
21402
21403		if ( value === true ) this.version ++;
21404
21405	}
21406
21407}
21407
21408
21409/**
21410 * A material for rendering instances of {@link Sprite}.
21411 *
21412 * ```js
21413 * const map = new THREE.TextureLoader().load( 'textures/sprite.png' );
21414 * const material = new THREE.SpriteMaterial( { map: map, color: 0xffffff } );
21415 *
21416 * const sprite = new THREE.Sprite( material );
21417 * sprite.scale.set(200, 200, 1)
21418 * scene.add( sprite );
21419 * ```
21420 *
21421 * @augments Material
21422 */
21423class SpriteMaterial extends Material {
21424
21425	/**
21426	 * Constructs a new sprite material.
21427	 *
21428	 * @param {Object} [parameters] - An object with one or more properties
21429	 * defining the material's appearance. Any property of the material
21430	 * (including any property from inherited materials) can be passed
21431	 * in here. Color values can be passed any type of value accepted
21432	 * by {@link Color#set}.
21433	 */
21434	constructor( parameters ) {
21435
21436		super();
21437
21438		/**
21439		 * This flag can be used for type testing.
21440		 *
21441		 * @type {boolean}
21442		 * @readonly
21443		 * @default true
21444		 */
21445		this.isSpriteMaterial = true;
21446
21447		this.type = 'SpriteMaterial';
21448
21449		/**
21450		 * Color of the material.
21451		 *
21452		 * @type {Color}
21453		 * @default (1,1,1)
21454		 */
21455		this.color = new Color( 0xffffff );
21456
21457		/**
21458		 * The color map. May optionally include an alpha channel, typically combined
21459		 * with {@link Material#transparent} or {@link Material#alphaTest}. The texture map
21460		 * color is modulated by the diffuse `color`.
21461		 *
21462		 * @type {?Texture}
21463		 * @default null
21464		 */
21465		this.map = null;
21466
21467		/**
21468		 * The alpha map is a grayscale texture that controls the opacity across the
21469		 * surface (black: fully transparent; white: fully opaque).
21470		 *
21471		 * Only the color of the texture is used, ignoring the alpha channel if one
21472		 * exists. For RGB and RGBA textures, the renderer will use the green channel
21473		 * when sampling this texture due to the extra bit of precision provided for
21474		 * green in DXT-compressed and uncompressed RGB 565 formats. Luminance-only and
21475		 * luminance/alpha textures will also still work as expected.
21476		 *
21477		 * @type {?Texture}
21478		 * @default null
21479		 */
21480		this.alphaMap = null;
21481
21482		/**
21483		 * The rotation of the sprite in radians.
21484		 *
21485		 * @type {number}
21486		 * @default 0
21487		 */
21488		this.rotation = 0;
21489
21490		/**
21491		 * Specifies whether size of the sprite is attenuated by the camera depth (perspective camera only).
21492		 *
21493		 * @type {boolean}
21494		 * @default true
21495		 */
21496		this.sizeAttenuation = true;
21497
21498		/**
21499		 * Overwritten since sprite materials are transparent
21500		 * by default.
21501		 *
21502		 * @type {boolean}
21503		 * @default true
21504		 */
21505		this.transparent = true;
21506
21507		/**
21508		 * Whether the material is affected by fog or not.
21509		 *
21510		 * @type {boolean}
21511		 * @default true
21512		 */
21513		this.fog = true;
21514
21515		this.setValues( parameters );
21516
21517	}
21518
21519	copy( source ) {
21520
21521		super.copy( source );
21522
21523		this.color.copy( source.color );
21524
21525		this.map = source.map;
21526
21527		this.alphaMap = source.alphaMap;
21528
21529		this.rotation = source.rotation;
21530
21531		this.sizeAttenuation = source.sizeAttenuation;
21532
vendor: 2,777 bytes, lines 21533-21648
21533		this.fog = source.fog;
21534
21535		return this;
21536
21537	}
21538
21539}
21540
21541let _geometry;
21542
21543const _intersectPoint = /*@__PURE__*/ new Vector3();
21544const _worldScale = /*@__PURE__*/ new Vector3();
21545const _mvPosition = /*@__PURE__*/ new Vector3();
21546
21547const _alignedPosition = /*@__PURE__*/ new Vector2();
21548const _rotatedPosition = /*@__PURE__*/ new Vector2();
21549const _viewWorldMatrix = /*@__PURE__*/ new Matrix4();
21550
21551const _vA$1 = /*@__PURE__*/ new Vector3();
21552const _vB$1 = /*@__PURE__*/ new Vector3();
21553const _vC$1 = /*@__PURE__*/ new Vector3();
21554
21555const _uvA = /*@__PURE__*/ new Vector2();
21556const _uvB = /*@__PURE__*/ new Vector2();
21557const _uvC = /*@__PURE__*/ new Vector2();
21558
21559/**
21560 * A sprite is a plane that always faces towards the camera, generally with a
21561 * partially transparent texture applied.
21562 *
21563 * Sprites do not cast shadows, setting {@link Object3D#castShadow} to `true` will
21564 * have no effect.
21565 *
21566 * ```js
21567 * const map = new THREE.TextureLoader().load( 'sprite.png' );
21568 * const material = new THREE.SpriteMaterial( { map: map } );
21569 *
21570 * const sprite = new THREE.Sprite( material );
21571 * scene.add( sprite );
21572 * ```
21573 *
21574 * @augments Object3D
21575 */
21576class Sprite extends Object3D {
21577
21578	/**
21579	 * Constructs a new sprite.
21580	 *
21581	 * @param {(SpriteMaterial|SpriteNodeMaterial)} [material] - The sprite material.
21582	 */
21583	constructor( material = new SpriteMaterial() ) {
21584
21585		super();
21586
21587		/**
21588		 * This flag can be used for type testing.
21589		 *
21590		 * @type {boolean}
21591		 * @readonly
21592		 * @default true
21593		 */
21594		this.isSprite = true;
21595
21596		this.type = 'Sprite';
21597
21598		if ( _geometry === undefined ) {
21599
21600			_geometry = new BufferGeometry();
21601
21602			const float32Array = new Float32Array( [
21603				-0.5, -0.5, 0, 0, 0,
21604				0.5, -0.5, 0, 1, 0,
21605				0.5, 0.5, 0, 1, 1,
21606				-0.5, 0.5, 0, 0, 1
21607			] );
21608
21609			const interleavedBuffer = new InterleavedBuffer( float32Array, 5 );
21610
21611			_geometry.setIndex( [ 0, 1, 2,	0, 2, 3 ] );
21612			_geometry.setAttribute( 'position', new InterleavedBufferAttribute( interleavedBuffer, 3, 0, false ) );
21613			_geometry.setAttribute( 'uv', new InterleavedBufferAttribute( interleavedBuffer, 2, 3, false ) );
21614
21615		}
21616
21617		/**
21618		 * The sprite geometry.
21619		 *
21620		 * @type {BufferGeometry}
21621		 */
21622		this.geometry = _geometry;
21623
21624		/**
21625		 * The sprite material.
21626		 *
21627		 * @type {(SpriteMaterial|SpriteNodeMaterial)}
21628		 */
21629		this.material = material;
21630
21631		/**
21632		 * The sprite's anchor point, and the point around which the sprite rotates.
21633		 * A value of `(0.5, 0.5)` corresponds to the midpoint of the sprite. A value
21634		 * of `(0, 0)` corresponds to the lower left corner of the sprite.
21635		 *
21636		 * @type {Vector2}
21637		 * @default (0.5,0.5)
21638		 */
21639		this.center = new Vector2( 0.5, 0.5 );
21640
21641		/**
21642		 * The number of instances of this sprite.
21643		 * Can only be used with {@link WebGPURenderer}.
21644		 *
21645		 * @type {number}
21646		 * @default 1
21647		 */
21648		this.count = 1
vendor: 9,105 bytes, lines 21648-22074
21648;
21649
21650	}
21651
21652	/**
21653	 * Computes intersection points between a casted ray and this sprite.
21654	 *
21655	 * @param {Raycaster} raycaster - The raycaster.
21656	 * @param {Array<Object>} intersects - The target array that holds the intersection points.
21657	 */
21658	raycast( raycaster, intersects ) {
21659
21660		if ( raycaster.camera === null ) {
21661
21662			error( 'Sprite: "Raycaster.camera" needs to be set in order to raycast against sprites.' );
21663
21664		}
21665
21666		_worldScale.setFromMatrixScale( this.matrixWorld );
21667
21668		_viewWorldMatrix.copy( raycaster.camera.matrixWorld );
21669		this.modelViewMatrix.multiplyMatrices( raycaster.camera.matrixWorldInverse, this.matrixWorld );
21670
21671		_mvPosition.setFromMatrixPosition( this.modelViewMatrix );
21672
21673		if ( raycaster.camera.isPerspectiveCamera && this.material.sizeAttenuation === false ) {
21674
21675			_worldScale.multiplyScalar( - _mvPosition.z );
21676
21677		}
21678
21679		const rotation = this.material.rotation;
21680		let sin, cos;
21681
21682		if ( rotation !== 0 ) {
21683
21684			cos = Math.cos( rotation );
21685			sin = Math.sin( rotation );
21686
21687		}
21688
21689		const center = this.center;
21690
21691		transformVertex( _vA$1.set( -0.5, -0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
21692		transformVertex( _vB$1.set( 0.5, -0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
21693		transformVertex( _vC$1.set( 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
21694
21695		_uvA.set( 0, 0 );
21696		_uvB.set( 1, 0 );
21697		_uvC.set( 1, 1 );
21698
21699		// check first triangle
21700		let intersect = raycaster.ray.intersectTriangle( _vA$1, _vB$1, _vC$1, false, _intersectPoint );
21701
21702		if ( intersect === null ) {
21703
21704			// check second triangle
21705			transformVertex( _vB$1.set( -0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
21706			_uvB.set( 0, 1 );
21707
21708			intersect = raycaster.ray.intersectTriangle( _vA$1, _vC$1, _vB$1, false, _intersectPoint );
21709			if ( intersect === null ) {
21710
21711				return;
21712
21713			}
21714
21715		}
21716
21717		const distance = raycaster.ray.origin.distanceTo( _intersectPoint );
21718
21719		if ( distance < raycaster.near || distance > raycaster.far ) return;
21720
21721		intersects.push( {
21722
21723			distance: distance,
21724			point: _intersectPoint.clone(),
21725			uv: Triangle.getInterpolation( _intersectPoint, _vA$1, _vB$1, _vC$1, _uvA, _uvB, _uvC, new Vector2() ),
21726			face: null,
21727			object: this
21728
21729		} );
21730
21731	}
21732
21733	copy( source, recursive ) {
21734
21735		super.copy( source, recursive );
21736
21737		if ( source.center !== undefined ) this.center.copy( source.center );
21738
21739		this.material = source.material;
21740
21741		return this;
21742
21743	}
21744
21745}
21746
21747function transformVertex( vertexPosition, mvPosition, center, scale, sin, cos ) {
21748
21749	// compute position in camera space
21750	_alignedPosition.subVectors( vertexPosition, center ).addScalar( 0.5 ).multiply( scale );
21751
21752	// to check if rotation is not zero
21753	if ( sin !== undefined ) {
21754
21755		_rotatedPosition.x = ( cos * _alignedPosition.x ) - ( sin * _alignedPosition.y );
21756		_rotatedPosition.y = ( sin * _alignedPosition.x ) + ( cos * _alignedPosition.y );
21757
21758	} else {
21759
21760		_rotatedPosition.copy( _alignedPosition );
21761
21762	}
21763
21764
21765	vertexPosition.copy( mvPosition );
21766	vertexPosition.x += _rotatedPosition.x;
21767	vertexPosition.y += _rotatedPosition.y;
21768
21769	// transform to world space
21770	vertexPosition.applyMatrix4( _viewWorldMatrix );
21771
21772}
21773
21774const _v1$2 = /*@__PURE__*/ new Vector3();
21775const _v2$1 = /*@__PURE__*/ new Vector3();
21776
21777/**
21778 * A component for providing a basic Level of Detail (LOD) mechanism.
21779 *
21780 * Every LOD level is associated with an object, and rendering can be switched
21781 * between them at the distances specified. Typically you would create, say,
21782 * three meshes, one for far away (low detail), one for mid range (medium
21783 * detail) and one for close up (high detail).
21784 *
21785 * ```js
21786 * const lod = new THREE.LOD();
21787 * const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
21788 *
21789 * //Create spheres with 3 levels of detail and create new LOD levels for them
21790 * for( let i = 0; i < 3; i++ ) {
21791 *
21792 * 	const geometry = new THREE.IcosahedronGeometry( 10, 3 - i );
21793 * 	const mesh = new THREE.Mesh( geometry, material );
21794 * 	lod.addLevel( mesh, i * 75 );
21795 *
21796 * }
21797 *
21798 * scene.add( lod );
21799 * ```
21800 *
21801 * @augments Object3D
21802 */
21803class LOD extends Object3D {
21804
21805	/**
21806	 * Constructs a new LOD.
21807	 */
21808	constructor() {
21809
21810		super();
21811
21812		/**
21813		 * This flag can be used for type testing.
21814		 *
21815		 * @type {boolean}
21816		 * @readonly
21817		 * @default true
21818		 */
21819		this.isLOD = true;
21820
21821		/**
21822		 * The current LOD index.
21823		 *
21824		 * @private
21825		 * @type {number}
21826		 * @default 0
21827		 */
21828		this._currentLevel = 0;
21829
21830		this.type = 'LOD';
21831
21832		Object.defineProperties( this, {
21833			/**
21834			 * This array holds the LOD levels.
21835			 *
21836			 * @name LOD#levels
21837			 * @type {Array<{object:Object3D,distance:number,hysteresis:number}>}
21838			 */
21839			levels: {
21840				enumerable: true,
21841				value: []
21842			}
21843		} );
21844
21845		/**
21846		 * Whether the LOD object is updated automatically by the renderer per frame
21847		 * or not. If set to `false`, you have to call {@link LOD#update} in the
21848		 * render loop by yourself.
21849		 *
21850		 * @type {boolean}
21851		 * @default true
21852		 */
21853		this.autoUpdate = true;
21854
21855	}
21856
21857	copy( source ) {
21858
21859		super.copy( source, false );
21860
21861		const levels = source.levels;
21862
21863		for ( let i = 0, l = levels.length; i < l; i ++ ) {
21864
21865			const level = levels[ i ];
21866
21867			this.addLevel( level.object.clone(), level.distance, level.hysteresis );
21868
21869		}
21870
21871		this.autoUpdate = source.autoUpdate;
21872
21873		return this;
21874
21875	}
21876
21877	/**
21878	 * Adds a mesh that will display at a certain distance and greater. Typically
21879	 * the further away the distance, the lower the detail on the mesh.
21880	 *
21881	 * @param {Object3D} object - The 3D object to display at this level.
21882	 * @param {number} [distance=0] - The distance at which to display this level of detail.
21883	 * @param {number} [hysteresis=0] - Threshold used to avoid flickering at LOD boundaries, as a fraction of distance.
21884	 * @return {LOD} A reference to this instance.
21885	 */
21886	addLevel( object, distance = 0, hysteresis = 0 ) {
21887
21888		distance = Math.abs( distance );
21889
21890		const levels = this.levels;
21891
21892		let l;
21893
21894		for ( l = 0; l < levels.length; l ++ ) {
21895
21896			if ( distance < levels[ l ].distance ) {
21897
21898				break;
21899
21900			}
21901
21902		}
21903
21904		levels.splice( l, 0, { distance: distance, hysteresis: hysteresis, object: object } );
21905
21906		this.add( object );
21907
21908		return this;
21909
21910	}
21911
21912	/**
21913	 * Removes an existing level, based on the distance from the camera.
21914	 * Returns `true` when the level has been removed. Otherwise `false`.
21915	 *
21916	 * @param {number} distance - Distance of the level to remove.
21917	 * @return {boolean} Whether the level has been removed or not.
21918	 */
21919	removeLevel( distance ) {
21920
21921		const levels = this.levels;
21922
21923		for ( let i = 0; i < levels.length; i ++ ) {
21924
21925			if ( levels[ i ].distance === distance ) {
21926
21927				const removedElements = levels.splice( i, 1 );
21928				this.remove( removedElements[ 0 ].object );
21929
21930				return true;
21931
21932			}
21933
21934		}
21935
21936		return false;
21937
21938	}
21939
21940	/**
21941	 * Returns the currently active LOD level index.
21942	 *
21943	 * @return {number} The current active LOD level index.
21944	 */
21945	getCurrentLevel() {
21946
21947		return this._currentLevel;
21948
21949	}
21950
21951	/**
21952	 * Returns a reference to the first 3D object that is greater than
21953	 * the given distance.
21954	 *
21955	 * @param {number} distance - The LOD distance.
21956	 * @return {?Object3D} The found 3D object. `null` if no 3D object has been found.
21957	 */
21958	getObjectForDistance( distance ) {
21959
21960		const levels = this.levels;
21961
21962		if ( levels.length > 0 ) {
21963
21964			let i, l;
21965
21966			for ( i = 1, l = levels.length; i < l; i ++ ) {
21967
21968				let levelDistance = levels[ i ].distance;
21969
21970				if ( levels[ i ].object.visible ) {
21971
21972					levelDistance -= levelDistance * levels[ i ].hysteresis;
21973
21974				}
21975
21976				if ( distance < levelDistance ) {
21977
21978					break;
21979
21980				}
21981
21982			}
21983
21984			return levels[ i - 1 ].object;
21985
21986		}
21987
21988		return null;
21989
21990	}
21991
21992	/**
21993	 * Computes intersection points between a casted ray and this LOD.
21994	 *
21995	 * @param {Raycaster} raycaster - The raycaster.
21996	 * @param {Array<Object>} intersects - The target array that holds the intersection points.
21997	 */
21998	raycast( raycaster, intersects ) {
21999
22000		const levels = this.levels;
22001
22002		if ( levels.length > 0 ) {
22003
22004			_v1$2.setFromMatrixPosition( this.matrixWorld );
22005
22006			const distance = raycaster.ray.origin.distanceTo( _v1$2 );
22007
22008			this.getObjectForDistance( distance ).raycast( raycaster, intersects );
22009
22010		}
22011
22012	}
22013
22014	/**
22015	 * Updates the LOD by computing which LOD level should be visible according
22016	 * to the current distance of the given camera.
22017	 *
22018	 * @param {Camera} camera - The camera the scene is rendered with.
22019	 */
22020	update( camera ) {
22021
22022		const levels = this.levels;
22023
22024		if ( levels.length > 1 ) {
22025
22026			_v1$2.setFromMatrixPosition( camera.matrixWorld );
22027			_v2$1.setFromMatrixPosition( this.matrixWorld );
22028
22029			const distance = _v1$2.distanceTo( _v2$1 ) / camera.zoom;
22030
22031			levels[ 0 ].object.visible = true;
22032
22033			let i, l;
22034
22035			for ( i = 1, l = levels.length; i < l; i ++ ) {
22036
22037				let levelDistance = levels[ i ].distance;
22038
22039				if ( levels[ i ].object.visible ) {
22040
22041					levelDistance -= levelDistance * levels[ i ].hysteresis;
22042
22043				}
22044
22045				if ( distance >= levelDistance ) {
22046
22047					levels[ i - 1 ].object.visible = false;
22048					levels[ i ].object.visible = true;
22049
22050				} else {
22051
22052					break;
22053
22054				}
22055
22056			}
22057
22058			this._currentLevel = i - 1;
22059
22060			for ( ; i < l; i ++ ) {
22061
22062				levels[ i ].object.visible = false;
22063
22064			}
22065
22066		}
22067
22068	}
22069
22070	toJSON( meta ) {
22071
22072		const data = super.toJSON( meta );
22073
22074		
22074if ( this.autoUpdate === false ) data.object.autoUpdate = false;
22075
22076		data.object.levels = [];
22077
22078		const levels = this.levels;
22079
22080		for ( let i = 0, l = levels.length; i < l; i ++ ) {
22081
22082			const level = levels[ i ];
22083
22084			data.object.levels.push( {
22085				object: level.object.uuid,
22086				distance: level.distance,
22087				hysteresis: level.hysteresis
22088			} );
22089
22090		}
22091
22092		return data;
22093
22094	}
22095
22096}
22097
22098const _vector$7 = /*@__PURE__*/ new Vector3();
22099const _segCenter = /*@__PURE__*/ new Vector3();
22100const _segDir = /*@__PURE__*/ new Vector3();
22101const _diff = /*@__PURE__*/ new Vector3();
22102
22103const _edge1 = /*@__PURE__*/ new Vector3();
22104const _edge2 = /*@__PURE__*/ new Vector3();
22105const _normal$1
vendor: 7,142 bytes, lines 22105-22397
22105 = /*@__PURE__*/ new Vector3();
22106
22107/**
22108 * A ray that emits from an origin in a certain direction. The class is used by
22109 * {@link Raycaster} to assist with raycasting. Raycasting is used for
22110 * mouse picking (working out what objects in the 3D space the mouse is over)
22111 * amongst other things.
22112 */
22113class Ray {
22114
22115	/**
22116	 * Constructs a new ray.
22117	 *
22118	 * @param {Vector3} [origin=(0,0,0)] - The origin of the ray.
22119	 * @param {Vector3} [direction=(0,0,-1)] - The (normalized) direction of the ray.
22120	 */
22121	constructor( origin = new Vector3(), direction = new Vector3( 0, 0, -1 ) ) {
22122
22123		/**
22124		 * The origin of the ray.
22125		 *
22126		 * @type {Vector3}
22127		 */
22128		this.origin = origin;
22129
22130		/**
22131		 * The (normalized) direction of the ray.
22132		 *
22133		 * @type {Vector3}
22134		 */
22135		this.direction = direction;
22136
22137	}
22138
22139	/**
22140	 * Sets the ray's components by copying the given values.
22141	 *
22142	 * @param {Vector3} origin - The origin.
22143	 * @param {Vector3} direction - The direction.
22144	 * @return {Ray} A reference to this ray.
22145	 */
22146	set( origin, direction ) {
22147
22148		this.origin.copy( origin );
22149		this.direction.copy( direction );
22150
22151		return this;
22152
22153	}
22154
22155	/**
22156	 * Copies the values of the given ray to this instance.
22157	 *
22158	 * @param {Ray} ray - The ray to copy.
22159	 * @return {Ray} A reference to this ray.
22160	 */
22161	copy( ray ) {
22162
22163		this.origin.copy( ray.origin );
22164		this.direction.copy( ray.direction );
22165
22166		return this;
22167
22168	}
22169
22170	/**
22171	 * Returns a vector that is located at a given distance along this ray.
22172	 *
22173	 * @param {number} t - The distance along the ray to retrieve a position for.
22174	 * @param {Vector3} target - The target vector that is used to store the method's result.
22175	 * @return {Vector3} A position on the ray.
22176	 */
22177	at( t, target ) {
22178
22179		return target.copy( this.origin ).addScaledVector( this.direction, t );
22180
22181	}
22182
22183	/**
22184	 * Adjusts the direction of the ray to point at the given vector in world space.
22185	 *
22186	 * @param {Vector3} v - The target position.
22187	 * @return {Ray} A reference to this ray.
22188	 */
22189	lookAt( v ) {
22190
22191		this.direction.copy( v ).sub( this.origin ).normalize();
22192
22193		return this;
22194
22195	}
22196
22197	/**
22198	 * Shift the origin of this ray along its direction by the given distance.
22199	 *
22200	 * @param {number} t - The distance along the ray to interpolate.
22201	 * @return {Ray} A reference to this ray.
22202	 */
22203	recast( t ) {
22204
22205		this.origin.copy( this.at( t, _vector$7 ) );
22206
22207		return this;
22208
22209	}
22210
22211	/**
22212	 * Returns the point along this ray that is closest to the given point.
22213	 *
22214	 * @param {Vector3} point - A point in 3D space to get the closet location on the ray for.
22215	 * @param {Vector3} target - The target vector that is used to store the method's result.
22216	 * @return {Vector3} The closest point on this ray.
22217	 */
22218	closestPointToPoint( point, target ) {
22219
22220		target.subVectors( point, this.origin );
22221
22222		const directionDistance = target.dot( this.direction );
22223
22224		if ( directionDistance < 0 ) {
22225
22226			return target.copy( this.origin );
22227
22228		}
22229
22230		return target.copy( this.origin ).addScaledVector( this.direction, directionDistance );
22231
22232	}
22233
22234	/**
22235	 * Returns the distance of the closest approach between this ray and the given point.
22236	 *
22237	 * @param {Vector3} point - A point in 3D space to compute the distance to.
22238	 * @return {number} The distance.
22239	 */
22240	distanceToPoint( point ) {
22241
22242		return Math.sqrt( this.distanceSqToPoint( point ) );
22243
22244	}
22245
22246	/**
22247	 * Returns the squared distance of the closest approach between this ray and the given point.
22248	 *
22249	 * @param {Vector3} point - A point in 3D space to compute the distance to.
22250	 * @return {number} The squared distance.
22251	 */
22252	distanceSqToPoint( point ) {
22253
22254		const directionDistance = _vector$7.subVectors( point, this.origin ).dot( this.direction );
22255
22256		// point behind the ray
22257
22258		if ( directionDistance < 0 ) {
22259
22260			return this.origin.distanceToSquared( point );
22261
22262		}
22263
22264		_vector$7.copy( this.origin ).addScaledVector( this.direction, directionDistance );
22265
22266		return _vector$7.distanceToSquared( point );
22267
22268	}
22269
22270	/**
22271	 * Returns the squared distance between this ray and the given line segment.
22272	 *
22273	 * @param {Vector3} v0 - The start point of the line segment.
22274	 * @param {Vector3} v1 - The end point of the line segment.
22275	 * @param {Vector3} [optionalPointOnRay] - When provided, it receives the point on this ray that is closest to the segment.
22276	 * @param {Vector3} [optionalPointOnSegment] - When provided, it receives the point on the line segment that is closest to this ray.
22277	 * @return {number} The squared distance.
22278	 */
22279	distanceSqToSegment( v0, v1, optionalPointOnRay, optionalPointOnSegment ) {
22280
22281		// from https://github.com/pmjoniak/GeometricTools/blob/master/GTEngine/Include/Mathematics/GteDistRaySegment.h
22282		// It returns the min distance between the ray and the segment
22283		// defined by v0 and v1
22284		// It can also set two optional targets :
22285		// - The closest point on the ray
22286		// - The closest point on the segment
22287
22288		_segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 );
22289		_segDir.copy( v1 ).sub( v0 ).normalize();
22290		_diff.copy( this.origin ).sub( _segCenter );
22291
22292		const segExtent = v0.distanceTo( v1 ) * 0.5;
22293		const a01 = - this.direction.dot( _segDir );
22294		const b0 = _diff.dot( this.direction );
22295		const b1 = - _diff.dot( _segDir );
22296		const c = _diff.lengthSq();
22297		const det = Math.abs( 1 - a01 * a01 );
22298		let s0, s1, sqrDist, extDet;
22299
22300		if ( det > 0 ) {
22301
22302			// The ray and segment are not parallel.
22303
22304			s0 = a01 * b1 - b0;
22305			s1 = a01 * b0 - b1;
22306			extDet = segExtent * det;
22307
22308			if ( s0 >= 0 ) {
22309
22310				if ( s1 >= - extDet ) {
22311
22312					if ( s1 <= extDet ) {
22313
22314						// region 0
22315						// Minimum at interior points of ray and segment.
22316
22317						const invDet = 1 / det;
22318						s0 *= invDet;
22319						s1 *= invDet;
22320						sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c;
22321
22322					} else {
22323
22324						// region 1
22325
22326						s1 = segExtent;
22327						s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
22328						sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
22329
22330					}
22331
22332				} else {
22333
22334					// region 5
22335
22336					s1 = - segExtent;
22337					s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
22338					sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
22339
22340				}
22341
22342			} else {
22343
22344				if ( s1 <= - extDet ) {
22345
22346					// region 4
22347
22348					s0 = Math.max( 0, - ( - a01 * segExtent + b0 ) );
22349					s1 = ( s0 > 0 ) ? - segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
22350					sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
22351
22352				} else if ( s1 <= extDet ) {
22353
22354					// region 3
22355
22356					s0 = 0;
22357					s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent );
22358					sqrDist = s1 * ( s1 + 2 * b1 ) + c;
22359
22360				} else {
22361
22362					// region 2
22363
22364					s0 = Math.max( 0, - ( a01 * segExtent + b0 ) );
22365					s1 = ( s0 > 0 ) ? segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
22366					sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
22367
22368				}
22369
22370			}
22371
22372		} else {
22373
22374			// Ray and segment are parallel.
22375
22376			s1 = ( a01 > 0 ) ? - segExtent : segExtent;
22377			s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
22378			sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
22379
22380		}
22381
22382		if ( optionalPointOnRay ) {
22383
22384			optionalPointOnRay.copy( this.origin ).addScaledVector( this.direction, s0 );
22385
22386		}
22387
22388		if ( optionalPointOnSegment ) {
22389
22390			optionalPointOnSegment.copy( _segCenter ).addScaledVector( _segDir, s1 );
22391
22392		}
22393
22394		return sqrDist;
22395
22396	}
22397
vendor: 8,703 bytes, lines 22398-22758
22398	/**
22399	 * Intersects this ray with the given sphere, returning the intersection
22400	 * point or `null` if there is no intersection.
22401	 *
22402	 * @param {Sphere} sphere - The sphere to intersect.
22403	 * @param {Vector3} target - The target vector that is used to store the method's result.
22404	 * @return {?Vector3} The intersection point.
22405	 */
22406	intersectSphere( sphere, target ) {
22407
22408		_vector$7.subVectors( sphere.center, this.origin );
22409		const tca = _vector$7.dot( this.direction );
22410		const d2 = _vector$7.dot( _vector$7 ) - tca * tca;
22411		const radius2 = sphere.radius * sphere.radius;
22412
22413		if ( d2 > radius2 ) return null;
22414
22415		const thc = Math.sqrt( radius2 - d2 );
22416
22417		// t0 = first intersect point - entrance on front of sphere
22418		const t0 = tca - thc;
22419
22420		// t1 = second intersect point - exit point on back of sphere
22421		const t1 = tca + thc;
22422
22423		// test to see if t1 is behind the ray - if so, return null
22424		if ( t1 < 0 ) return null;
22425
22426		// test to see if t0 is behind the ray:
22427		// if it is, the ray is inside the sphere, so return the second exit point scaled by t1,
22428		// in order to always return an intersect point that is in front of the ray.
22429		if ( t0 < 0 ) return this.at( t1, target );
22430
22431		// else t0 is in front of the ray, so return the first collision point scaled by t0
22432		return this.at( t0, target );
22433
22434	}
22435
22436	/**
22437	 * Returns `true` if this ray intersects with the given sphere.
22438	 *
22439	 * @param {Sphere} sphere - The sphere to intersect.
22440	 * @return {boolean} Whether this ray intersects with the given sphere or not.
22441	 */
22442	intersectsSphere( sphere ) {
22443
22444		if ( sphere.radius < 0 ) return false; // handle empty spheres, see #31187
22445
22446		return this.distanceSqToPoint( sphere.center ) <= ( sphere.radius * sphere.radius );
22447
22448	}
22449
22450	/**
22451	 * Computes the distance from the ray's origin to the given plane. Returns `null` if the ray
22452	 * does not intersect with the plane.
22453	 *
22454	 * @param {Plane} plane - The plane to compute the distance to.
22455	 * @return {?number} Whether this ray intersects with the given sphere or not.
22456	 */
22457	distanceToPlane( plane ) {
22458
22459		const denominator = plane.normal.dot( this.direction );
22460
22461		if ( denominator === 0 ) {
22462
22463			// line is coplanar, return origin
22464			if ( plane.distanceToPoint( this.origin ) === 0 ) {
22465
22466				return 0;
22467
22468			}
22469
22470			// Null is preferable to undefined since undefined means.... it is undefined
22471
22472			return null;
22473
22474		}
22475
22476		const t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator;
22477
22478		// Return if the ray never intersects the plane
22479
22480		return t >= 0 ? t : null;
22481
22482	}
22483
22484	/**
22485	 * Intersects this ray with the given plane, returning the intersection
22486	 * point or `null` if there is no intersection.
22487	 *
22488	 * @param {Plane} plane - The plane to intersect.
22489	 * @param {Vector3} target - The target vector that is used to store the method's result.
22490	 * @return {?Vector3} The intersection point.
22491	 */
22492	intersectPlane( plane, target ) {
22493
22494		const t = this.distanceToPlane( plane );
22495
22496		if ( t === null ) {
22497
22498			return null;
22499
22500		}
22501
22502		return this.at( t, target );
22503
22504	}
22505
22506	/**
22507	 * Returns `true` if this ray intersects with the given plane.
22508	 *
22509	 * @param {Plane} plane - The plane to intersect.
22510	 * @return {boolean} Whether this ray intersects with the given plane or not.
22511	 */
22512	intersectsPlane( plane ) {
22513
22514		// check if the ray lies on the plane first
22515
22516		const distToPoint = plane.distanceToPoint( this.origin );
22517
22518		if ( distToPoint === 0 ) {
22519
22520			return true;
22521
22522		}
22523
22524		const denominator = plane.normal.dot( this.direction );
22525
22526		if ( denominator * distToPoint < 0 ) {
22527
22528			return true;
22529
22530		}
22531
22532		// ray origin is behind the plane (and is pointing behind it)
22533
22534		return false;
22535
22536	}
22537
22538	/**
22539	 * Intersects this ray with the given bounding box, returning the intersection
22540	 * point or `null` if there is no intersection.
22541	 *
22542	 * @param {Box3} box - The box to intersect.
22543	 * @param {Vector3} target - The target vector that is used to store the method's result.
22544	 * @return {?Vector3} The intersection point.
22545	 */
22546	intersectBox( box, target ) {
22547
22548		let tmin, tmax, tymin, tymax, tzmin, tzmax;
22549
22550		const invdirx = 1 / this.direction.x,
22551			invdiry = 1 / this.direction.y,
22552			invdirz = 1 / this.direction.z;
22553
22554		const origin = this.origin;
22555
22556		if ( invdirx >= 0 ) {
22557
22558			tmin = ( box.min.x - origin.x ) * invdirx;
22559			tmax = ( box.max.x - origin.x ) * invdirx;
22560
22561		} else {
22562
22563			tmin = ( box.max.x - origin.x ) * invdirx;
22564			tmax = ( box.min.x - origin.x ) * invdirx;
22565
22566		}
22567
22568		if ( invdiry >= 0 ) {
22569
22570			tymin = ( box.min.y - origin.y ) * invdiry;
22571			tymax = ( box.max.y - origin.y ) * invdiry;
22572
22573		} else {
22574
22575			tymin = ( box.max.y - origin.y ) * invdiry;
22576			tymax = ( box.min.y - origin.y ) * invdiry;
22577
22578		}
22579
22580		if ( ( tmin > tymax ) || ( tymin > tmax ) ) return null;
22581
22582		if ( tymin > tmin || isNaN( tmin ) ) tmin = tymin;
22583
22584		if ( tymax < tmax || isNaN( tmax ) ) tmax = tymax;
22585
22586		if ( invdirz >= 0 ) {
22587
22588			tzmin = ( box.min.z - origin.z ) * invdirz;
22589			tzmax = ( box.max.z - origin.z ) * invdirz;
22590
22591		} else {
22592
22593			tzmin = ( box.max.z - origin.z ) * invdirz;
22594			tzmax = ( box.min.z - origin.z ) * invdirz;
22595
22596		}
22597
22598		if ( ( tmin > tzmax ) || ( tzmin > tmax ) ) return null;
22599
22600		if ( tzmin > tmin || tmin !== tmin ) tmin = tzmin;
22601
22602		if ( tzmax < tmax || tmax !== tmax ) tmax = tzmax;
22603
22604		//return point closest to the ray (positive side)
22605
22606		if ( tmax < 0 ) return null;
22607
22608		return this.at( tmin >= 0 ? tmin : tmax, target );
22609
22610	}
22611
22612	/**
22613	 * Returns `true` if this ray intersects with the given box.
22614	 *
22615	 * @param {Box3} box - The box to intersect.
22616	 * @return {boolean} Whether this ray intersects with the given box or not.
22617	 */
22618	intersectsBox( box ) {
22619
22620		return this.intersectBox( box, _vector$7 ) !== null;
22621
22622	}
22623
22624	/**
22625	 * Intersects this ray with the given triangle, returning the intersection
22626	 * point or `null` if there is no intersection.
22627	 *
22628	 * @param {Vector3} a - The first vertex of the triangle.
22629	 * @param {Vector3} b - The second vertex of the triangle.
22630	 * @param {Vector3} c - The third vertex of the triangle.
22631	 * @param {boolean} backfaceCulling - Whether to use backface culling or not.
22632	 * @param {Vector3} target - The target vector that is used to store the method's result.
22633	 * @return {?Vector3} The intersection point.
22634	 */
22635	intersectTriangle( a, b, c, backfaceCulling, target ) {
22636
22637		// Compute the offset origin, edges, and normal.
22638
22639		// from https://github.com/pmjoniak/GeometricTools/blob/master/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h
22640
22641		_edge1.subVectors( b, a );
22642		_edge2.subVectors( c, a );
22643		_normal$1.crossVectors( _edge1, _edge2 );
22644
22645		// Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction,
22646		// E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by
22647		//   |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2))
22648		//   |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q))
22649		//   |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N)
22650		let DdN = this.direction.dot( _normal$1 );
22651		let sign;
22652
22653		if ( DdN > 0 ) {
22654
22655			if ( backfaceCulling ) return null;
22656			sign = 1;
22657
22658		} else if ( DdN < 0 ) {
22659
22660			sign = -1;
22661			DdN = - DdN;
22662
22663		} else {
22664
22665			return null;
22666
22667		}
22668
22669		_diff.subVectors( this.origin, a );
22670		const DdQxE2 = sign * this.direction.dot( _edge2.crossVectors( _diff, _edge2 ) );
22671
22672		// b1 < 0, no intersection
22673		if ( DdQxE2 < 0 ) {
22674
22675			return null;
22676
22677		}
22678
22679		const DdE1xQ = sign * this.direction.dot( _edge1.cross( _diff ) );
22680
22681		// b2 < 0, no intersection
22682		if ( DdE1xQ < 0 ) {
22683
22684			return null;
22685
22686		}
22687
22688		// b1+b2 > 1, no intersection
22689		if ( DdQxE2 + DdE1xQ > DdN ) {
22690
22691			return null;
22692
22693		}
22694
22695		// Line intersects triangle, check if ray does.
22696		const QdN = - sign * _diff.dot( _normal$1 );
22697
22698		// t < 0, no intersection
22699		if ( QdN < 0 ) {
22700
22701			return null;
22702
22703		}
22704
22705		// Ray intersects triangle.
22706		return this.at( QdN / DdN, target );
22707
22708	}
22709
22710	/**
22711	 * Transforms this ray with the given 4x4 transformation matrix.
22712	 *
22713	 * @param {Matrix4} matrix4 - The transformation matrix.
22714	 * @return {Ray} A reference to this ray.
22715	 */
22716	applyMatrix4( matrix4 ) {
22717
22718		this.origin.applyMatrix4( matrix4 );
22719		this.direction.transformDirection( matrix4 );
22720
22721		return this;
22722
22723	}
22724
22725	/**
22726	 * Returns `true` if this ray is equal with the given one.
22727	 *
22728	 * @param {Ray} ray - The ray to test for equality.
22729	 * @return {boolean} Whether this ray is equal with the given one.
22730	 */
22731	equals( ray ) {
22732
22733		return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction );
22734
22735	}
22736
22737	/**
22738	 * Returns a new ray with copied values from this instance.
22739	 *
22740	 * @return {Ray} A clone of this instance.
22741	 */
22742	clone() {
22743
22744		return new this.constructor().copy( this );
22745
22746	}
22747
22748}
22749
22750/**
22751 * A material for drawing geometries in a simple shaded (flat or wireframe) way.
22752 *
22753 * This material is not affected by lights.
22754 *
22755 * @augments Material
22756 * @demo scenes/material-browser.html#MeshBasicMaterial
22757 */
22758class MeshBasicMaterial extends Material
22758 {
22759
22760	/**
22761	 * Constructs a new mesh basic material.
22762	 *
22763	 * @param {Object} [parameters] - An object with one or more properties
22764	 * defining the material's appearance. Any property of the material
22765	 * (including any property from inherited materials) can be passed
22766	 * in here. Color values can be passed any type of value accepted
22767	 * by {@link Color#set}.
22768	 */
22769	constructor( parameters ) {
22770
22771		super();
22772
22773		/**
22774		 * This flag can be used for type testing.
22775		 *
22776		 * @type {boolean}
22777		 * @readonly
22778		 * @default true
22779		 */
22780		this.isMeshBasicMaterial = true;
22781
22782		this.type = 'MeshBasicMaterial';
22783
22784		/**
22785		 * Color of the material.
22786		 *
22787		 * @type {Color}
22788		 * @default (1,1,1)
22789		 */
22790		this.color = new Color( 0xffffff ); // diffuse
22791
22792		/**
22793		 * The color map. May optionally include an alpha channel, typically combined
22794		 * with {@link Material#transparent} or {@link Material#alphaTest}. The texture map
22795		 * color is modulated by the diffuse `color`.
22796		 *
22797		 * @type {?Texture}
22798		 * @default null
22799		 */
22800		this.map = null;
22801
22802		/**
22803		 * The light map. Requires a second set of UVs.
22804		 *
22805		 * @type {?Texture}
22806		 * @default null
22807		 */
22808		this.lightMap = null;
22809
22810		/**
22811		 * Intensity of the baked light.
22812		 *
22813		 * @type {number}
22814		 * @default 1
22815		 */
22816		this.lightMapIntensity = 1.0;
22817
22818		/**
22819		 * The red channel of this texture is used as the ambient occlusion map.
22820		 * Requires a second set of UVs.
22821		 *
22822		 * @type {?Texture}
22823		 * @default null
22824		 */
22825		this.aoMap = null;
22826
22827		/**
22828		 * Intensity of the ambient occlusion effect. Range is `[0,1]`, where `0`
22829		 * disables ambient occlusion. Where intensity is `1` and the AO map's
22830		 * red channel is also `1`, ambient light is fully occluded on a surface.
22831		 *
22832		 * @type {number}
22833		 * @default 1
22834		 */
22835		this.aoMapIntensity = 1.0;
22836
22837		/**
22838		 * Specular map used by the material.
22839		 *
22840		 * @type {?Texture}
22841		 * @default null
22842		 */
22843		this.specularMap = null;
22844
22845		/**
22846		 * The alpha map is a grayscale texture that controls the opacity across the
22847		 * surface (black: fully transparent; white: fully opaque).
22848		 *
22849		 * Only the color of the texture is used, ignoring the alpha channel if one
22850		 * exists. For RGB and RGBA textures, the renderer will use the green channel
22851		 * when sampling this texture due to the extra bit of precision provided for
22852		 * green in DXT-compressed and uncompressed RGB 565 formats. Luminance-only and
22853		 * luminance/alpha textures will also still work as expected.
22854		 *
22855		 * @type {?Texture}
22856		 * @default null
22857		 */
22858		this.alphaMap = null;
22859
22860		/**
22861		 * The environment map
vendor: 5,823 bytes, lines 22861-23114
22861.
22862		 *
22863		 * @type {?Texture}
22864		 * @default null
22865		 */
22866		this.envMap = null;
22867
22868		/**
22869		 * The rotation of the environment map in radians.
22870		 *
22871		 * @type {Euler}
22872		 * @default (0,0,0)
22873		 */
22874		this.envMapRotation = new Euler();
22875
22876		/**
22877		 * How to combine the result of the surface's color with the environment map, if any.
22878		 *
22879		 * When set to `MixOperation`, the {@link MeshBasicMaterial#reflectivity} is used to
22880		 * blend between the two colors.
22881		 *
22882		 * @type {(MultiplyOperation|MixOperation|AddOperation)}
22883		 * @default MultiplyOperation
22884		 */
22885		this.combine = MultiplyOperation;
22886
22887		/**
22888		 * How much the environment map affects the surface.
22889		 * The valid range is between `0` (no reflections) and `1` (full reflections).
22890		 *
22891		 * @type {number}
22892		 * @default 1
22893		 */
22894		this.reflectivity = 1;
22895
22896		/**
22897		 * The index of refraction (IOR) of air (approximately 1) divided by the
22898		 * index of refraction of the material. It is used with environment mapping
22899		 * modes {@link CubeRefractionMapping} and {@link EquirectangularRefractionMapping}.
22900		 * The refraction ratio should not exceed `1`.
22901		 *
22902		 * @type {number}
22903		 * @default 0.98
22904		 */
22905		this.refractionRatio = 0.98;
22906
22907		/**
22908		 * Renders the geometry as a wireframe.
22909		 *
22910		 * @type {boolean}
22911		 * @default false
22912		 */
22913		this.wireframe = false;
22914
22915		/**
22916		 * Controls the thickness of the wireframe.
22917		 *
22918		 * Can only be used with {@link SVGRenderer}.
22919		 *
22920		 * @type {number}
22921		 * @default 1
22922		 */
22923		this.wireframeLinewidth = 1;
22924
22925		/**
22926		 * Defines appearance of wireframe ends.
22927		 *
22928		 * Can only be used with {@link SVGRenderer}.
22929		 *
22930		 * @type {('round'|'bevel'|'miter')}
22931		 * @default 'round'
22932		 */
22933		this.wireframeLinecap = 'round';
22934
22935		/**
22936		 * Defines appearance of wireframe joints.
22937		 *
22938		 * Can only be used with {@link SVGRenderer}.
22939		 *
22940		 * @type {('round'|'bevel'|'miter')}
22941		 * @default 'round'
22942		 */
22943		this.wireframeLinejoin = 'round';
22944
22945		/**
22946		 * Whether the material is affected by fog or not.
22947		 *
22948		 * @type {boolean}
22949		 * @default true
22950		 */
22951		this.fog = true;
22952
22953		this.setValues( parameters );
22954
22955	}
22956
22957	copy( source ) {
22958
22959		super.copy( source );
22960
22961		this.color.copy( source.color );
22962
22963		this.map = source.map;
22964
22965		this.lightMap = source.lightMap;
22966		this.lightMapIntensity = source.lightMapIntensity;
22967
22968		this.aoMap = source.aoMap;
22969		this.aoMapIntensity = source.aoMapIntensity;
22970
22971		this.specularMap = source.specularMap;
22972
22973		this.alphaMap = source.alphaMap;
22974
22975		this.envMap = source.envMap;
22976		this.envMapRotation.copy( source.envMapRotation );
22977		this.combine = source.combine;
22978		this.reflectivity = source.reflectivity;
22979		this.refractionRatio = source.refractionRatio;
22980
22981		this.wireframe = source.wireframe;
22982		this.wireframeLinewidth = source.wireframeLinewidth;
22983		this.wireframeLinecap = source.wireframeLinecap;
22984		this.wireframeLinejoin = source.wireframeLinejoin;
22985
22986		this.fog = source.fog;
22987
22988		return this;
22989
22990	}
22991
22992}
22993
22994const _inverseMatrix$3 = /*@__PURE__*/ new Matrix4();
22995const _ray$3 = /*@__PURE__*/ new Ray();
22996const _sphere$6 = /*@__PURE__*/ new Sphere();
22997const _sphereHitAt = /*@__PURE__*/ new Vector3();
22998
22999const _vA = /*@__PURE__*/ new Vector3();
23000const _vB = /*@__PURE__*/ new Vector3();
23001const _vC = /*@__PURE__*/ new Vector3();
23002
23003const _tempA = /*@__PURE__*/ new Vector3();
23004const _morphA = /*@__PURE__*/ new Vector3();
23005
23006const _intersectionPoint = /*@__PURE__*/ new Vector3();
23007const _intersectionPointWorld = /*@__PURE__*/ new Vector3();
23008
23009/**
23010 * Class representing triangular polygon mesh based objects.
23011 *
23012 * ```js
23013 * const geometry = new THREE.BoxGeometry( 1, 1, 1 );
23014 * const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
23015 * const mesh = new THREE.Mesh( geometry, material );
23016 * scene.add( mesh );
23017 * ```
23018 *
23019 * @augments Object3D
23020 */
23021class Mesh extends Object3D {
23022
23023	/**
23024	 * Constructs a new mesh.
23025	 *
23026	 * @param {BufferGeometry} [geometry] - The mesh geometry.
23027	 * @param {Material|Array<Material>} [material] - The mesh material.
23028	 */
23029	constructor( geometry = new BufferGeometry(), material = new MeshBasicMaterial() ) {
23030
23031		super();
23032
23033		/**
23034		 * This flag can be used for type testing.
23035		 *
23036		 * @type {boolean}
23037		 * @readonly
23038		 * @default true
23039		 */
23040		this.isMesh = true;
23041
23042		this.type = 'Mesh';
23043
23044		/**
23045		 * The mesh geometry.
23046		 *
23047		 * @type {BufferGeometry}
23048		 */
23049		this.geometry = geometry;
23050
23051		/**
23052		 * The mesh material.
23053		 *
23054		 * @type {Material|Array<Material>}
23055		 * @default MeshBasicMaterial
23056		 */
23057		this.material = material;
23058
23059		/**
23060		 * A dictionary representing the morph targets in the geometry. The key is the
23061		 * morph targets name, the value its attribute index. This member is `undefined`
23062		 * by default and only set when morph targets are detected in the geometry.
23063		 *
23064		 * @type {Object<string,number>|undefined}
23065		 * @default undefined
23066		 */
23067		this.morphTargetDictionary = undefined;
23068
23069		/**
23070		 * An array of weights typically in the range `[0,1]` that specify how much of the morph
23071		 * is applied. This member is `undefined` by default and only set when morph targets are
23072		 * detected in the geometry.
23073		 *
23074		 * @type {Array<number>|undefined}
23075		 * @default undefined
23076		 */
23077		this.morphTargetInfluences = undefined;
23078
23079		/**
23080		 * The number of instances of this mesh.
23081		 * Can only be used with {@link WebGPURenderer}.
23082		 *
23083		 * @type {number}
23084		 * @default 1
23085		 */
23086		this.count = 1;
23087
23088		this.updateMorphTargets();
23089
23090	}
23091
23092	copy( source, recursive ) {
23093
23094		super.copy( source, recursive );
23095
23096		if ( source.morphTargetInfluences !== undefined ) {
23097
23098			this.morphTargetInfluences = source.morphTargetInfluences.slice();
23099
23100		}
23101
23102		if ( source.morphTargetDictionary !== undefined ) {
23103
23104			this.morphTargetDictionary = Object.assign( {}, source.morphTargetDictionary );
23105
23106		}
23107
23108		this.material = Array.isArray( source.material ) ? source.material.slice() : source.material;
23109		this.geometry = source.geometry;
23110
23111		return this;
23112
23113	}
23114
vendor: 8,480 bytes, lines 23115-23448
23115	/**
23116	 * Sets the values of {@link Mesh#morphTargetDictionary} and {@link Mesh#morphTargetInfluences}
23117	 * to make sure existing morph targets can influence this 3D object.
23118	 */
23119	updateMorphTargets() {
23120
23121		const geometry = this.geometry;
23122
23123		const morphAttributes = geometry.morphAttributes;
23124		const keys = Object.keys( morphAttributes );
23125
23126		if ( keys.length > 0 ) {
23127
23128			const morphAttribute = morphAttributes[ keys[ 0 ] ];
23129
23130			if ( morphAttribute !== undefined ) {
23131
23132				this.morphTargetInfluences = [];
23133				this.morphTargetDictionary = {};
23134
23135				for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
23136
23137					const name = morphAttribute[ m ].name || String( m );
23138
23139					this.morphTargetInfluences.push( 0 );
23140					this.morphTargetDictionary[ name ] = m;
23141
23142				}
23143
23144			}
23145
23146		}
23147
23148	}
23149
23150	/**
23151	 * Returns the local-space position of the vertex at the given index, taking into
23152	 * account the current animation state of both morph targets and skinning.
23153	 *
23154	 * @param {number} index - The vertex index.
23155	 * @param {Vector3} target - The target object that is used to store the method's result.
23156	 * @return {Vector3} The vertex position in local space.
23157	 */
23158	getVertexPosition( index, target ) {
23159
23160		const geometry = this.geometry;
23161		const position = geometry.attributes.position;
23162		const morphPosition = geometry.morphAttributes.position;
23163		const morphTargetsRelative = geometry.morphTargetsRelative;
23164
23165		target.fromBufferAttribute( position, index );
23166
23167		const morphInfluences = this.morphTargetInfluences;
23168
23169		if ( morphPosition && morphInfluences ) {
23170
23171			_morphA.set( 0, 0, 0 );
23172
23173			for ( let i = 0, il = morphPosition.length; i < il; i ++ ) {
23174
23175				const influence = morphInfluences[ i ];
23176				const morphAttribute = morphPosition[ i ];
23177
23178				if ( influence === 0 ) continue;
23179
23180				_tempA.fromBufferAttribute( morphAttribute, index );
23181
23182				if ( morphTargetsRelative ) {
23183
23184					_morphA.addScaledVector( _tempA, influence );
23185
23186				} else {
23187
23188					_morphA.addScaledVector( _tempA.sub( target ), influence );
23189
23190				}
23191
23192			}
23193
23194			target.add( _morphA );
23195
23196		}
23197
23198		return target;
23199
23200	}
23201
23202	/**
23203	 * Computes intersection points between a casted ray and this line.
23204	 *
23205	 * @param {Raycaster} raycaster - The raycaster.
23206	 * @param {Array<Object>} intersects - The target array that holds the intersection points.
23207	 */
23208	raycast( raycaster, intersects ) {
23209
23210		const geometry = this.geometry;
23211		const material = this.material;
23212		const matrixWorld = this.matrixWorld;
23213
23214		if ( material === undefined ) return;
23215
23216		// test with bounding sphere in world space
23217
23218		if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
23219
23220		_sphere$6.copy( geometry.boundingSphere );
23221		_sphere$6.applyMatrix4( matrixWorld );
23222
23223		// check distance from ray origin to bounding sphere
23224
23225		_ray$3.copy( raycaster.ray ).recast( raycaster.near );
23226
23227		if ( _sphere$6.containsPoint( _ray$3.origin ) === false ) {
23228
23229			if ( _ray$3.intersectSphere( _sphere$6, _sphereHitAt ) === null ) return;
23230
23231			if ( _ray$3.origin.distanceToSquared( _sphereHitAt ) > ( raycaster.far - raycaster.near ) ** 2 ) return;
23232
23233		}
23234
23235		// convert ray to local space of mesh
23236
23237		_inverseMatrix$3.copy( matrixWorld ).invert();
23238		_ray$3.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$3 );
23239
23240		// test with bounding box in local space
23241
23242		if ( geometry.boundingBox !== null ) {
23243
23244			if ( _ray$3.intersectsBox( geometry.boundingBox ) === false ) return;
23245
23246		}
23247
23248		// test for intersections with geometry
23249
23250		this._computeIntersections( raycaster, intersects, _ray$3 );
23251
23252	}
23253
23254	_computeIntersections( raycaster, intersects, rayLocalSpace ) {
23255
23256		let intersection;
23257
23258		const geometry = this.geometry;
23259		const material = this.material;
23260
23261		const index = geometry.index;
23262		const position = geometry.attributes.position;
23263		const uv = geometry.attributes.uv;
23264		const uv1 = geometry.attributes.uv1;
23265		const normal = geometry.attributes.normal;
23266		const groups = geometry.groups;
23267		const drawRange = geometry.drawRange;
23268
23269		if ( index !== null ) {
23270
23271			// indexed buffer geometry
23272
23273			if ( Array.isArray( material ) ) {
23274
23275				for ( let i = 0, il = groups.length; i < il; i ++ ) {
23276
23277					const group = groups[ i ];
23278					const groupMaterial = material[ group.materialIndex ];
23279
23280					const start = Math.max( group.start, drawRange.start );
23281					const end = Math.min( index.count, Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) ) );
23282
23283					for ( let j = start, jl = end; j < jl; j += 3 ) {
23284
23285						const a = index.getX( j );
23286						const b = index.getX( j + 1 );
23287						const c = index.getX( j + 2 );
23288
23289						intersection = checkGeometryIntersection( this, groupMaterial, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c );
23290
23291						if ( intersection ) {
23292
23293							intersection.faceIndex = Math.floor( j / 3 ); // triangle number in indexed buffer semantics
23294							intersection.face.materialIndex = group.materialIndex;
23295							intersects.push( intersection );
23296
23297						}
23298
23299					}
23300
23301				}
23302
23303			} else {
23304
23305				const start = Math.max( 0, drawRange.start );
23306				const end = Math.min( index.count, ( drawRange.start + drawRange.count ) );
23307
23308				for ( let i = start, il = end; i < il; i += 3 ) {
23309
23310					const a = index.getX( i );
23311					const b = index.getX( i + 1 );
23312					const c = index.getX( i + 2 );
23313
23314					intersection = checkGeometryIntersection( this, material, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c );
23315
23316					if ( intersection ) {
23317
23318						intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indexed buffer semantics
23319						intersects.push( intersection );
23320
23321					}
23322
23323				}
23324
23325			}
23326
23327		} else if ( position !== undefined ) {
23328
23329			// non-indexed buffer geometry
23330
23331			if ( Array.isArray( material ) ) {
23332
23333				for ( let i = 0, il = groups.length; i < il; i ++ ) {
23334
23335					const group = groups[ i ];
23336					const groupMaterial = material[ group.materialIndex ];
23337
23338					const start = Math.max( group.start, drawRange.start );
23339					const end = Math.min( position.count, Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) ) );
23340
23341					for ( let j = start, jl = end; j < jl; j += 3 ) {
23342
23343						const a = j;
23344						const b = j + 1;
23345						const c = j + 2;
23346
23347						intersection = checkGeometryIntersection( this, groupMaterial, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c );
23348
23349						if ( intersection ) {
23350
23351							intersection.faceIndex = Math.floor( j / 3 ); // triangle number in non-indexed buffer semantics
23352							intersection.face.materialIndex = group.materialIndex;
23353							intersects.push( intersection );
23354
23355						}
23356
23357					}
23358
23359				}
23360
23361			} else {
23362
23363				const start = Math.max( 0, drawRange.start );
23364				const end = Math.min( position.count, ( drawRange.start + drawRange.count ) );
23365
23366				for ( let i = start, il = end; i < il; i += 3 ) {
23367
23368					const a = i;
23369					const b = i + 1;
23370					const c = i + 2;
23371
23372					intersection = checkGeometryIntersection( this, material, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c );
23373
23374					if ( intersection ) {
23375
23376						intersection.faceIndex = Math.floor( i / 3 ); // triangle number in non-indexed buffer semantics
23377						intersects.push( intersection );
23378
23379					}
23380
23381				}
23382
23383			}
23384
23385		}
23386
23387	}
23388
23389}
23390
23391function checkIntersection$1( object, material, raycaster, ray, pA, pB, pC, point ) {
23392
23393	let intersect;
23394
23395	if ( material.side === BackSide ) {
23396
23397		intersect = ray.intersectTriangle( pC, pB, pA, true, point );
23398
23399	} else {
23400
23401		intersect = ray.intersectTriangle( pA, pB, pC, ( material.side === FrontSide ), point );
23402
23403	}
23404
23405	if ( intersect === null ) return null;
23406
23407	_intersectionPointWorld.copy( point );
23408	_intersectionPointWorld.applyMatrix4( object.matrixWorld );
23409
23410	const distance = raycaster.ray.origin.distanceTo( _intersectionPointWorld );
23411
23412	if ( distance < raycaster.near || distance > raycaster.far ) return null;
23413
23414	return {
23415		distance: distance,
23416		point: _intersectionPointWorld.clone(),
23417		object: object
23418	};
23419
23420}
23421
23422function checkGeometryIntersection( object, material, raycaster, ray, uv, uv1, normal, a, b, c ) {
23423
23424	object.getVertexPosition( a, _vA );
23425	object.getVertexPosition( b, _vB );
23426	object.getVertexPosition( c, _vC );
23427
23428	const intersection = checkIntersection$1( object, material, raycaster, ray, _vA, _vB, _vC, _intersectionPoint );
23429
23430	if ( intersection ) {
23431
23432		const barycoord = new Vector3();
23433		Triangle.getBarycoord( _intersectionPoint, _vA, _vB, _vC, barycoord );
23434
23435		if ( uv ) {
23436
23437			intersection.uv = Triangle.getInterpolatedAttribute( uv, a, b, c, barycoord, new Vector2() );
23438
23439		}
23440
23441		if ( uv1 ) {
23442
23443			intersection.uv1 = Triangle.getInterpolatedAttribute( uv1, a, b, c, barycoord, new Vector2() );
23444
23445		}
23446
23447		if ( normal ) {
23448
vendor: 13,640 bytes, lines 23449-24021
23449			intersection.normal = Triangle.getInterpolatedAttribute( normal, a, b, c, barycoord, new Vector3() );
23450
23451			if ( intersection.normal.dot( ray.direction ) > 0 ) {
23452
23453				intersection.normal.multiplyScalar( -1 );
23454
23455			}
23456
23457		}
23458
23459		const face = {
23460			a: a,
23461			b: b,
23462			c: c,
23463			normal: new Vector3(),
23464			materialIndex: 0
23465		};
23466
23467		Triangle.getNormal( _vA, _vB, _vC, face.normal );
23468
23469		intersection.face = face;
23470		intersection.barycoord = barycoord;
23471
23472	}
23473
23474	return intersection;
23475
23476}
23477
23478const _baseVector = /*@__PURE__*/ new Vector4();
23479
23480const _skinIndex = /*@__PURE__*/ new Vector4();
23481const _skinWeight = /*@__PURE__*/ new Vector4();
23482
23483const _vector4 = /*@__PURE__*/ new Vector4();
23484const _matrix4 = /*@__PURE__*/ new Matrix4();
23485const _vertex = /*@__PURE__*/ new Vector3();
23486
23487const _sphere$5 = /*@__PURE__*/ new Sphere();
23488const _inverseMatrix$2 = /*@__PURE__*/ new Matrix4();
23489const _ray$2 = /*@__PURE__*/ new Ray();
23490
23491/**
23492 * A mesh that has a {@link Skeleton} that can then be used to animate the
23493 * vertices of the geometry with skinning/skeleton animation.
23494 *
23495 * Next to a valid skeleton, the skinned mesh requires skin indices and weights
23496 * as buffer attributes in its geometry. These attribute define which bones affect a single
23497 * vertex to a certain extend.
23498 *
23499 * Typically skinned meshes are not created manually but loaders like {@link GLTFLoader}
23500 * or {@link FBXLoader } import respective models.
23501 *
23502 * @augments Mesh
23503 * @demo scenes/bones-browser.html
23504 */
23505class SkinnedMesh extends Mesh {
23506
23507	/**
23508	 * Constructs a new skinned mesh.
23509	 *
23510	 * @param {BufferGeometry} [geometry] - The mesh geometry.
23511	 * @param {Material|Array<Material>} [material] - The mesh material.
23512	 */
23513	constructor( geometry, material ) {
23514
23515		super( geometry, material );
23516
23517		/**
23518		 * This flag can be used for type testing.
23519		 *
23520		 * @type {boolean}
23521		 * @readonly
23522		 * @default true
23523		 */
23524		this.isSkinnedMesh = true;
23525
23526		this.type = 'SkinnedMesh';
23527
23528		/**
23529		 * `AttachedBindMode` means the skinned mesh shares the same world space as the skeleton.
23530		 * This is not true when using `DetachedBindMode` which is useful when sharing a skeleton
23531		 * across multiple skinned meshes.
23532		 *
23533		 * @type {(AttachedBindMode|DetachedBindMode)}
23534		 * @default AttachedBindMode
23535		 */
23536		this.bindMode = AttachedBindMode;
23537
23538		/**
23539		 * The base matrix that is used for the bound bone transforms.
23540		 *
23541		 * @type {Matrix4}
23542		 */
23543		this.bindMatrix = new Matrix4();
23544
23545		/**
23546		 * The base matrix that is used for resetting the bound bone transforms.
23547		 *
23548		 * @type {Matrix4}
23549		 */
23550		this.bindMatrixInverse = new Matrix4();
23551
23552		/**
23553		 * The bounding box of the skinned mesh. Can be computed via {@link SkinnedMesh#computeBoundingBox}.
23554		 *
23555		 * @type {?Box3}
23556		 * @default null
23557		 */
23558		this.boundingBox = null;
23559
23560		/**
23561		 * The bounding sphere of the skinned mesh. Can be computed via {@link SkinnedMesh#computeBoundingSphere}.
23562		 *
23563		 * @type {?Sphere}
23564		 * @default null
23565		 */
23566		this.boundingSphere = null;
23567
23568	}
23569
23570	/**
23571	 * Computes the bounding box of the skinned mesh, and updates {@link SkinnedMesh#boundingBox}.
23572	 * The bounding box is not automatically computed by the engine; this method must be called by your app.
23573	 * If the skinned mesh is animated, the bounding box should be recomputed per frame in order to reflect
23574	 * the current animation state.
23575	 */
23576	computeBoundingBox() {
23577
23578		const geometry = this.geometry;
23579
23580		if ( this.boundingBox === null ) {
23581
23582			this.boundingBox = new Box3();
23583
23584		}
23585
23586		this.boundingBox.makeEmpty();
23587
23588		const positionAttribute = geometry.getAttribute( 'position' );
23589
23590		for ( let i = 0; i < positionAttribute.count; i ++ ) {
23591
23592			this.getVertexPosition( i, _vertex );
23593			this.boundingBox.expandByPoint( _vertex );
23594
23595		}
23596
23597	}
23598
23599	/**
23600	 * Computes the bounding sphere of the skinned mesh, and updates {@link SkinnedMesh#boundingSphere}.
23601	 * The bounding sphere is automatically computed by the engine once when it is needed, e.g., for ray casting
23602	 * and view frustum culling. If the skinned mesh is animated, the bounding sphere should be recomputed
23603	 * per frame in order to reflect the current animation state.
23604	 */
23605	computeBoundingSphere() {
23606
23607		const geometry = this.geometry;
23608
23609		if ( this.boundingSphere === null ) {
23610
23611			this.boundingSphere = new Sphere();
23612
23613		}
23614
23615		this.boundingSphere.makeEmpty();
23616
23617		const positionAttribute = geometry.getAttribute( 'position' );
23618
23619		for ( let i = 0; i < positionAttribute.count; i ++ ) {
23620
23621			this.getVertexPosition( i, _vertex );
23622			this.boundingSphere.expandByPoint( _vertex );
23623
23624		}
23625
23626	}
23627
23628	copy( source, recursive ) {
23629
23630		super.copy( source, recursive );
23631
23632		this.bindMode = source.bindMode;
23633		this.bindMatrix.copy( source.bindMatrix );
23634		this.bindMatrixInverse.copy( source.bindMatrixInverse );
23635
23636		this.skeleton = source.skeleton;
23637
23638		if ( source.boundingBox !== null ) this.boundingBox = source.boundingBox.clone();
23639		if ( source.boundingSphere !== null ) this.boundingSphere = source.boundingSphere.clone();
23640
23641		return this;
23642
23643	}
23644
23645	raycast( raycaster, intersects ) {
23646
23647		const material = this.material;
23648		const matrixWorld = this.matrixWorld;
23649
23650		if ( material === undefined ) return;
23651
23652		// test with bounding sphere in world space
23653
23654		if ( this.boundingSphere === null ) this.computeBoundingSphere();
23655
23656		_sphere$5.copy( this.boundingSphere );
23657		_sphere$5.applyMatrix4( matrixWorld );
23658
23659		if ( raycaster.ray.intersectsSphere( _sphere$5 ) === false ) return;
23660
23661		// convert ray to local space of skinned mesh
23662
23663		_inverseMatrix$2.copy( matrixWorld ).invert();
23664		_ray$2.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$2 );
23665
23666		// test with bounding box in local space
23667
23668		if ( this.boundingBox !== null ) {
23669
23670			if ( _ray$2.intersectsBox( this.boundingBox ) === false ) return;
23671
23672		}
23673
23674		// test for intersections with geometry
23675
23676		this._computeIntersections( raycaster, intersects, _ray$2 );
23677
23678	}
23679
23680	getVertexPosition( index, target ) {
23681
23682		super.getVertexPosition( index, target );
23683
23684		this.applyBoneTransform( index, target );
23685
23686		return target;
23687
23688	}
23689
23690	/**
23691	 * Binds the given skeleton to the skinned mesh.
23692	 *
23693	 * @param {Skeleton} skeleton - The skeleton to bind.
23694	 * @param {Matrix4} [bindMatrix] - The bind matrix. If no bind matrix is provided,
23695	 * the skinned mesh's world matrix will be used instead.
23696	 */
23697	bind( skeleton, bindMatrix ) {
23698
23699		this.skeleton = skeleton;
23700
23701		if ( bindMatrix === undefined ) {
23702
23703			this.updateMatrixWorld( true );
23704
23705			this.skeleton.calculateInverses();
23706
23707			bindMatrix = this.matrixWorld;
23708
23709		}
23710
23711		this.bindMatrix.copy( bindMatrix );
23712		this.bindMatrixInverse.copy( bindMatrix ).invert();
23713
23714	}
23715
23716	/**
23717	 * This method sets the skinned mesh in the rest pose).
23718	 */
23719	pose() {
23720
23721		this.skeleton.pose();
23722
23723	}
23724
23725	/**
23726	 * Normalizes the skin weights which are defined as a buffer attribute
23727	 * in the skinned mesh's geometry.
23728	 */
23729	normalizeSkinWeights() {
23730
23731		const vector = new Vector4();
23732
23733		const skinWeight = this.geometry.attributes.skinWeight;
23734
23735		for ( let i = 0, l = skinWeight.count; i < l; i ++ ) {
23736
23737			vector.fromBufferAttribute( skinWeight, i );
23738
23739			const scale = 1.0 / vector.manhattanLength();
23740
23741			if ( scale !== Infinity ) {
23742
23743				vector.multiplyScalar( scale );
23744
23745			} else {
23746
23747				vector.set( 1, 0, 0, 0 ); // do something reasonable
23748
23749			}
23750
23751			skinWeight.setXYZW( i, vector.x, vector.y, vector.z, vector.w );
23752
23753		}
23754
23755	}
23756
23757	updateMatrixWorld( force ) {
23758
23759		super.updateMatrixWorld( force );
23760
23761		if ( this.bindMode === AttachedBindMode ) {
23762
23763			this.bindMatrixInverse.copy( this.matrixWorld ).invert();
23764
23765		} else if ( this.bindMode === DetachedBindMode ) {
23766
23767			this.bindMatrixInverse.copy( this.bindMatrix ).invert();
23768
23769		} else {
23770
23771			warn( 'SkinnedMesh: Unrecognized bindMode: ' + this.bindMode );
23772
23773		}
23774
23775	}
23776
23777	/**
23778	 * Applies the bone transform associated with the given index to the given
23779	 * vector. Can be used to transform positions or direction vectors by providing
23780	 * a Vector4 with 1 or 0 in the w component respectively. Returns the updated vector.
23781	 *
23782	 * @param {number} index - The vertex index.
23783	 * @param {Vector3|Vector4} target - The target object that is used to store the method's result.
23784	 * @return {Vector3|Vector4} The updated vertex attribute data.
23785	 */
23786	applyBoneTransform( index, target ) {
23787
23788		const skeleton = this.skeleton;
23789		const geometry = this.geometry;
23790
23791		_skinIndex.fromBufferAttribute( geometry.attributes.skinIndex, index );
23792		_skinWeight.fromBufferAttribute( geometry.attributes.skinWeight, index );
23793
23794		if ( target.isVector4 ) {
23795
23796			_baseVector.copy( target );
23797			target.set( 0, 0, 0, 0 );
23798
23799		} else {
23800
23801			_baseVector.set( ...target, 1 );
23802			target.set( 0, 0, 0 );
23803
23804		}
23805
23806		_baseVector.applyMatrix4( this.bindMatrix );
23807
23808		for ( let i = 0; i < 4; i ++ ) {
23809
23810			const weight = _skinWeight.getComponent( i );
23811
23812			if ( weight !== 0 ) {
23813
23814				const boneIndex = _skinIndex.getComponent( i );
23815
23816				_matrix4.multiplyMatrices( skeleton.bones[ boneIndex ].matrixWorld, skeleton.boneInverses[ boneIndex ] );
23817
23818				target.addScaledVector( _vector4.copy( _baseVector ).applyMatrix4( _matrix4 ), weight );
23819
23820			}
23821
23822		}
23823
23824		if ( target.isVector4 ) {
23825
23826			// ensure the homogenous coordinate remains unchanged after vector operations
23827			target.w = _baseVector.w;
23828
23829		}
23830
23831		return target.applyMatrix4( this.bindMatrixInverse );
23832
23833	}
23834
23835}
23836
23837/**
23838 * A bone which is part of a {@link Skeleton}. The skeleton in turn is used by
23839 * the {@link SkinnedMesh}.
23840 *
23841 * ```js
23842 * const root = new THREE.Bone();
23843 * const child = new THREE.Bone();
23844 *
23845 * root.add( child );
23846 * child.position.y = 5;
23847 * ```
23848 *
23849 * @augments Object3D
23850 */
23851class Bone extends Object3D {
23852
23853	/**
23854	 * Constructs a new bone.
23855	 */
23856	constructor() {
23857
23858		super();
23859
23860		/**
23861		 * This flag can be used for type testing.
23862		 *
23863		 * @type {boolean}
23864		 * @readonly
23865		 * @default true
23866		 */
23867		this.isBone = true;
23868
23869		this.type = 'Bone';
23870
23871	}
23872
23873}
23874
23875/**
23876 * Creates a texture directly from raw buffer data.
23877 *
23878 * The interpretation of the data depends on type and format: If the type is
23879 * `UnsignedByteType`, a `Uint8Array` will be useful for addressing the
23880 * texel data. If the format is `RGBAFormat`, data needs four values for
23881 * one texel; Red, Green, Blue and Alpha (typically the opacity).
23882 *
23883 * @augments Texture
23884 */
23885class DataTexture extends Texture {
23886
23887	/**
23888	 * Constructs a new data texture.
23889	 *
23890	 * @param {?TypedArray} [data=null] - The buffer data.
23891	 * @param {number} [width=1] - The width of the texture.
23892	 * @param {number} [height=1] - The height of the texture.
23893	 * @param {number} [format=RGBAFormat] - The texture format.
23894	 * @param {number} [type=UnsignedByteType] - The texture type.
23895	 * @param {number} [mapping=Texture.DEFAULT_MAPPING] - The texture mapping.
23896	 * @param {number} [wrapS=ClampToEdgeWrapping] - The wrapS value.
23897	 * @param {number} [wrapT=ClampToEdgeWrapping] - The wrapT value.
23898	 * @param {number} [magFilter=NearestFilter] - The mag filter value.
23899	 * @param {number} [minFilter=NearestFilter] - The min filter value.
23900	 * @param {number} [anisotropy=Texture.DEFAULT_ANISOTROPY] - The anisotropy value.
23901	 * @param {string} [colorSpace=NoColorSpace] - The color space.
23902	 */
23903	constructor( data = null, width = 1, height = 1, format, type, mapping, wrapS, wrapT, magFilter = NearestFilter, minFilter = NearestFilter, anisotropy, colorSpace ) {
23904
23905		super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace );
23906
23907		/**
23908		 * This flag can be used for type testing.
23909		 *
23910		 * @type {boolean}
23911		 * @readonly
23912		 * @default true
23913		 */
23914		this.isDataTexture = true;
23915
23916		/**
23917		 * The image definition of a data texture.
23918		 *
23919		 * @type {{data:TypedArray,width:number,height:number}}
23920		 */
23921		this.image = { data: data, width: width, height: height };
23922
23923		/**
23924		 * Whether to generate mipmaps (if possible) for a texture.
23925		 *
23926		 * Overwritten and set to `false` by default.
23927		 *
23928		 * @type {boolean}
23929		 * @default false
23930		 */
23931		this.generateMipmaps = false;
23932
23933		/**
23934		 * If set to `true`, the texture is flipped along the vertical axis when
23935		 * uploaded to the GPU.
23936		 *
23937		 * Overwritten and set to `false` by default.
23938		 *
23939		 * @type {boolean}
23940		 * @default false
23941		 */
23942		this.flipY = false;
23943
23944		/**
23945		 * Specifies the alignment requirements for the start of each pixel row in memory.
23946		 *
23947		 * Overwritten and set to `1` by default.
23948		 *
23949		 * @type {boolean}
23950		 * @default 1
23951		 */
23952		this.unpackAlignment = 1;
23953
23954	}
23955
23956}
23957
23958const _offsetMatrix = /*@__PURE__*/ new Matrix4();
23959const _identityMatrix = /*@__PURE__*/ new Matrix4();
23960
23961/**
23962 * Class for representing the armatures in `three.js`. The skeleton
23963 * is defined by a hierarchy of bones.
23964 *
23965 * ```js
23966 * const bones = [];
23967 *
23968 * const shoulder = new THREE.Bone();
23969 * const elbow = new THREE.Bone();
23970 * const hand = new THREE.Bone();
23971 *
23972 * shoulder.add( elbow );
23973 * elbow.add( hand );
23974 *
23975 * bones.push( shoulder , elbow, hand);
23976 *
23977 * shoulder.position.y = -5;
23978 * elbow.position.y = 0;
23979 * hand.position.y = 5;
23980 *
23981 * const armSkeleton = new THREE.Skeleton( bones );
23982 * ```
23983 */
23984class Skeleton {
23985
23986	/**
23987	 * Constructs a new skeleton.
23988	 *
23989	 * @param {Array<Bone>} [bones] - An array of bones.
23990	 * @param {Array<Matrix4>} [boneInverses] - An array of bone inverse matrices.
23991	 * If not provided, these matrices will be computed automatically via {@link Skeleton#calculateInverses}.
23992	 */
23993	constructor( bones = [], boneInverses = [] ) {
23994
23995		this.uuid = generateUUID();
23996
23997		/**
23998		 * An array of bones defining the skeleton.
23999		 *
24000		 * @type {Array<Bone>}
24001		 */
24002		this.bones = bones.slice( 0 );
24003
24004		/**
24005		 * An array of bone inverse matrices.
24006		 *
24007		 * @type {Array<Matrix4>}
24008		 */
24009		this.boneInverses = boneInverses;
24010
24011		/**
24012		 * An array buffer holding the bone data.
24013		 * Input data for {@link Skeleton#boneTexture}.
24014		 *
24015		 * @type {?Float32Array}
24016		 * @default null
24017		 */
24018		this.boneMatrices = null;
24019
24020		/**
24021		 * A
vendor: 10,843 bytes, lines 24021-24513
24021n array buffer holding the bone data of the previous frame.
24022		 * Required for computing velocity. Maintained in {@link SkinningNode}.
24023		 *
24024		 * @type {?Float32Array}
24025		 * @default null
24026		 */
24027		this.previousBoneMatrices = null;
24028
24029		/**
24030		 * A texture holding the bone data for use
24031		 * in the vertex shader.
24032		 *
24033		 * @type {?DataTexture}
24034		 * @default null
24035		 */
24036		this.boneTexture = null;
24037
24038		this.init();
24039
24040	}
24041
24042	/**
24043	 * Initializes the skeleton. This method gets automatically called by the constructor
24044	 * but depending on how the skeleton is created it might be necessary to call this method
24045	 * manually.
24046	 */
24047	init() {
24048
24049		const bones = this.bones;
24050		const boneInverses = this.boneInverses;
24051
24052		this.boneMatrices = new Float32Array( bones.length * 16 );
24053
24054		// calculate inverse bone matrices if necessary
24055
24056		if ( boneInverses.length === 0 ) {
24057
24058			this.calculateInverses();
24059
24060		} else {
24061
24062			// handle special case
24063
24064			if ( bones.length !== boneInverses.length ) {
24065
24066				warn( 'Skeleton: Number of inverse bone matrices does not match amount of bones.' );
24067
24068				this.boneInverses = [];
24069
24070				for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
24071
24072					this.boneInverses.push( new Matrix4() );
24073
24074				}
24075
24076			}
24077
24078		}
24079
24080	}
24081
24082	/**
24083	 * Computes the bone inverse matrices. This method resets {@link Skeleton#boneInverses}
24084	 * and fills it with new matrices.
24085	 */
24086	calculateInverses() {
24087
24088		this.boneInverses.length = 0;
24089
24090		for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
24091
24092			const inverse = new Matrix4();
24093
24094			if ( this.bones[ i ] ) {
24095
24096				inverse.copy( this.bones[ i ].matrixWorld ).invert();
24097
24098			}
24099
24100			this.boneInverses.push( inverse );
24101
24102		}
24103
24104	}
24105
24106	/**
24107	 * Resets the skeleton to the base pose.
24108	 */
24109	pose() {
24110
24111		// recover the bind-time world matrices
24112
24113		for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
24114
24115			const bone = this.bones[ i ];
24116
24117			if ( bone ) {
24118
24119				bone.matrixWorld.copy( this.boneInverses[ i ] ).invert();
24120
24121			}
24122
24123		}
24124
24125		// compute the local matrices, positions, rotations and scales
24126
24127		for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
24128
24129			const bone = this.bones[ i ];
24130
24131			if ( bone ) {
24132
24133				if ( bone.parent && bone.parent.isBone ) {
24134
24135					bone.matrix.copy( bone.parent.matrixWorld ).invert();
24136					bone.matrix.multiply( bone.matrixWorld );
24137
24138				} else {
24139
24140					bone.matrix.copy( bone.matrixWorld );
24141
24142				}
24143
24144				bone.matrix.decompose( bone.position, bone.quaternion, bone.scale );
24145
24146			}
24147
24148		}
24149
24150	}
24151
24152	/**
24153	 * Resets the skeleton to the base pose.
24154	 */
24155	update() {
24156
24157		const bones = this.bones;
24158		const boneInverses = this.boneInverses;
24159		const boneMatrices = this.boneMatrices;
24160		const boneTexture = this.boneTexture;
24161
24162		// flatten bone matrices to array
24163
24164		for ( let i = 0, il = bones.length; i < il; i ++ ) {
24165
24166			// compute the offset between the current and the original transform
24167
24168			const matrix = bones[ i ] ? bones[ i ].matrixWorld : _identityMatrix;
24169
24170			_offsetMatrix.multiplyMatrices( matrix, boneInverses[ i ] );
24171			_offsetMatrix.toArray( boneMatrices, i * 16 );
24172
24173		}
24174
24175		if ( boneTexture !== null ) {
24176
24177			boneTexture.needsUpdate = true;
24178
24179		}
24180
24181	}
24182
24183	/**
24184	 * Returns a new skeleton with copied values from this instance.
24185	 *
24186	 * @return {Skeleton} A clone of this instance.
24187	 */
24188	clone() {
24189
24190		return new Skeleton( this.bones, this.boneInverses );
24191
24192	}
24193
24194	/**
24195	 * Computes a data texture for passing bone data to the vertex shader.
24196	 *
24197	 * @return {Skeleton} A reference of this instance.
24198	 */
24199	computeBoneTexture() {
24200
24201		// layout (1 matrix = 4 pixels)
24202		//      RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)
24203		//  with  8x8  pixel texture max   16 bones * 4 pixels =  (8 * 8)
24204		//       16x16 pixel texture max   64 bones * 4 pixels = (16 * 16)
24205		//       32x32 pixel texture max  256 bones * 4 pixels = (32 * 32)
24206		//       64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64)
24207
24208		let size = Math.sqrt( this.bones.length * 4 ); // 4 pixels needed for 1 matrix
24209		size = Math.ceil( size / 4 ) * 4;
24210		size = Math.max( size, 4 );
24211
24212		const boneMatrices = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel
24213		boneMatrices.set( this.boneMatrices ); // copy current values
24214
24215		const boneTexture = new DataTexture( boneMatrices, size, size, RGBAFormat, FloatType );
24216		boneTexture.needsUpdate = true;
24217
24218		this.boneMatrices = boneMatrices;
24219		this.boneTexture = boneTexture;
24220
24221		return this;
24222
24223	}
24224
24225	/**
24226	 * Searches through the skeleton's bone array and returns the first with a
24227	 * matching name.
24228	 *
24229	 * @param {string} name - The name of the bone.
24230	 * @return {Bone|undefined} The found bone. `undefined` if no bone has been found.
24231	 */
24232	getBoneByName( name ) {
24233
24234		for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
24235
24236			const bone = this.bones[ i ];
24237
24238			if ( bone.name === name ) {
24239
24240				return bone;
24241
24242			}
24243
24244		}
24245
24246		return undefined;
24247
24248	}
24249
24250	/**
24251	 * Frees the GPU-related resources allocated by this instance. Call this
24252	 * method whenever this instance is no longer used in your app.
24253	 */
24254	dispose( ) {
24255
24256		if ( this.boneTexture !== null ) {
24257
24258			this.boneTexture.dispose();
24259
24260			this.boneTexture = null;
24261
24262		}
24263
24264	}
24265
24266	/**
24267	 * Setups the skeleton by the given JSON and bones.
24268	 *
24269	 * @param {Object} json - The skeleton as serialized JSON.
24270	 * @param {Object<string, Bone>} bones - An array of bones.
24271	 * @return {Skeleton} A reference of this instance.
24272	 */
24273	fromJSON( json, bones ) {
24274
24275		this.uuid = json.uuid;
24276
24277		for ( let i = 0, l = json.bones.length; i < l; i ++ ) {
24278
24279			const uuid = json.bones[ i ];
24280			let bone = bones[ uuid ];
24281
24282			if ( bone === undefined ) {
24283
24284				warn( 'Skeleton: No bone found with UUID:', uuid );
24285				bone = new Bone();
24286
24287			}
24288
24289			this.bones.push( bone );
24290			this.boneInverses.push( new Matrix4().fromArray( json.boneInverses[ i ] ) );
24291
24292		}
24293
24294		this.init();
24295
24296		return this;
24297
24298	}
24299
24300	/**
24301	 * Serializes the skeleton into JSON.
24302	 *
24303	 * @return {Object} A JSON object representing the serialized skeleton.
24304	 * @see {@link ObjectLoader#parse}
24305	 */
24306	toJSON() {
24307
24308		const data = {
24309			metadata: {
24310				version: 4.7,
24311				type: 'Skeleton',
24312				generator: 'Skeleton.toJSON'
24313			},
24314			bones: [],
24315			boneInverses: []
24316		};
24317
24318		data.uuid = this.uuid;
24319
24320		const bones = this.bones;
24321		const boneInverses = this.boneInverses;
24322
24323		for ( let i = 0, l = bones.length; i < l; i ++ ) {
24324
24325			const bone = bones[ i ];
24326			data.bones.push( bone.uuid );
24327
24328			const boneInverse = boneInverses[ i ];
24329			data.boneInverses.push( boneInverse.toArray() );
24330
24331		}
24332
24333		return data;
24334
24335	}
24336
24337}
24338
24339/**
24340 * An instanced version of a buffer attribute.
24341 *
24342 * @augments BufferAttribute
24343 */
24344class InstancedBufferAttribute extends BufferAttribute {
24345
24346	/**
24347	 * Constructs a new instanced buffer attribute.
24348	 *
24349	 * @param {TypedArray} array - The array holding the attribute data.
24350	 * @param {number} itemSize - The item size.
24351	 * @param {boolean} [normalized=false] - Whether the data are normalized or not.
24352	 * @param {number} [meshPerAttribute=1] - How often a value of this buffer attribute should be repeated.
24353	 */
24354	constructor( array, itemSize, normalized, meshPerAttribute = 1 ) {
24355
24356		super( array, itemSize, normalized );
24357
24358		/**
24359		 * This flag can be used for type testing.
24360		 *
24361		 * @type {boolean}
24362		 * @readonly
24363		 * @default true
24364		 */
24365		this.isInstancedBufferAttribute = true;
24366
24367		/**
24368		 * Defines how often a value of this buffer attribute should be repeated. A
24369		 * value of one means that each value of the instanced attribute is used for
24370		 * a single instance. A value of two means that each value is used for two
24371		 * consecutive instances (and so on).
24372		 *
24373		 * @type {number}
24374		 * @default 1
24375		 */
24376		this.meshPerAttribute = meshPerAttribute;
24377
24378	}
24379
24380	copy( source ) {
24381
24382		super.copy( source );
24383
24384		this.meshPerAttribute = source.meshPerAttribute;
24385
24386		return this;
24387
24388	}
24389
24390	toJSON() {
24391
24392		const data = super.toJSON();
24393
24394		data.meshPerAttribute = this.meshPerAttribute;
24395
24396		data.isInstancedBufferAttribute = true;
24397
24398		return data;
24399
24400	}
24401
24402}
24403
24404const _instanceLocalMatrix = /*@__PURE__*/ new Matrix4();
24405const _instanceWorldMatrix = /*@__PURE__*/ new Matrix4();
24406
24407const _instanceIntersects = [];
24408
24409const _box3 = /*@__PURE__*/ new Box3();
24410const _identity = /*@__PURE__*/ new Matrix4();
24411const _mesh$1 = /*@__PURE__*/ new Mesh();
24412const _sphere$4 = /*@__PURE__*/ new Sphere();
24413
24414/**
24415 * A special version of a mesh with instanced rendering support. Use
24416 * this class if you have to render a large number of objects with the same
24417 * geometry and material(s) but with different world transformations. The usage
24418 * of 'InstancedMesh' will help you to reduce the number of draw calls and thus
24419 * improve the overall rendering performance in your application.
24420 *
24421 * @augments Mesh
24422 */
24423class InstancedMesh extends Mesh {
24424
24425	/**
24426	 * Constructs a new instanced mesh.
24427	 *
24428	 * @param {BufferGeometry} [geometry] - The mesh geometry.
24429	 * @param {Material|Array<Material>} [material] - The mesh material.
24430	 * @param {number} count - The number of instances.
24431	 */
24432	constructor( geometry, material, count ) {
24433
24434		super( geometry, material );
24435
24436		/**
24437		 * This flag can be used for type testing.
24438		 *
24439		 * @type {boolean}
24440		 * @readonly
24441		 * @default true
24442		 */
24443		this.isInstancedMesh = true;
24444
24445		/**
24446		 * Represents the local transformation of all instances. You have to set its
24447		 * {@link BufferAttribute#needsUpdate} flag to true if you modify instanced data
24448		 * via {@link InstancedMesh#setMatrixAt}.
24449		 *
24450		 * @type {InstancedBufferAttribute}
24451		 */
24452		this.instanceMatrix = new InstancedBufferAttribute( new Float32Array( count * 16 ), 16 );
24453
24454		/**
24455		 * Represents the local transformation of all instances of the previous frame.
24456		 * Required for computing velocity. Maintained in {@link InstanceNode}.
24457		 *
24458		 * @type {?InstancedBufferAttribute}
24459		 * @default null
24460		 */
24461		this.previousInstanceMatrix = null;
24462
24463		/**
24464		 * Represents the color of all instances. You have to set its
24465		 * {@link BufferAttribute#needsUpdate} flag to true if you modify instanced data
24466		 * via {@link InstancedMesh#setColorAt}.
24467		 *
24468		 * @type {?InstancedBufferAttribute}
24469		 * @default null
24470		 */
24471		this.instanceColor = null;
24472
24473		/**
24474		 * Represents the morph target weights of all instances. You have to set its
24475		 * {@link Texture#needsUpdate} flag to true if you modify instanced data
24476		 * via {@link InstancedMesh#setMorphAt}.
24477		 *
24478		 * @type {?DataTexture}
24479		 * @default null
24480		 */
24481		this.morphTexture = null;
24482
24483		/**
24484		 * The number of instances.
24485		 *
24486		 * @type {number}
24487		 */
24488		this.count = count;
24489
24490		/**
24491		 * The bounding box of the instanced mesh. Can be computed via {@link InstancedMesh#computeBoundingBox}.
24492		 *
24493		 * @type {?Box3}
24494		 * @default null
24495		 */
24496		this.boundingBox = null;
24497
24498		/**
24499		 * The bounding sphere of the instanced mesh. Can be computed via {@link InstancedMesh#computeBoundingSphere}.
24500		 *
24501		 * @type {?Sphere}
24502		 * @default null
24503		 */
24504		this.boundingSphere = null;
24505
24506		for ( let i = 0; i < count; i ++ ) {
24507
24508			this.setMatrixAt( i, _identity );
24509
24510		}
24511
24512	}
24513
24514	/**
24515	 * Computes the bounding box of the instanced mesh, and updates {@link InstancedMesh#boundingBox}.
24516	 * The bounding box is not automatically computed by the engine; this method must be called by your app.
24517	 * You may need to recompute the bounding box if an instance is transformed via {@link InstancedMesh#setMatrixAt}.
24518	 */
24519	computeBoundingBox() {
24520
24521		const geometry = this.geometry;
24522		const count = this.count;
24523
24524		if ( this.boundingBox === null ) {
24525
24526			this.boundingBox = new Box3();
24527
24528		}
24529
24530		if ( geometry.boundingBox === null ) {
24531
24532			geometry.computeBoundingBox();
24533
24534		}
24535
24536		this.boundingBox.makeEmpty();
24537
24538		for ( let i = 0; i < count; i ++ ) {
24539
24540			this.getMatrixAt( i, _instanceLocalMatrix );
24541
24542			_box3.copy( geometry.boundingBox ).applyMatrix4( _instanceLocalMatrix );
24543
24544			this.boundingBox.union( _box3 );
24545
24546		}
24547
24548	}
24549
24550	/**
24551	 * Computes the bounding sphere of the instanced mesh, and updates {@link InstancedMesh#boundingSphere}
24552	 * The engine automatically computes the bounding sphere when it is needed, e.g., for ray casting or view frustum culling.
24553	 * You may need to recompute the bounding sphere if an instance is transformed via {@link InstancedMesh#setMatrixAt}.
24554	 */
24555	computeBoundingSphere() {
24556
24557		const geometry = this.geometry;
24558		const count = this.count;
24559
24560		if ( this.boundingSphere === null ) {
24561
24562			this.boundingSphere = new Sphere();
24563
24564		}
24565
24566		if ( geometry.boundingSphere === null ) {
24567
24568			geometry.computeBoundingSphere();
24569
24570		}
24571
24572		this.boundingSphere.makeEmpty();
24573
24574		for ( let i = 0; i < count; i ++ ) {
24575
24576			this.getMatrixAt( i, _instanceLocalMatrix );
24577
24578			_sphere$4.copy( geometry.boundingSphere ).applyMatrix4( _instanceLocalMatrix );
24579
24580			this.boundingSphere.union( _sphere$4 );
24581
24582		}
24583
24584	}
24585
24586	copy( source, recursive ) {
24587
24588		super.copy( source, recursive );
24589
24590		this.instanceMatrix.copy( source.instanceMatrix );
24591
24592		if ( source.previousInstanceMatrix !== null ) this.previousInstanceMatrix = source.previousInstanceMatrix.clone(
vendor: 5,489 bytes, lines 24592-24797
24592);
24593
24594		if ( source.morphTexture !== null ) this.morphTexture = source.morphTexture.clone();
24595		if ( source.instanceColor !== null ) this.instanceColor = source.instanceColor.clone();
24596
24597		this.count = source.count;
24598
24599		if ( source.boundingBox !== null ) this.boundingBox = source.boundingBox.clone();
24600		if ( source.boundingSphere !== null ) this.boundingSphere = source.boundingSphere.clone();
24601
24602		return this;
24603
24604	}
24605
24606	/**
24607	 * Gets the color of the defined instance.
24608	 *
24609	 * @param {number} index - The instance index.
24610	 * @param {Color} color - The target object that is used to store the method's result.
24611	 * @return {Color} A reference to the target color.
24612	 */
24613	getColorAt( index, color ) {
24614
24615		if ( this.instanceColor === null ) {
24616
24617			return color.setRGB( 1, 1, 1 );
24618
24619		} else {
24620
24621			return color.fromArray( this.instanceColor.array, index * 3 );
24622
24623		}
24624
24625	}
24626
24627	/**
24628	 * Gets the local transformation matrix of the defined instance.
24629	 *
24630	 * @param {number} index - The instance index.
24631	 * @param {Matrix4} matrix - The target object that is used to store the method's result.
24632	 * @return {Matrix4} A reference to the target matrix.
24633	 */
24634	getMatrixAt( index, matrix ) {
24635
24636		return matrix.fromArray( this.instanceMatrix.array, index * 16 );
24637
24638	}
24639
24640	/**
24641	 * Gets the morph target weights of the defined instance.
24642	 *
24643	 * @param {number} index - The instance index.
24644	 * @param {Mesh} object - The target object that is used to store the method's result.
24645	 */
24646	getMorphAt( index, object ) {
24647
24648		const objectInfluences = object.morphTargetInfluences;
24649
24650		const array = this.morphTexture.source.data.data;
24651
24652		const len = objectInfluences.length + 1; // All influences + the baseInfluenceSum
24653
24654		const dataIndex = index * len + 1; // Skip the baseInfluenceSum at the beginning
24655
24656		for ( let i = 0; i < objectInfluences.length; i ++ ) {
24657
24658			objectInfluences[ i ] = array[ dataIndex + i ];
24659
24660		}
24661
24662	}
24663
24664	raycast( raycaster, intersects ) {
24665
24666		const matrixWorld = this.matrixWorld;
24667		const raycastTimes = this.count;
24668
24669		_mesh$1.geometry = this.geometry;
24670		_mesh$1.material = this.material;
24671
24672		if ( _mesh$1.material === undefined ) return;
24673
24674		// test with bounding sphere first
24675
24676		if ( this.boundingSphere === null ) this.computeBoundingSphere();
24677
24678		_sphere$4.copy( this.boundingSphere );
24679		_sphere$4.applyMatrix4( matrixWorld );
24680
24681		if ( raycaster.ray.intersectsSphere( _sphere$4 ) === false ) return;
24682
24683		// now test each instance
24684
24685		for ( let instanceId = 0; instanceId < raycastTimes; instanceId ++ ) {
24686
24687			// calculate the world matrix for each instance
24688
24689			this.getMatrixAt( instanceId, _instanceLocalMatrix );
24690
24691			_instanceWorldMatrix.multiplyMatrices( matrixWorld, _instanceLocalMatrix );
24692
24693			// the mesh represents this single instance
24694
24695			_mesh$1.matrixWorld = _instanceWorldMatrix;
24696
24697			_mesh$1.raycast( raycaster, _instanceIntersects );
24698
24699			// process the result of raycast
24700
24701			for ( let i = 0, l = _instanceIntersects.length; i < l; i ++ ) {
24702
24703				const intersect = _instanceIntersects[ i ];
24704				intersect.instanceId = instanceId;
24705				intersect.object = this;
24706				intersects.push( intersect );
24707
24708			}
24709
24710			_instanceIntersects.length = 0;
24711
24712		}
24713
24714	}
24715
24716	/**
24717	 * Sets the given color to the defined instance. Make sure you set the `needsUpdate` flag of
24718	 * {@link InstancedMesh#instanceColor} to `true` after updating all the colors.
24719	 *
24720	 * @param {number} index - The instance index.
24721	 * @param {Color} color - The instance color.
24722	 * @return {InstancedMesh} A reference to this instanced mesh.
24723	 */
24724	setColorAt( index, color ) {
24725
24726		if ( this.instanceColor === null ) {
24727
24728			this.instanceColor = new InstancedBufferAttribute( new Float32Array( this.instanceMatrix.count * 3 ).fill( 1 ), 3 );
24729
24730		}
24731
24732		color.toArray( this.instanceColor.array, index * 3 );
24733		return this;
24734
24735	}
24736
24737	/**
24738	 * Sets the given local transformation matrix to the defined instance. Make sure you set the `needsUpdate` flag of
24739	 * {@link InstancedMesh#instanceMatrix} to `true` after updating all the matrices.
24740	 *
24741	 * @param {number} index - The instance index.
24742	 * @param {Matrix4} matrix - The local transformation.
24743	 * @return {InstancedMesh} A reference to this instanced mesh.
24744	 */
24745	setMatrixAt( index, matrix ) {
24746
24747		matrix.toArray( this.instanceMatrix.array, index * 16 );
24748		return this;
24749
24750	}
24751
24752	/**
24753	 * Sets the morph target weights to the defined instance. Make sure you set the `needsUpdate` flag of
24754	 * {@link InstancedMesh#morphTexture} to `true` after updating all the influences.
24755	 *
24756	 * @param {number} index - The instance index.
24757	 * @param {Mesh} object -  A mesh which `morphTargetInfluences` property containing the morph target weights
24758	 * of a single instance.
24759	 * @return {InstancedMesh} A reference to this instanced mesh.
24760	 */
24761	setMorphAt( index, object ) {
24762
24763		const objectInfluences = object.morphTargetInfluences;
24764
24765		const len = objectInfluences.length + 1; // morphBaseInfluence + all influences
24766
24767		if ( this.morphTexture === null ) {
24768
24769			this.morphTexture = new DataTexture( new Float32Array( len * this.count ), len, this.count, RedFormat, FloatType );
24770
24771		}
24772
24773		const array = this.morphTexture.source.data.data;
24774
24775		let morphInfluencesSum = 0;
24776
24777		for ( let i = 0; i < objectInfluences.length; i ++ ) {
24778
24779			morphInfluencesSum += objectInfluences[ i ];
24780
24781		}
24782
24783		const morphBaseInfluence = this.geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum;
24784
24785		const dataIndex = len * index;
24786
24787		array[ dataIndex ] = morphBaseInfluence;
24788
24789		array.set( objectInfluences, dataIndex + 1 );
24790		return this;
24791
24792	}
24793
24794	updateMorphTargets() {
24795
24796	}
24797
vendor: 5,463 bytes, lines 24798-25026
24798	/**
24799	 * Frees the GPU-related resources allocated by this instance. Call this
24800	 * method whenever this instance is no longer used in your app.
24801	 */
24802	dispose() {
24803
24804		this.dispatchEvent( { type: 'dispose' } );
24805
24806		if ( this.morphTexture !== null ) {
24807
24808			this.morphTexture.dispose();
24809			this.morphTexture = null;
24810
24811		}
24812
24813	}
24814
24815}
24816
24817const _vector1 = /*@__PURE__*/ new Vector3();
24818const _vector2 = /*@__PURE__*/ new Vector3();
24819const _normalMatrix = /*@__PURE__*/ new Matrix3();
24820
24821/**
24822 * A two dimensional surface that extends infinitely in 3D space, represented
24823 * in [Hessian normal form](http://mathworld.wolfram.com/HessianNormalForm.html)
24824 * by a unit length normal vector and a constant.
24825 */
24826class Plane {
24827
24828	/**
24829	 * Constructs a new plane.
24830	 *
24831	 * @param {Vector3} [normal=(1,0,0)] - A unit length vector defining the normal of the plane.
24832	 * @param {number} [constant=0] - The signed distance from the origin to the plane.
24833	 */
24834	constructor( normal = new Vector3( 1, 0, 0 ), constant = 0 ) {
24835
24836		/**
24837		 * This flag can be used for type testing.
24838		 *
24839		 * @type {boolean}
24840		 * @readonly
24841		 * @default true
24842		 */
24843		this.isPlane = true;
24844
24845		/**
24846		 * A unit length vector defining the normal of the plane.
24847		 *
24848		 * @type {Vector3}
24849		 */
24850		this.normal = normal;
24851
24852		/**
24853		 * The signed distance from the origin to the plane.
24854		 *
24855		 * @type {number}
24856		 * @default 0
24857		 */
24858		this.constant = constant;
24859
24860	}
24861
24862	/**
24863	 * Sets the plane components by copying the given values.
24864	 *
24865	 * @param {Vector3} normal - The normal.
24866	 * @param {number} constant - The constant.
24867	 * @return {Plane} A reference to this plane.
24868	 */
24869	set( normal, constant ) {
24870
24871		this.normal.copy( normal );
24872		this.constant = constant;
24873
24874		return this;
24875
24876	}
24877
24878	/**
24879	 * Sets the plane components by defining `x`, `y`, `z` as the
24880	 * plane normal and `w` as the constant.
24881	 *
24882	 * @param {number} x - The value for the normal's x component.
24883	 * @param {number} y - The value for the normal's y component.
24884	 * @param {number} z - The value for the normal's z component.
24885	 * @param {number} w - The constant value.
24886	 * @return {Plane} A reference to this plane.
24887	 */
24888	setComponents( x, y, z, w ) {
24889
24890		this.normal.set( x, y, z );
24891		this.constant = w;
24892
24893		return this;
24894
24895	}
24896
24897	/**
24898	 * Sets the plane from the given normal and coplanar point (that is a point
24899	 * that lies onto the plane).
24900	 *
24901	 * @param {Vector3} normal - The normal.
24902	 * @param {Vector3} point - A coplanar point.
24903	 * @return {Plane} A reference to this plane.
24904	 */
24905	setFromNormalAndCoplanarPoint( normal, point ) {
24906
24907		this.normal.copy( normal );
24908		this.constant = - point.dot( this.normal );
24909
24910		return this;
24911
24912	}
24913
24914	/**
24915	 * Sets the plane from three coplanar points. The winding order is
24916	 * assumed to be counter-clockwise, and determines the direction of
24917	 * the plane normal.
24918	 *
24919	 * @param {Vector3} a - The first coplanar point.
24920	 * @param {Vector3} b - The second coplanar point.
24921	 * @param {Vector3} c - The third coplanar point.
24922	 * @return {Plane} A reference to this plane.
24923	 */
24924	setFromCoplanarPoints( a, b, c ) {
24925
24926		const normal = _vector1.subVectors( c, b ).cross( _vector2.subVectors( a, b ) ).normalize();
24927
24928		// Q: should an error be thrown if normal is zero (e.g. degenerate plane)?
24929
24930		this.setFromNormalAndCoplanarPoint( normal, a );
24931
24932		return this;
24933
24934	}
24935
24936	/**
24937	 * Copies the values of the given plane to this instance.
24938	 *
24939	 * @param {Plane} plane - The plane to copy.
24940	 * @return {Plane} A reference to this plane.
24941	 */
24942	copy( plane ) {
24943
24944		this.normal.copy( plane.normal );
24945		this.constant = plane.constant;
24946
24947		return this;
24948
24949	}
24950
24951	/**
24952	 * Normalizes the plane normal and adjusts the constant accordingly.
24953	 *
24954	 * @return {Plane} A reference to this plane.
24955	 */
24956	normalize() {
24957
24958		// Note: will lead to a divide by zero if the plane is invalid.
24959
24960		const inverseNormalLength = 1.0 / this.normal.length();
24961		this.normal.multiplyScalar( inverseNormalLength );
24962		this.constant *= inverseNormalLength;
24963
24964		return this;
24965
24966	}
24967
24968	/**
24969	 * Negates both the plane normal and the constant.
24970	 *
24971	 * @return {Plane} A reference to this plane.
24972	 */
24973	negate() {
24974
24975		this.constant *= -1;
24976		this.normal.negate();
24977
24978		return this;
24979
24980	}
24981
24982	/**
24983	 * Returns the signed distance from the given point to this plane.
24984	 *
24985	 * @param {Vector3} point - The point to compute the distance for.
24986	 * @return {number} The signed distance.
24987	 */
24988	distanceToPoint( point ) {
24989
24990		return this.normal.dot( point ) + this.constant;
24991
24992	}
24993
24994	/**
24995	 * Returns the signed distance from the given sphere to this plane.
24996	 *
24997	 * @param {Sphere} sphere - The sphere to compute the distance for.
24998	 * @return {number} The signed distance.
24999	 */
25000	distanceToSphere( sphere ) {
25001
25002		return this.distanceToPoint( sphere.center ) - sphere.radius;
25003
25004	}
25005
25006	/**
25007	 * Projects a the given point onto the plane.
25008	 *
25009	 * @param {Vector3} point - The point to project.
25010	 * @param {Vector3} target - The target vector that is used to store the method's result.
25011	 * @return {Vector3} The projected point on the plane.
25012	 */
25013	projectPoint( point, target ) {
25014
25015		return target.copy( point ).addScaledVector( this.normal, - this.distanceToPoint( point ) );
25016
25017	}
25018
25019	/**
25020	 * Returns the intersection point of the passed line and the plane. Returns
25021	 * `null` if the line does not intersect. Returns the line's starting point if
25022	 * the line is coplanar with the plane.
25023	 *
25024	 * @param {Line3} line - The line to compute the intersection for.
25025	 * @param {Vector3} target - The target vector that is used to store the method's result.
25026	 * @
25026param {boolean} [clampToLine=true] - Whether to clamp the intersection to the line segment.
25027	 * @return {?Vector3} The intersection point. Returns `null` if no intersection is detected.
25028	 */
25029	intersectLine( line, target, clampToLine = true ) {
25030
25031		const direction = line.delta( _vector1 );
25032
25033		const denominator = this.normal.dot( direction );
25034
25035		if ( denominator === 0 ) {
25036
25037			// line is coplanar, return origin
25038			if ( this.distanceToPoint( line.start ) === 0 ) {
25039
25040				return target.copy( line.start );
25041
25042			}
25043
25044			// Unsure if this is the correct method to handle this case.
25045			return null;
25046
25047		}
25048
25049		const t = - ( line.start.dot( this.normal ) + this.constant ) / denominator;
25050
25051		if ( ( clampToLine === true ) && ( t < 0 || t > 1 )
vendor: 10,709 bytes, lines 25051-25457
25051 ) {
25052
25053			return null;
25054
25055		}
25056
25057		return target.copy( line.start ).addScaledVector( direction, t );
25058
25059	}
25060
25061	/**
25062	 * Returns `true` if the given line segment intersects with (passes through) the plane.
25063	 *
25064	 * @param {Line3} line - The line to test.
25065	 * @return {boolean} Whether the given line segment intersects with the plane or not.
25066	 */
25067	intersectsLine( line ) {
25068
25069		// Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it.
25070
25071		const startSign = this.distanceToPoint( line.start );
25072		const endSign = this.distanceToPoint( line.end );
25073
25074		return ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 );
25075
25076	}
25077
25078	/**
25079	 * Returns `true` if the given bounding box intersects with the plane.
25080	 *
25081	 * @param {Box3} box - The bounding box to test.
25082	 * @return {boolean} Whether the given bounding box intersects with the plane or not.
25083	 */
25084	intersectsBox( box ) {
25085
25086		return box.intersectsPlane( this );
25087
25088	}
25089
25090	/**
25091	 * Returns `true` if the given bounding sphere intersects with the plane.
25092	 *
25093	 * @param {Sphere} sphere - The bounding sphere to test.
25094	 * @return {boolean} Whether the given bounding sphere intersects with the plane or not.
25095	 */
25096	intersectsSphere( sphere ) {
25097
25098		return sphere.intersectsPlane( this );
25099
25100	}
25101
25102	/**
25103	 * Returns a coplanar vector to the plane, by calculating the
25104	 * projection of the normal at the origin onto the plane.
25105	 *
25106	 * @param {Vector3} target - The target vector that is used to store the method's result.
25107	 * @return {Vector3} The coplanar point.
25108	 */
25109	coplanarPoint( target ) {
25110
25111		return target.copy( this.normal ).multiplyScalar( - this.constant );
25112
25113	}
25114
25115	/**
25116	 * Apply a 4x4 matrix to the plane. The matrix must be an affine, homogeneous transform.
25117	 *
25118	 * The optional normal matrix can be pre-computed like so:
25119	 * ```js
25120	 * const optionalNormalMatrix = new THREE.Matrix3().getNormalMatrix( matrix );
25121	 * ```
25122	 *
25123	 * @param {Matrix4} matrix - The transformation matrix.
25124	 * @param {Matrix4} [optionalNormalMatrix] - A pre-computed normal matrix.
25125	 * @return {Plane} A reference to this plane.
25126	 */
25127	applyMatrix4( matrix, optionalNormalMatrix ) {
25128
25129		const normalMatrix = optionalNormalMatrix || _normalMatrix.getNormalMatrix( matrix );
25130
25131		const referencePoint = this.coplanarPoint( _vector1 ).applyMatrix4( matrix );
25132
25133		const normal = this.normal.applyMatrix3( normalMatrix ).normalize();
25134
25135		this.constant = - referencePoint.dot( normal );
25136
25137		return this;
25138
25139	}
25140
25141	/**
25142	 * Translates the plane by the distance defined by the given offset vector.
25143	 * Note that this only affects the plane constant and will not affect the normal vector.
25144	 *
25145	 * @param {Vector3} offset - The offset vector.
25146	 * @return {Plane} A reference to this plane.
25147	 */
25148	translate( offset ) {
25149
25150		this.constant -= offset.dot( this.normal );
25151
25152		return this;
25153
25154	}
25155
25156	/**
25157	 * Returns `true` if this plane is equal with the given one.
25158	 *
25159	 * @param {Plane} plane - The plane to test for equality.
25160	 * @return {boolean} Whether this plane is equal with the given one.
25161	 */
25162	equals( plane ) {
25163
25164		return plane.normal.equals( this.normal ) && ( plane.constant === this.constant );
25165
25166	}
25167
25168	/**
25169	 * Returns a new plane with copied values from this instance.
25170	 *
25171	 * @return {Plane} A clone of this instance.
25172	 */
25173	clone() {
25174
25175		return new this.constructor().copy( this );
25176
25177	}
25178
25179}
25180
25181const _sphere$3 = /*@__PURE__*/ new Sphere();
25182const _defaultSpriteCenter = /*@__PURE__*/ new Vector2( 0.5, 0.5 );
25183const _vector$6 = /*@__PURE__*/ new Vector3();
25184
25185/**
25186 * Frustums are used to determine what is inside the camera's field of view.
25187 * They help speed up the rendering process - objects which lie outside a camera's
25188 * frustum can safely be excluded from rendering.
25189 *
25190 * This class is mainly intended for use internally by a renderer.
25191 */
25192class Frustum {
25193
25194	/**
25195	 * Constructs a new frustum.
25196	 *
25197	 * @param {Plane} [p0] - The first plane that encloses the frustum.
25198	 * @param {Plane} [p1] - The second plane that encloses the frustum.
25199	 * @param {Plane} [p2] - The third plane that encloses the frustum.
25200	 * @param {Plane} [p3] - The fourth plane that encloses the frustum.
25201	 * @param {Plane} [p4] - The fifth plane that encloses the frustum.
25202	 * @param {Plane} [p5] - The sixth plane that encloses the frustum.
25203	 */
25204	constructor( p0 = new Plane(), p1 = new Plane(), p2 = new Plane(), p3 = new Plane(), p4 = new Plane(), p5 = new Plane() ) {
25205
25206		/**
25207		 * This array holds the planes that enclose the frustum.
25208		 *
25209		 * @type {Array<Plane>}
25210		 */
25211		this.planes = [ p0, p1, p2, p3, p4, p5 ];
25212
25213	}
25214
25215	/**
25216	 * Sets the frustum planes by copying the given planes.
25217	 *
25218	 * @param {Plane} [p0] - The first plane that encloses the frustum.
25219	 * @param {Plane} [p1] - The second plane that encloses the frustum.
25220	 * @param {Plane} [p2] - The third plane that encloses the frustum.
25221	 * @param {Plane} [p3] - The fourth plane that encloses the frustum.
25222	 * @param {Plane} [p4] - The fifth plane that encloses the frustum.
25223	 * @param {Plane} [p5] - The sixth plane that encloses the frustum.
25224	 * @return {Frustum} A reference to this frustum.
25225	 */
25226	set( p0, p1, p2, p3, p4, p5 ) {
25227
25228		const planes = this.planes;
25229
25230		planes[ 0 ].copy( p0 );
25231		planes[ 1 ].copy( p1 );
25232		planes[ 2 ].copy( p2 );
25233		planes[ 3 ].copy( p3 );
25234		planes[ 4 ].copy( p4 );
25235		planes[ 5 ].copy( p5 );
25236
25237		return this;
25238
25239	}
25240
25241	/**
25242	 * Copies the values of the given frustum to this instance.
25243	 *
25244	 * @param {Frustum} frustum - The frustum to copy.
25245	 * @return {Frustum} A reference to this frustum.
25246	 */
25247	copy( frustum ) {
25248
25249		const planes = this.planes;
25250
25251		for ( let i = 0; i < 6; i ++ ) {
25252
25253			planes[ i ].copy( frustum.planes[ i ] );
25254
25255		}
25256
25257		return this;
25258
25259	}
25260
25261	/**
25262	 * Sets the frustum planes from the given projection matrix.
25263	 *
25264	 * @param {Matrix4} m - The projection matrix.
25265	 * @param {(WebGLCoordinateSystem|WebGPUCoordinateSystem)} coordinateSystem - The coordinate system.
25266	 * @param {boolean} [reversedDepth=false] - Whether to use a reversed depth.
25267	 * @return {Frustum} A reference to this frustum.
25268	 */
25269	setFromProjectionMatrix( m, coordinateSystem = WebGLCoordinateSystem, reversedDepth = false ) {
25270
25271		const planes = this.planes;
25272		const me = m.elements;
25273		const me0 = me[ 0 ], me1 = me[ 1 ], me2 = me[ 2 ], me3 = me[ 3 ];
25274		const me4 = me[ 4 ], me5 = me[ 5 ], me6 = me[ 6 ], me7 = me[ 7 ];
25275		const me8 = me[ 8 ], me9 = me[ 9 ], me10 = me[ 10 ], me11 = me[ 11 ];
25276		const me12 = me[ 12 ], me13 = me[ 13 ], me14 = me[ 14 ], me15 = me[ 15 ];
25277
25278		planes[ 0 ].setComponents( me3 - me0, me7 - me4, me11 - me8, me15 - me12 ).normalize();
25279		planes[ 1 ].setComponents( me3 + me0, me7 + me4, me11 + me8, me15 + me12 ).normalize();
25280		planes[ 2 ].setComponents( me3 + me1, me7 + me5, me11 + me9, me15 + me13 ).normalize();
25281		planes[ 3 ].setComponents( me3 - me1, me7 - me5, me11 - me9, me15 - me13 ).normalize();
25282
25283		if ( reversedDepth ) {
25284
25285			planes[ 4 ].setComponents( me2, me6, me10, me14 ).normalize(); // far
25286			planes[ 5 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize(); // near
25287
25288		} else {
25289
25290			planes[ 4 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize(); // far
25291
25292			if ( coordinateSystem === WebGLCoordinateSystem ) {
25293
25294				planes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize(); // near
25295
25296			} else if ( coordinateSystem === WebGPUCoordinateSystem ) {
25297
25298				planes[ 5 ].setComponents( me2, me6, me10, me14 ).normalize(); // near
25299
25300			} else {
25301
25302				throw new Error( 'THREE.Frustum.setFromProjectionMatrix(): Invalid coordinate system: ' + coordinateSystem );
25303
25304			}
25305
25306		}
25307
25308		return this;
25309
25310	}
25311
25312	/**
25313	 * Returns `true` if the 3D object's bounding sphere is intersecting this frustum.
25314	 *
25315	 * Note that the 3D object must have a geometry so that the bounding sphere can be calculated.
25316	 *
25317	 * @param {Object3D} object - The 3D object to test.
25318	 * @return {boolean} Whether the 3D object's bounding sphere is intersecting this frustum or not.
25319	 */
25320	intersectsObject( object ) {
25321
25322		if ( object.boundingSphere !== undefined ) {
25323
25324			if ( object.boundingSphere === null ) object.computeBoundingSphere();
25325
25326			_sphere$3.copy( object.boundingSphere ).applyMatrix4( object.matrixWorld );
25327
25328		} else {
25329
25330			const geometry = object.geometry;
25331
25332			if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
25333
25334			_sphere$3.copy( geometry.boundingSphere ).applyMatrix4( object.matrixWorld );
25335
25336		}
25337
25338		return this.intersectsSphere( _sphere$3 );
25339
25340	}
25341
25342	/**
25343	 * Returns `true` if the given sprite is intersecting this frustum.
25344	 *
25345	 * @param {Sprite} sprite - The sprite to test.
25346	 * @return {boolean} Whether the sprite is intersecting this frustum or not.
25347	 */
25348	intersectsSprite( sprite ) {
25349
25350		_sphere$3.center.set( 0, 0, 0 );
25351
25352		const offset = _defaultSpriteCenter.distanceTo( sprite.center );
25353
25354		_sphere$3.radius = 0.7071067811865476 + offset;
25355		_sphere$3.applyMatrix4( sprite.matrixWorld );
25356
25357		return this.intersectsSphere( _sphere$3 );
25358
25359	}
25360
25361	/**
25362	 * Returns `true` if the given bounding sphere is intersecting this frustum.
25363	 *
25364	 * @param {Sphere} sphere - The bounding sphere to test.
25365	 * @return {boolean} Whether the bounding sphere is intersecting this frustum or not.
25366	 */
25367	intersectsSphere( sphere ) {
25368
25369		const planes = this.planes;
25370		const center = sphere.center;
25371		const negRadius = - sphere.radius;
25372
25373		for ( let i = 0; i < 6; i ++ ) {
25374
25375			const distance = planes[ i ].distanceToPoint( center );
25376
25377			if ( distance < negRadius ) {
25378
25379				return false;
25380
25381			}
25382
25383		}
25384
25385		return true;
25386
25387	}
25388
25389	/**
25390	 * Returns `true` if the given bounding box is intersecting this frustum.
25391	 *
25392	 * @param {Box3} box - The bounding box to test.
25393	 * @return {boolean} Whether the bounding box is intersecting this frustum or not.
25394	 */
25395	intersectsBox( box ) {
25396
25397		const planes = this.planes;
25398
25399		for ( let i = 0; i < 6; i ++ ) {
25400
25401			const plane = planes[ i ];
25402
25403			// corner at max distance
25404
25405			_vector$6.x = plane.normal.x > 0 ? box.max.x : box.min.x;
25406			_vector$6.y = plane.normal.y > 0 ? box.max.y : box.min.y;
25407			_vector$6.z = plane.normal.z > 0 ? box.max.z : box.min.z;
25408
25409			if ( plane.distanceToPoint( _vector$6 ) < 0 ) {
25410
25411				return false;
25412
25413			}
25414
25415		}
25416
25417		return true;
25418
25419	}
25420
25421	/**
25422	 * Returns `true` if the given point lies within the frustum.
25423	 *
25424	 * @param {Vector3} point - The point to test.
25425	 * @return {boolean} Whether the point lies within this frustum or not.
25426	 */
25427	containsPoint( point ) {
25428
25429		const planes = this.planes;
25430
25431		for ( let i = 0; i < 6; i ++ ) {
25432
25433			if ( planes[ i ].distanceToPoint( point ) < 0 ) {
25434
25435				return false;
25436
25437			}
25438
25439		}
25440
25441		return true;
25442
25443	}
25444
25445	/**
25446	 * Returns a new frustum with copied values from this instance.
25447	 *
25448	 * @return {Frustum} A clone of this instance.
25449	 */
25450	clone() {
25451
25452		return new this.constructor().copy( this );
25453
25454	}
25455
25456}
25457
25458const _projScreenMatrix$1 = /*@__PURE__*/ new Matrix4();
25459const _frustum$1 = /*@__PURE__*/ new Frustum();
25460
25461/**
25462 * FrustumArray is used to determine if an object is visible in at least one camera
25463 * from an array of cameras. This is particularly useful for multi-view renderers.
25464*/
25465class FrustumArray {
25466
25467	/**
25468	 * Constructs a new frustum array.
25469	 *
25470	 */
25471	constructor() {
25472
25473		/**
25474		 * The coordinate system to use.
25475		 *
25476		 * @type {WebGLCoordinateSystem|WebGPUCoordinateSystem}
25477		 * @default WebGLCoordinateSystem
25478		 */
25479		this.coordinateSystem = WebGLCoordinateSystem;
25480
25481	}
25482
25483	/**
25484	 * Returns `true` if the 3D object's bounding sphere is intersecting any frustum
25485	 * from the camera array.
25486	 *
25487	 * @param {Object3D} object - The 3D object to test.
25488	 * @param {Object} cameraArray - An object with a cameras property containing an array of cameras.
25489	 * @return {boolean} Whether the 3D object is visible in any camera.
25490	 */
25491	intersectsObject( object, cameraArray ) {
25492
25493		if ( ! cameraArray.isArrayCamera || cameraArray.cameras.length === 0 ) {
25494
25495			return false;
25496
25497		}
25498
25499		for ( let i = 0; i < cameraArray.cameras.length; i ++ ) {
25500
25501			const camera = cameraArray.cameras[ i ];
25502
25503			_projScreenMatrix$1.multiplyMatrices(
25504				camera.projectionMatrix,
25505				camera.matrixWorldInverse
25506			);
25507
25508			_frustum$1.setFromProjectionMatrix(
25509				_projScreenMatrix$1,
25510				camera.coordinateSystem,
25511				camera.reversedDepth
25512			);
25513
25514			if ( _frustum$1.intersectsObject( object ) ) {
25515
25516				return true; // Object is visible in at least one camera
25517
25518			}
25519
25520		}
25521
25522		return false; // Not visible in any camera
25523
25524	}
25525
25526	/**
25527	 * Returns `true` if the given sprite is intersecting any frustum
25528	 * from the camera array.
25529	 *
25530	 * @param {Sprite} sprite - The sprite to test.
25531	 * @param {Object} cameraArray - An object with a cameras property containing an array of cameras.
25532	 * @return {boolean} Whether the sprite is visible in any camera.
25533	 */
25534	intersectsSprite( sprite, cameraArray ) {
25535
25536		if ( ! cameraArray || ! cameraArray.cameras || cameraArray.cameras.length === 0 ) {
25537
25538			return false;
25539
25540		}
25541
25542		for ( let i = 0; i < cameraArray.cameras.length; i ++ ) {
25543
25544			const camera = cameraArray.cameras[ i ];
25545
25546			_projScreenMatrix$1.multiplyMatrices(
25547				camera.projectionMatrix,
25548				camera.matrixWorldInverse
25549			);
25550
25551			_frustum$1.setFromProjectionMatrix(
25552				_projScreenMatrix$1,
25553				camera.coordinateSystem,
25554				camera.reversedDepth
25555			);
25556
25557			if ( _frustum$1.intersectsSprite( sprite ) ) {
25558
25559				return true; // Sprite is visible in at least one camera
25560
25561			}
25562
25563		}
25564
25565		return false; // Not visible in any camera
25566
25567	}
25568
25569	/**
25570	 * Returns `true` if the given bounding sphere is intersecting any frustum
25571	 * from the camera array.
25572	 *
25573	 * @param {Sphere} sphere - The bounding sphere to test.
25574	 * @param {Object} cameraArray - An object with a cameras property containing an array of cameras.
25575	 * @return {boolean} Whether the sphere is visible in any camera.
25576	 */
25577	intersectsSphere( sphere, cameraArray ) {
25578
25579		if ( ! cameraArray || ! cameraArray.cameras || cameraArray.cameras.length === 0 ) {
25580
25581			return false;
25582
25583		}
25584
25585		for ( let i = 0; i < cameraArray.cameras.length; i ++ ) {
25586
25587			const camera = cameraArray.cameras[ i ];
25588
25589			_projScreenMatrix$1.multiplyMatrices(
25590				camera.projectionMatrix,
25591				camera.matrixWorldInverse
25592			);
25593
25594			_frustum$1.setFromProjectionMatrix(
25595				_projScreenMatrix$1,
25596				camera.coordinateSystem,
25597				camera.reversedDepth
25598			);
25599
25600			if ( _frustum$1.intersectsSphere( sphere ) ) {
25601
25602				return true; // Sphere is visible in at least one camera
25603
25604			}
25605
25606		}
25607
25608		return false; // Not visible in any camera
25609
25610	}
25611
25612	/**
25613	 * Returns `true` if the given bounding box is intersecting any frustum
25614	 * from the camera array.
25615	 *
25616	 * @param {Box3} box - The bounding box to test.
25617	 * @param {Object} cameraArray - An object with a cameras property containing an array of cameras.
25618	 * @return {boolean} Whether the box is visible in any camera.
25619	 */
25620	intersectsBox( box, cameraArray ) {
25621
25622		if ( ! cameraArray || ! cameraArray.cameras || cameraArray.cameras.length === 0 ) {
25623
25624			return false;
25625
25626		}
25627
25628		for ( let i = 0; i < cameraArray.cameras.length; i ++ ) {
25629
25630			const camera = cameraArray.cameras[ i ];
25631
25632			_projScreenMatrix$1.multiplyMatrices(
25633				camera.projectionMatrix,
25634				camera.matrixWorldInverse
25635			);
25636
25637			_frustum$1.setFromProjectionMatrix(
25638				_projScreenMatrix$1,
25639				camera.coordinateSystem,
25640				camera.reversedDepth
25641			);
25642
25643			if ( _frustum$1.intersectsBox( box ) ) {
25644
25645				return true; // Box is visible in at least one camera
25646
25647			}
25648
25649		}
25650
25651		return false; // Not visible in any camera
25652
25653	}
25654
25655	/**
25656	 * Returns `true` if the given point lies within any frustum
25657	 * from the camera array.
25658	 *
25659	 * @param {Vector3} point - The point to test.
25660	 * @param {Object} cameraArray - An object with a cameras property containing an array of cameras.
25661	 * @return {boolean} Whether the point is visible in any camera.
25662	 */
25663	containsPoint( point, cameraArray ) {
25664
25665		if ( ! cameraArray || ! cameraArray.cameras || cameraArray.cameras.length === 0 ) {
25666
25667			return false;
25668
25669		}
25670
25671		for ( let i = 0; i < cameraArray.cameras.length; i ++ ) {
25672
25673			const camera = cameraArray.cameras[ i ];
25674
25675			_projScreenMatrix$1.multiplyMatrices(
25676				camera.projectionMatrix,
25677				camera.matrixWorldInverse
25678			);
25679
25680			_frustum$1.setFromProjectionMatrix(
25681				_projScreenMatrix$1,
25682				camera.coordinateSystem,
25683				camera.reversedDepth
25684			);
25685
vendor: 4,394 bytes, lines 25686-25872
25686			if ( _frustum$1.containsPoint( point ) ) {
25687
25688				return true; // Point is visible in at least one camera
25689
25690			}
25691
25692		}
25693
25694		return false; // Not visible in any camera
25695
25696	}
25697
25698	/**
25699	 * Returns a new frustum array with copied values from this instance.
25700	 *
25701	 * @return {FrustumArray} A clone of this instance.
25702	 */
25703	clone() {
25704
25705		return new FrustumArray();
25706
25707	}
25708
25709}
25710
25711function ascIdSort( a, b ) {
25712
25713	return a - b;
25714
25715}
25716
25717function sortOpaque( a, b ) {
25718
25719	return a.z - b.z;
25720
25721}
25722
25723function sortTransparent( a, b ) {
25724
25725	return b.z - a.z;
25726
25727}
25728
25729class MultiDrawRenderList {
25730
25731	constructor() {
25732
25733		this.index = 0;
25734		this.pool = [];
25735		this.list = [];
25736
25737	}
25738
25739	push( start, count, z, index ) {
25740
25741		const pool = this.pool;
25742		const list = this.list;
25743		if ( this.index >= pool.length ) {
25744
25745			pool.push( {
25746
25747				start: -1,
25748				count: -1,
25749				z: -1,
25750				index: -1,
25751
25752			} );
25753
25754		}
25755
25756		const item = pool[ this.index ];
25757		list.push( item );
25758		this.index ++;
25759
25760		item.start = start;
25761		item.count = count;
25762		item.z = z;
25763		item.index = index;
25764
25765	}
25766
25767	reset() {
25768
25769		this.list.length = 0;
25770		this.index = 0;
25771
25772	}
25773
25774}
25775
25776const _matrix$1 = /*@__PURE__*/ new Matrix4();
25777const _whiteColor = /*@__PURE__*/ new Color( 1, 1, 1 );
25778const _frustum = /*@__PURE__*/ new Frustum();
25779const _frustumArray = /*@__PURE__*/ new FrustumArray();
25780const _box$1 = /*@__PURE__*/ new Box3();
25781const _sphere$2 = /*@__PURE__*/ new Sphere();
25782const _vector$5 = /*@__PURE__*/ new Vector3();
25783const _forward$1 = /*@__PURE__*/ new Vector3();
25784const _temp = /*@__PURE__*/ new Vector3();
25785const _renderList = /*@__PURE__*/ new MultiDrawRenderList();
25786const _mesh = /*@__PURE__*/ new Mesh();
25787const _batchIntersects = [];
25788
25789// copies data from attribute "src" into "target" starting at "targetOffset"
25790function copyAttributeData( src, target, targetOffset = 0 ) {
25791
25792	const itemSize = target.itemSize;
25793	if ( src.isInterleavedBufferAttribute || src.array.constructor !== target.array.constructor ) {
25794
25795		// use the component getters and setters if the array data cannot
25796		// be copied directly
25797		const vertexCount = src.count;
25798		for ( let i = 0; i < vertexCount; i ++ ) {
25799
25800			for ( let c = 0; c < itemSize; c ++ ) {
25801
25802				target.setComponent( i + targetOffset, c, src.getComponent( i, c ) );
25803
25804			}
25805
25806		}
25807
25808	} else {
25809
25810		// faster copy approach using typed array set function
25811		target.array.set( src.array, targetOffset * itemSize );
25812
25813	}
25814
25815	target.needsUpdate = true;
25816
25817}
25818
25819// safely copies array contents to a potentially smaller array
25820function copyArrayContents( src, target ) {
25821
25822	if ( src.constructor !== target.constructor ) {
25823
25824		// if arrays are of a different type (eg due to index size increasing) then data must be per-element copied
25825		const len = Math.min( src.length, target.length );
25826		for ( let i = 0; i < len; i ++ ) {
25827
25828			target[ i ] = src[ i ];
25829
25830		}
25831
25832	} else {
25833
25834		// if the arrays use the same data layout we can use a fast block copy
25835		const len = Math.min( src.length, target.length );
25836		target.set( new src.constructor( src.buffer, 0, len ) );
25837
25838	}
25839
25840}
25841
25842/**
25843 * A special version of a mesh with multi draw batch rendering support. Use
25844 * this class if you have to render a large number of objects with the same
25845 * material but with different geometries or world transformations. The usage of
25846 * `BatchedMesh` will help you to reduce the number of draw calls and thus improve the overall
25847 * rendering performance in your application.
25848 *
25849 * ```js
25850 * const box = new THREE.BoxGeometry( 1, 1, 1 );
25851 * const sphere = new THREE.SphereGeometry( 1, 12, 12 );
25852 * const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
25853 *
25854 * // initialize and add geometries into the batched mesh
25855 * const batchedMesh = new BatchedMesh( 10, 5000, 10000, material );
25856 * const boxGeometryId = batchedMesh.addGeometry( box );
25857 * const sphereGeometryId = batchedMesh.addGeometry( sphere );
25858 *
25859 * // create instances of those geometries
25860 * const boxInstancedId1 = batchedMesh.addInstance( boxGeometryId );
25861 * const boxInstancedId2 = batchedMesh.addInstance( boxGeometryId );
25862 *
25863 * const sphereInstancedId1 = batchedMesh.addInstance( sphereGeometryId );
25864 * const sphereInstancedId2 = batchedMesh.addInstance( sphereGeometryId );
25865 *
25866 * // position the geometries
25867 * batchedMesh.setMatrixAt( boxInstancedId1, boxMatrix1 );
25868 * batchedMesh.setMatrixAt( boxInstancedId2, boxMatrix2 );
25869 *
25870 * batchedMesh.setMatrixAt( sphereInstancedId1, sphereMatrix1 );
25871 * batchedMesh.setMatrixAt( sphereInstancedId2, sphereMatrix2 );
25872 *
25873 * scene.add( batchedMesh );
25874 * ```
25875 *
25876 * @augments Mesh
25877 */
25878class BatchedMesh extends Mesh {
25879
25880	/**
25881	 * Constructs a new batched mesh.
25882	 *
25883	 * @param {number} maxInstanceCount - The maximum number of individual instances planned to be added and rendered.
25884	 * @param {number} maxVertexCount - The maximum number of vertices to be used by all unique geometries.
25885	 * @param {number} [maxIndexCount=maxVertexCount*2] - The maximum number of indices to be used by all unique geometries
25886	 * @param {Material|Array<Material>} [material] - The mesh material.
25887	 */
25888	constructor( maxInstanceCount, maxVertexCount, maxIndexCount = maxVertexCount * 2, material ) {
25889
25890		super( new BufferGeometry(), material );
25891
25892		/**
25893		 * This flag can be used for type testing.
25894		 *
25895		 * @type {boolean}
25896		 * @readonly
25897		 * @default true
25898		 */
25899		this.isBatchedMesh = true;
25900
25901		/**
25902		 * When set ot `true`, the individual objects of a batch are frustum culled.
25903		 *
25904		 * @type {boolean}
25905		 * @default true
25906		 */
25907		this.perObjectFrustumCulled = true;
25908
25909		/**
25910		 * When set to `true`, the individual objects of a batch are sorted to improve overdraw-related artifacts.
25911		 * If the material is marked as "transparent" objects are rendered back to front and if not then they are
25912		 * rendered front to back.
25913		 *
25914		 * @type {boolean}
25915		 * @default true
25916		 */
25917		this.sortObjects = true;
25918
25919		/**
25920		 * The bounding box of the batched mesh. Can be computed via {@link BatchedMesh#computeBoundingBox}.
25921		 *
25922		 * @type {?Box3}
25923		 * @default null
25924		 */
25925		this.boundingBox = null;
25926
25927		/**
25928		 * The bounding sphere of the batched mesh. Can be computed via {@link BatchedMesh#computeBoundingSphere}.
25929		 *
25930		 * @type {?Sphere}
25931		 * @default null
25932		 */
25933		this.boundingSphere = null;
25934
25935		/**
25936		 * Takes a sort a function that is run before render. The function takes a list of instances to
25937		 * sort and a camera. The objects in the list include a "z" field to perform a depth-ordered
25938		 * sort with.
25939		 *
25940		 * @type {?Function}
25941		 * @default null
25942		 */
25943		this.customSort = null;
25944
25945		// stores visible, active, and geometry id per instance and reserved buffer ranges for geometries
25946		this._instanceInfo = [];
25947		this._geometryInfo = [];
25948
25949		// instance, geometry ids that have been set as inactive, and are available to be overwritten
25950		this._availableInstanceIds = [];
25951		this._availableGeometryIds = [];
25952
25953		// used to track where the next point is that geometry should be inserted
25954		this._nextIndexStart = 0;
25955		this._nextVertexStart = 0;
25956		this._geometryCount = 0;
25957
25958		// flags
25959		this._visibilityChanged = true;
25960		this._geometryInitialized = false;
25961
25962		// cached user options
25963		this._maxInstanceCount = maxInstanceCount;
25964		this._maxVertexCount = maxVertexCount;
25965		this._maxIndexCount = maxIndexCount;
25966
25967		// buffers for multi draw
25968		this._multiDrawCounts = new Int32Array( maxInstanceCount );
25969		this._multiDrawStarts = new Int32Array( maxInstanceCount );
25970		this._multiDrawCount = 0
vendor: 25,687 bytes, lines 25970-26901
25970;
25971
25972		// Local matrix per geometry by using data texture
25973		this._matricesTexture = null;
25974		this._indirectTexture = null;
25975		this._colorsTexture = null;
25976
25977		this._initMatricesTexture();
25978		this._initIndirectTexture();
25979
25980	}
25981
25982	/**
25983	 * The maximum number of individual instances that can be stored in the batch.
25984	 *
25985	 * @type {number}
25986	 * @readonly
25987	 */
25988	get maxInstanceCount() {
25989
25990		return this._maxInstanceCount;
25991
25992	}
25993
25994	/**
25995	 * The instance count.
25996	 *
25997	 * @type {number}
25998	 * @readonly
25999	 */
26000	get instanceCount() {
26001
26002		return this._instanceInfo.length - this._availableInstanceIds.length;
26003
26004	}
26005
26006	/**
26007	 * The number of unused vertices.
26008	 *
26009	 * @type {number}
26010	 * @readonly
26011	 */
26012	get unusedVertexCount() {
26013
26014		return this._maxVertexCount - this._nextVertexStart;
26015
26016	}
26017
26018	/**
26019	 * The number of unused indices.
26020	 *
26021	 * @type {number}
26022	 * @readonly
26023	 */
26024	get unusedIndexCount() {
26025
26026		return this._maxIndexCount - this._nextIndexStart;
26027
26028	}
26029
26030	_initMatricesTexture() {
26031
26032		// layout (1 matrix = 4 pixels)
26033		//      RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)
26034		//  with  8x8  pixel texture max   16 matrices * 4 pixels =  (8 * 8)
26035		//       16x16 pixel texture max   64 matrices * 4 pixels = (16 * 16)
26036		//       32x32 pixel texture max  256 matrices * 4 pixels = (32 * 32)
26037		//       64x64 pixel texture max 1024 matrices * 4 pixels = (64 * 64)
26038
26039		let size = Math.sqrt( this._maxInstanceCount * 4 ); // 4 pixels needed for 1 matrix
26040		size = Math.ceil( size / 4 ) * 4;
26041		size = Math.max( size, 4 );
26042
26043		const matricesArray = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel
26044		const matricesTexture = new DataTexture( matricesArray, size, size, RGBAFormat, FloatType );
26045
26046		this._matricesTexture = matricesTexture;
26047
26048	}
26049
26050	_initIndirectTexture() {
26051
26052		let size = Math.sqrt( this._maxInstanceCount );
26053		size = Math.ceil( size );
26054
26055		const indirectArray = new Uint32Array( size * size );
26056		const indirectTexture = new DataTexture( indirectArray, size, size, RedIntegerFormat, UnsignedIntType );
26057
26058		this._indirectTexture = indirectTexture;
26059
26060	}
26061
26062	_initColorsTexture() {
26063
26064		let size = Math.sqrt( this._maxInstanceCount );
26065		size = Math.ceil( size );
26066
26067		// 4 floats per RGBA pixel initialized to white
26068		const colorsArray = new Float32Array( size * size * 4 ).fill( 1 );
26069		const colorsTexture = new DataTexture( colorsArray, size, size, RGBAFormat, FloatType );
26070		colorsTexture.colorSpace = ColorManagement.workingColorSpace;
26071
26072		this._colorsTexture = colorsTexture;
26073
26074	}
26075
26076	_initializeGeometry( reference ) {
26077
26078		const geometry = this.geometry;
26079		const maxVertexCount = this._maxVertexCount;
26080		const maxIndexCount = this._maxIndexCount;
26081		if ( this._geometryInitialized === false ) {
26082
26083			for ( const attributeName in reference.attributes ) {
26084
26085				const srcAttribute = reference.getAttribute( attributeName );
26086				const { array, itemSize, normalized } = srcAttribute;
26087
26088				const dstArray = new array.constructor( maxVertexCount * itemSize );
26089				const dstAttribute = new BufferAttribute( dstArray, itemSize, normalized );
26090
26091				geometry.setAttribute( attributeName, dstAttribute );
26092
26093			}
26094
26095			if ( reference.getIndex() !== null ) {
26096
26097				// Reserve last u16 index for primitive restart.
26098				const indexArray = maxVertexCount > 65535
26099					? new Uint32Array( maxIndexCount )
26100					: new Uint16Array( maxIndexCount );
26101
26102				geometry.setIndex( new BufferAttribute( indexArray, 1 ) );
26103
26104			}
26105
26106			this._geometryInitialized = true;
26107
26108		}
26109
26110	}
26111
26112	// Make sure the geometry is compatible with the existing combined geometry attributes
26113	_validateGeometry( geometry ) {
26114
26115		// check to ensure the geometries are using consistent attributes and indices
26116		const batchGeometry = this.geometry;
26117		if ( Boolean( geometry.getIndex() ) !== Boolean( batchGeometry.getIndex() ) ) {
26118
26119			throw new Error( 'THREE.BatchedMesh: All geometries must consistently have "index".' );
26120
26121		}
26122
26123		for ( const attributeName in batchGeometry.attributes ) {
26124
26125			if ( ! geometry.hasAttribute( attributeName ) ) {
26126
26127				throw new Error( `THREE.BatchedMesh: Added geometry missing "${ attributeName }". All geometries must have consistent attributes.` );
26128
26129			}
26130
26131			const srcAttribute = geometry.getAttribute( attributeName );
26132			const dstAttribute = batchGeometry.getAttribute( attributeName );
26133			if ( srcAttribute.itemSize !== dstAttribute.itemSize || srcAttribute.normalized !== dstAttribute.normalized ) {
26134
26135				throw new Error( 'THREE.BatchedMesh: All attributes must have a consistent itemSize and normalized value.' );
26136
26137			}
26138
26139		}
26140
26141	}
26142
26143	/**
26144	 * Validates the instance defined by the given ID.
26145	 *
26146	 * @param {number} instanceId - The instance to validate.
26147	 */
26148	validateInstanceId( instanceId ) {
26149
26150		const instanceInfo = this._instanceInfo;
26151		if ( instanceId < 0 || instanceId >= instanceInfo.length || instanceInfo[ instanceId ].active === false ) {
26152
26153			throw new Error( `THREE.BatchedMesh: Invalid instanceId ${instanceId}. Instance is either out of range or has been deleted.` );
26154
26155		}
26156
26157	}
26158
26159	/**
26160	 * Validates the geometry defined by the given ID.
26161	 *
26162	 * @param {number} geometryId - The geometry to validate.
26163	 */
26164	validateGeometryId( geometryId ) {
26165
26166		const geometryInfoList = this._geometryInfo;
26167		if ( geometryId < 0 || geometryId >= geometryInfoList.length || geometryInfoList[ geometryId ].active === false ) {
26168
26169			throw new Error( `THREE.BatchedMesh: Invalid geometryId ${geometryId}. Geometry is either out of range or has been deleted.` );
26170
26171		}
26172
26173	}
26174
26175	/**
26176	 * Takes a sort a function that is run before render. The function takes a list of instances to
26177	 * sort and a camera. The objects in the list include a "z" field to perform a depth-ordered sort with.
26178	 *
26179	 * @param {Function} func - The custom sort function.
26180	 * @return {BatchedMesh} A reference to this batched mesh.
26181	 */
26182	setCustomSort( func ) {
26183
26184		this.customSort = func;
26185		return this;
26186
26187	}
26188
26189	/**
26190	 * Computes the bounding box, updating {@link BatchedMesh#boundingBox}.
26191	 * Bounding boxes aren't computed by default. They need to be explicitly computed,
26192	 * otherwise they are `null`.
26193	 */
26194	computeBoundingBox() {
26195
26196		if ( this.boundingBox === null ) {
26197
26198			this.boundingBox = new Box3();
26199
26200		}
26201
26202		const boundingBox = this.boundingBox;
26203		const instanceInfo = this._instanceInfo;
26204
26205		boundingBox.makeEmpty();
26206		for ( let i = 0, l = instanceInfo.length; i < l; i ++ ) {
26207
26208			if ( instanceInfo[ i ].active === false ) continue;
26209
26210			const geometryId = instanceInfo[ i ].geometryIndex;
26211			this.getMatrixAt( i, _matrix$1 );
26212			this.getBoundingBoxAt( geometryId, _box$1 ).applyMatrix4( _matrix$1 );
26213			boundingBox.union( _box$1 );
26214
26215		}
26216
26217	}
26218
26219	/**
26220	 * Computes the bounding sphere, updating {@link BatchedMesh#boundingSphere}.
26221	 * Bounding spheres aren't computed by default. They need to be explicitly computed,
26222	 * otherwise they are `null`.
26223	 */
26224	computeBoundingSphere() {
26225
26226		if ( this.boundingSphere === null ) {
26227
26228			this.boundingSphere = new Sphere();
26229
26230		}
26231
26232		const boundingSphere = this.boundingSphere;
26233		const instanceInfo = this._instanceInfo;
26234
26235		boundingSphere.makeEmpty();
26236		for ( let i = 0, l = instanceInfo.length; i < l; i ++ ) {
26237
26238			if ( instanceInfo[ i ].active === false ) continue;
26239
26240			const geometryId = instanceInfo[ i ].geometryIndex;
26241			this.getMatrixAt( i, _matrix$1 );
26242			this.getBoundingSphereAt( geometryId, _sphere$2 ).applyMatrix4( _matrix$1 );
26243			boundingSphere.union( _sphere$2 );
26244
26245		}
26246
26247	}
26248
26249	/**
26250	 * Adds a new instance to the batch using the geometry of the given ID and returns
26251	 * a new id referring to the new instance to be used by other functions.
26252	 *
26253	 * @param {number} geometryId - The ID of a previously added geometry via {@link BatchedMesh#addGeometry}.
26254	 * @return {number} The instance ID.
26255	 */
26256	addInstance( geometryId ) {
26257
26258		const atCapacity = this._instanceInfo.length >= this.maxInstanceCount;
26259
26260		// ensure we're not over geometry
26261		if ( atCapacity && this._availableInstanceIds.length === 0 ) {
26262
26263			throw new Error( 'THREE.BatchedMesh: Maximum item count reached.' );
26264
26265		}
26266
26267		const instanceInfo = {
26268			visible: true,
26269			active: true,
26270			geometryIndex: geometryId,
26271		};
26272
26273		let drawId = null;
26274
26275		// Prioritize using previously freed instance ids
26276		if ( this._availableInstanceIds.length > 0 ) {
26277
26278			this._availableInstanceIds.sort( ascIdSort );
26279
26280			drawId = this._availableInstanceIds.shift();
26281			this._instanceInfo[ drawId ] = instanceInfo;
26282
26283		} else {
26284
26285			drawId = this._instanceInfo.length;
26286			this._instanceInfo.push( instanceInfo );
26287
26288		}
26289
26290		const matricesTexture = this._matricesTexture;
26291		_matrix$1.identity().toArray( matricesTexture.image.data, drawId * 16 );
26292		matricesTexture.needsUpdate = true;
26293
26294		const colorsTexture = this._colorsTexture;
26295		if ( colorsTexture ) {
26296
26297			_whiteColor.toArray( colorsTexture.image.data, drawId * 4 );
26298			colorsTexture.needsUpdate = true;
26299
26300		}
26301
26302		this._visibilityChanged = true;
26303		return drawId;
26304
26305	}
26306
26307	/**
26308	 * Adds the given geometry to the batch and returns the associated
26309	 * geometry id referring to it to be used in other functions.
26310	 *
26311	 * @param {BufferGeometry} geometry - The geometry to add.
26312	 * @param {number} [reservedVertexCount=-1] - Optional parameter specifying the amount of
26313	 * vertex buffer space to reserve for the added geometry. This is necessary if it is planned
26314	 * to set a new geometry at this index at a later time that is larger than the original geometry.
26315	 * Defaults to the length of the given geometry vertex buffer.
26316	 * @param {number} [reservedIndexCount=-1] - Optional parameter specifying the amount of index
26317	 * buffer space to reserve for the added geometry. This is necessary if it is planned to set a
26318	 * new geometry at this index at a later time that is larger than the original geometry. Defaults to
26319	 * the length of the given geometry index buffer.
26320	 * @return {number} The geometry ID.
26321	 */
26322	addGeometry( geometry, reservedVertexCount = -1, reservedIndexCount = -1 ) {
26323
26324		this._initializeGeometry( geometry );
26325
26326		this._validateGeometry( geometry );
26327
26328		const geometryInfo = {
26329			// geometry information
26330			vertexStart: -1,
26331			vertexCount: -1,
26332			reservedVertexCount: -1,
26333
26334			indexStart: -1,
26335			indexCount: -1,
26336			reservedIndexCount: -1,
26337
26338			// draw range information
26339			start: -1,
26340			count: -1,
26341
26342			// state
26343			boundingBox: null,
26344			boundingSphere: null,
26345			active: true,
26346		};
26347
26348		const geometryInfoList = this._geometryInfo;
26349		geometryInfo.vertexStart = this._nextVertexStart;
26350		geometryInfo.reservedVertexCount = reservedVertexCount === -1 ? geometry.getAttribute( 'position' ).count : reservedVertexCount;
26351
26352		const index = geometry.getIndex();
26353		const hasIndex = index !== null;
26354		if ( hasIndex ) {
26355
26356			geometryInfo.indexStart = this._nextIndexStart;
26357			geometryInfo.reservedIndexCount = reservedIndexCount === -1 ? index.count : reservedIndexCount;
26358
26359		}
26360
26361		if (
26362			geometryInfo.indexStart !== -1 &&
26363			geometryInfo.indexStart + geometryInfo.reservedIndexCount > this._maxIndexCount ||
26364			geometryInfo.vertexStart + geometryInfo.reservedVertexCount > this._maxVertexCount
26365		) {
26366
26367			throw new Error( 'THREE.BatchedMesh: Reserved space request exceeds the maximum buffer size.' );
26368
26369		}
26370
26371		// update id
26372		let geometryId;
26373		if ( this._availableGeometryIds.length > 0 ) {
26374
26375			this._availableGeometryIds.sort( ascIdSort );
26376
26377			geometryId = this._availableGeometryIds.shift();
26378			geometryInfoList[ geometryId ] = geometryInfo;
26379
26380
26381		} else {
26382
26383			geometryId = this._geometryCount;
26384			this._geometryCount ++;
26385			geometryInfoList.push( geometryInfo );
26386
26387		}
26388
26389		// update the geometry
26390		this.setGeometryAt( geometryId, geometry );
26391
26392		// increment the next geometry position
26393		this._nextIndexStart = geometryInfo.indexStart + geometryInfo.reservedIndexCount;
26394		this._nextVertexStart = geometryInfo.vertexStart + geometryInfo.reservedVertexCount;
26395
26396		return geometryId;
26397
26398	}
26399
26400	/**
26401	 * Replaces the geometry at the given ID with the provided geometry. Throws an error if there
26402	 * is not enough space reserved for geometry. Calling this will change all instances that are
26403	 * rendering that geometry.
26404	 *
26405	 * @param {number} geometryId - The ID of the geometry that should be replaced with the given geometry.
26406	 * @param {BufferGeometry} geometry - The new geometry.
26407	 * @return {number} The geometry ID.
26408	 */
26409	setGeometryAt( geometryId, geometry ) {
26410
26411		if ( geometryId >= this._geometryCount ) {
26412
26413			throw new Error( 'THREE.BatchedMesh: Maximum geometry count reached.' );
26414
26415		}
26416
26417		this._validateGeometry( geometry );
26418
26419		const batchGeometry = this.geometry;
26420		const hasIndex = batchGeometry.getIndex() !== null;
26421		const dstIndex = batchGeometry.getIndex();
26422		const srcIndex = geometry.getIndex();
26423		const geometryInfo = this._geometryInfo[ geometryId ];
26424		if (
26425			hasIndex &&
26426			srcIndex.count > geometryInfo.reservedIndexCount ||
26427			geometry.attributes.position.count > geometryInfo.reservedVertexCount
26428		) {
26429
26430			throw new Error( 'THREE.BatchedMesh: Reserved space not large enough for provided geometry.' );
26431
26432		}
26433
26434		// copy geometry buffer data over
26435		const vertexStart = geometryInfo.vertexStart;
26436		const reservedVertexCount = geometryInfo.reservedVertexCount;
26437		geometryInfo.vertexCount = geometry.getAttribute( 'position' ).count;
26438
26439		for ( const attributeName in batchGeometry.attributes ) {
26440
26441			// copy attribute data
26442			const srcAttribute = geometry.getAttribute( attributeName );
26443			const dstAttribute = batchGeometry.getAttribute( attributeName );
26444			copyAttributeData( srcAttribute, dstAttribute, vertexStart );
26445
26446			// fill the rest in with zeroes
26447			const itemSize = srcAttribute.itemSize;
26448			for ( let i = srcAttribute.count, l = reservedVertexCount; i < l; i ++ ) {
26449
26450				const index = vertexStart + i;
26451				for ( let c = 0; c < itemSize; c ++ ) {
26452
26453					dstAttribute.setComponent( index, c, 0 );
26454
26455				}
26456
26457			}
26458
26459			dstAttribute.needsUpdate = true;
26460			dstAttribute.addUpdateRange( vertexStart * itemSize, reservedVertexCount * itemSize );
26461
26462		}
26463
26464		// copy index
26465		if ( hasIndex ) {
26466
26467			const indexStart = geometryInfo.indexStart;
26468			const reservedIndexCount = geometryInfo.reservedIndexCount;
26469			geometryInfo.indexCount = geometry.getIndex().count;
26470
26471			// copy index data over
26472			for ( let i = 0; i < srcIndex.count; i ++ ) {
26473
26474				dstIndex.setX( indexStart + i, vertexStart + srcIndex.getX( i ) );
26475
26476			}
26477
26478			// fill the rest in with zeroes
26479			for ( let i = srcIndex.count, l = reservedIndexCount; i < l; i ++ ) {
26480
26481				dstIndex.setX( indexStart + i, vertexStart );
26482
26483			}
26484
26485			dstIndex.needsUpdate = true;
26486			dstIndex.addUpdateRange( indexStart, geometryInfo.reservedIndexCount );
26487
26488		}
26489
26490		// update the draw range
26491		geometryInfo.start = hasIndex ? geometryInfo.indexStart : geometryInfo.vertexStart;
26492		geometryInfo.count = hasIndex ? geometryInfo.indexCount : geometryInfo.vertexCount;
26493
26494		// store the bounding boxes
26495		geometryInfo.boundingBox = null;
26496		if ( geometry.boundingBox !== null ) {
26497
26498			geometryInfo.boundingBox = geometry.boundingBox.clone();
26499
26500		}
26501
26502		geometryInfo.boundingSphere = null;
26503		if ( geometry.boundingSphere !== null ) {
26504
26505			geometryInfo.boundingSphere = geometry.boundingSphere.clone();
26506
26507		}
26508
26509		this._visibilityChanged = true;
26510		return geometryId;
26511
26512	}
26513
26514	/**
26515	 * Deletes the geometry defined by the given ID from this batch. Any instances referencing
26516	 * this geometry will also be removed as a side effect.
26517	 *
26518	 * @param {number} geometryId - The ID of the geometry to remove from the batch.
26519	 * @return {BatchedMesh} A reference to this batched mesh.
26520	 */
26521	deleteGeometry( geometryId ) {
26522
26523		const geometryInfoList = this._geometryInfo;
26524		if ( geometryId >= geometryInfoList.length || geometryInfoList[ geometryId ].active === false ) {
26525
26526			return this;
26527
26528		}
26529
26530		// delete any instances associated with this geometry
26531		const instanceInfo = this._instanceInfo;
26532		for ( let i = 0, l = instanceInfo.length; i < l; i ++ ) {
26533
26534			if ( instanceInfo[ i ].active && instanceInfo[ i ].geometryIndex === geometryId ) {
26535
26536				this.deleteInstance( i );
26537
26538			}
26539
26540		}
26541
26542		geometryInfoList[ geometryId ].active = false;
26543		this._availableGeometryIds.push( geometryId );
26544		this._visibilityChanged = true;
26545
26546		return this;
26547
26548	}
26549
26550	/**
26551	 * Deletes an existing instance from the batch using the given ID.
26552	 *
26553	 * @param {number} instanceId - The ID of the instance to remove from the batch.
26554	 * @return {BatchedMesh} A reference to this batched mesh.
26555	 */
26556	deleteInstance( instanceId ) {
26557
26558		this.validateInstanceId( instanceId );
26559
26560		this._instanceInfo[ instanceId ].active = false;
26561		this._availableInstanceIds.push( instanceId );
26562		this._visibilityChanged = true;
26563
26564		return this;
26565
26566	}
26567
26568	/**
26569	 * Repacks the sub geometries in BatchedMesh to remove any unused space remaining from
26570	 * previously deleted geometry, freeing up space to add new geometry.
26571	 *
26572	 * @return {BatchedMesh} A reference to this batched mesh.
26573	 */
26574	optimize() {
26575
26576		// track the next indices to copy data to
26577		let nextVertexStart = 0;
26578		let nextIndexStart = 0;
26579
26580		// Iterate over all geometry ranges in order sorted from earliest in the geometry buffer to latest
26581		// in the geometry buffer. Because draw range objects can be reused there is no guarantee of their order.
26582		const geometryInfoList = this._geometryInfo;
26583		const indices = geometryInfoList
26584			.map( ( e, i ) => i )
26585			.sort( ( a, b ) => {
26586
26587				return geometryInfoList[ a ].vertexStart - geometryInfoList[ b ].vertexStart;
26588
26589			} );
26590
26591		const geometry = this.geometry;
26592		for ( let i = 0, l = geometryInfoList.length; i < l; i ++ ) {
26593
26594			// if a geometry range is inactive then don't copy anything
26595			const index = indices[ i ];
26596			const geometryInfo = geometryInfoList[ index ];
26597			if ( geometryInfo.active === false ) {
26598
26599				continue;
26600
26601			}
26602
26603			// if a geometry contains an index buffer then shift it, as well
26604			if ( geometry.index !== null ) {
26605
26606				if ( geometryInfo.indexStart !== nextIndexStart ) {
26607
26608					const { indexStart, vertexStart, reservedIndexCount } = geometryInfo;
26609					const index = geometry.index;
26610					const array = index.array;
26611
26612					// shift the index pointers based on how the vertex data will shift
26613					// adjusting the index must happen first so the original vertex start value is available
26614					const elementDelta = nextVertexStart - vertexStart;
26615					for ( let j = indexStart; j < indexStart + reservedIndexCount; j ++ ) {
26616
26617						array[ j ] = array[ j ] + elementDelta;
26618
26619					}
26620
26621					index.array.copyWithin( nextIndexStart, indexStart, indexStart + reservedIndexCount );
26622					index.addUpdateRange( nextIndexStart, reservedIndexCount );
26623					index.needsUpdate = true;
26624
26625					geometryInfo.indexStart = nextIndexStart;
26626
26627				}
26628
26629				nextIndexStart += geometryInfo.reservedIndexCount;
26630
26631			}
26632
26633			// if a geometry needs to be moved then copy attribute data to overwrite unused space
26634			if ( geometryInfo.vertexStart !== nextVertexStart ) {
26635
26636				const { vertexStart, reservedVertexCount } = geometryInfo;
26637				const attributes = geometry.attributes;
26638				for ( const key in attributes ) {
26639
26640					const attribute = attributes[ key ];
26641					const { array, itemSize } = attribute;
26642					array.copyWithin( nextVertexStart * itemSize, vertexStart * itemSize, ( vertexStart + reservedVertexCount ) * itemSize );
26643					attribute.addUpdateRange( nextVertexStart * itemSize, reservedVertexCount * itemSize );
26644					attribute.needsUpdate = true;
26645
26646				}
26647
26648				geometryInfo.vertexStart = nextVertexStart;
26649
26650			}
26651
26652			nextVertexStart += geometryInfo.reservedVertexCount;
26653			geometryInfo.start = geometry.index ? geometryInfo.indexStart : geometryInfo.vertexStart;
26654
26655		}
26656
26657		this._nextIndexStart = nextIndexStart;
26658		this._nextVertexStart = nextVertexStart;
26659		this._visibilityChanged = true;
26660
26661		return this;
26662
26663	}
26664
26665	/**
26666	 * Returns the bounding box for the given geometry.
26667	 *
26668	 * @param {number} geometryId - The ID of the geometry to return the bounding box for.
26669	 * @param {Box3} target - The target object that is used to store the method's result.
26670	 * @return {?Box3} The geometry's bounding box. Returns `null` if no geometry has been found for the given ID.
26671	 */
26672	getBoundingBoxAt( geometryId, target ) {
26673
26674		if ( geometryId >= this._geometryCount ) {
26675
26676			return null;
26677
26678		}
26679
26680		// compute bounding box
26681		const geometry = this.geometry;
26682		const geometryInfo = this._geometryInfo[ geometryId ];
26683		if ( geometryInfo.boundingBox === null ) {
26684
26685			const box = new Box3();
26686			const index = geometry.index;
26687			const position = geometry.attributes.position;
26688			for ( let i = geometryInfo.start, l = geometryInfo.start + geometryInfo.count; i < l; i ++ ) {
26689
26690				let iv = i;
26691				if ( index ) {
26692
26693					iv = index.getX( iv );
26694
26695				}
26696
26697				box.expandByPoint( _vector$5.fromBufferAttribute( position, iv ) );
26698
26699			}
26700
26701			geometryInfo.boundingBox = box;
26702
26703		}
26704
26705		target.copy( geometryInfo.boundingBox );
26706		return target;
26707
26708	}
26709
26710	/**
26711	 * Returns the bounding sphere for the given geometry.
26712	 *
26713	 * @param {number} geometryId - The ID of the geometry to return the bounding sphere for.
26714	 * @param {Sphere} target - The target object that is used to store the method's result.
26715	 * @return {?Sphere} The geometry's bounding sphere. Returns `null` if no geometry has been found for the given ID.
26716	 */
26717	getBoundingSphereAt( geometryId, target ) {
26718
26719		if ( geometryId >= this._geometryCount ) {
26720
26721			return null;
26722
26723		}
26724
26725		// compute bounding sphere
26726		const geometry = this.geometry;
26727		const geometryInfo = this._geometryInfo[ geometryId ];
26728		if ( geometryInfo.boundingSphere === null ) {
26729
26730			const sphere = new Sphere();
26731			this.getBoundingBoxAt( geometryId, _box$1 );
26732			_box$1.getCenter( sphere.center );
26733
26734			const index = geometry.index;
26735			const position = geometry.attributes.position;
26736
26737			let maxRadiusSq = 0;
26738			for ( let i = geometryInfo.start, l = geometryInfo.start + geometryInfo.count; i < l; i ++ ) {
26739
26740				let iv = i;
26741				if ( index ) {
26742
26743					iv = index.getX( iv );
26744
26745				}
26746
26747				_vector$5.fromBufferAttribute( position, iv );
26748				maxRadiusSq = Math.max( maxRadiusSq, sphere.center.distanceToSquared( _vector$5 ) );
26749
26750			}
26751
26752			sphere.radius = Math.sqrt( maxRadiusSq );
26753			geometryInfo.boundingSphere = sphere;
26754
26755		}
26756
26757		target.copy( geometryInfo.boundingSphere );
26758		return target;
26759
26760	}
26761
26762	/**
26763	 * Sets the given local transformation matrix to the defined instance.
26764	 * Negatively scaled matrices are not supported.
26765	 *
26766	 * @param {number} instanceId - The ID of an instance to set the matrix of.
26767	 * @param {Matrix4} matrix - A 4x4 matrix representing the local transformation of a single instance.
26768	 * @return {BatchedMesh} A reference to this batched mesh.
26769	 */
26770	setMatrixAt( instanceId, matrix ) {
26771
26772		this.validateInstanceId( instanceId );
26773
26774		const matricesTexture = this._matricesTexture;
26775		const matricesArray = this._matricesTexture.image.data;
26776		matrix.toArray( matricesArray, instanceId * 16 );
26777		matricesTexture.needsUpdate = true;
26778
26779		return this;
26780
26781	}
26782
26783	/**
26784	 * Returns the local transformation matrix of the defined instance.
26785	 *
26786	 * @param {number} instanceId - The ID of an instance to get the matrix of.
26787	 * @param {Matrix4} matrix - The target object that is used to store the method's result.
26788	 * @return {Matrix4} The instance's local transformation matrix.
26789	 */
26790	getMatrixAt( instanceId, matrix ) {
26791
26792		this.validateInstanceId( instanceId );
26793		return matrix.fromArray( this._matricesTexture.image.data, instanceId * 16 );
26794
26795	}
26796
26797	/**
26798	 * Sets the given color to the defined instance.
26799	 *
26800	 * @param {number} instanceId - The ID of an instance to set the color of.
26801	 * @param {Color|Vector4} color - The color to set the instance to. Use a `Vector4` to also define alpha.
26802	 * @return {BatchedMesh} A reference to this batched mesh.
26803	 */
26804	setColorAt( instanceId, color ) {
26805
26806		this.validateInstanceId( instanceId );
26807
26808		if ( this._colorsTexture === null ) {
26809
26810			this._initColorsTexture();
26811
26812		}
26813
26814		color.toArray( this._colorsTexture.image.data, instanceId * 4 );
26815		this._colorsTexture.needsUpdate = true;
26816
26817		return this;
26818
26819	}
26820
26821	/**
26822	 * Returns the color of the defined instance.
26823	 *
26824	 * @param {number} instanceId - The ID of an instance to get the color of.
26825	 * @param {Color|Vector4} color - The target object that is used to store the method's result.
26826	 * @return {Color|Vector4} The instance's color.  Use a `Vector4` to also retrieve alpha.
26827	 */
26828	getColorAt( instanceId, color ) {
26829
26830		this.validateInstanceId( instanceId );
26831		if ( this._colorsTexture === null ) {
26832
26833			if ( color.isVector4 ) {
26834
26835				return color.set( 1, 1, 1, 1 );
26836
26837			} else {
26838
26839				return color.setRGB( 1, 1, 1 );
26840
26841			}
26842
26843		} else {
26844
26845			return color.fromArray( this._colorsTexture.image.data, instanceId * 4 );
26846
26847		}
26848
26849	}
26850
26851	/**
26852	 * Sets the visibility of the instance.
26853	 *
26854	 * @param {number} instanceId - The id of the instance to set the visibility of.
26855	 * @param {boolean} visible - Whether the instance is visible or not.
26856	 * @return {BatchedMesh} A reference to this batched mesh.
26857	 */
26858	setVisibleAt( instanceId, visible ) {
26859
26860		this.validateInstanceId( instanceId );
26861
26862		if ( this._instanceInfo[ instanceId ].visible === visible ) {
26863
26864			return this;
26865
26866		}
26867
26868		this._instanceInfo[ instanceId ].visible = visible;
26869		this._visibilityChanged = true;
26870
26871		return this;
26872
26873	}
26874
26875	/**
26876	 * Returns the visibility state of the defined instance.
26877	 *
26878	 * @param {number} instanceId - The ID of an instance to get the visibility state of.
26879	 * @return {boolean} Whether the instance is visible or not.
26880	 */
26881	getVisibleAt( instanceId ) {
26882
26883		this.validateInstanceId( instanceId );
26884
26885		return this._instanceInfo[ instanceId ].visible;
26886
26887	}
26888
26889	/**
26890	 * Sets the geometry ID of the instance at the given index.
26891	 *
26892	 * @param {number} instanceId - The ID of the instance to set the geometry ID of.
26893	 * @param {number} geometryId - The geometry ID to be use by the instance.
26894	 * @return {BatchedMesh} A reference to this batched mesh.
26895	 */
26896	setGeometryIdAt( instanceId, geometryId ) {
26897
26898		this.validateInstanceId( instanceId );
26899		this.validateGeometryId( geometryId );
26900
26901		this._instanceInfo[ instanceId ].geometryIndex = geometryId;
26902
26903		return this;
26904
26905	}
26906
26907	/**
26908	 * Returns the geometry ID of the defined instance.
26909	 *
26910	 * @param {number} instanceId - The ID of an instance to get the geometry ID of.
26911	 * @return {number} The instance's geometry ID.
26912	 */
26913	getGeometryIdAt( instanceId ) {
26914
26915		this.validateInstanceId( instanceId );
26916
26917		return this._instanceInfo[ instanceId ].geometryIndex;
26918
26919	}
26920
26921	/**
26922	 * Get the range representing the subset of triangles related to the attached geometry,
26923	 * indicating the starting offset and count, or `null` if invalid.
26924	 *
26925	 * @param {number} geometryId - The id of the geometry to get the range of.
26926	 * @param {Object} [target] - The target object that is used to store the method's result.
26927	 * @return {{
26928	 * 	vertexStart:number,vertexCount:number,reservedVertexCount:number,
26929	 * 	indexStart:number,indexCount:number,reservedIndexCount:number,
26930	 * 	start:number,count:number
26931	 * }} The result object with range data.
26932	 */
26933	getGeometryRangeAt( geometryId, target = {} ) {
26934
26935		this.validateGeometryId( geometryId );
26936
26937		const geometryInfo = this._geometryInfo[ geometryId ];
26938		target.vertexStart = geometryInfo.vertexStart;
26939		target.vertexCount = geometryInfo.vertexCount;
26940		target.reservedVertexCount = geometryInfo.reservedVertexCount;
26941
26942		target.indexStart = geometryInfo.indexStart;
26943		target.indexCount = geometryInfo.indexCount;
26944		target.reservedIndexCount = geometryInfo.reservedIndexCount;
26945
26946		target.start = geometryInfo.start;
26947		target.count = geometryInfo.count;
26948
26949		return target;
26950
26951	}
26952
26953	/**
26954	 * Resizes the necessary buffers to support the provided number of instances.
26955	 * If the provided arguments shrink the number of instances but there are not enough
26956	 * unused Ids at the end of the list then an error is thrown.
26957	 *
26958	 * @param {number} maxInstanceCount - The max number of individual instances that can be added and rendered by the batch.
26959	*/
vendor: 7,347 bytes, lines 26960-27189
26960	setInstanceCount( maxInstanceCount ) {
26961
26962		// shrink the available instances as much as possible
26963		const availableInstanceIds = this._availableInstanceIds;
26964		const instanceInfo = this._instanceInfo;
26965		availableInstanceIds.sort( ascIdSort );
26966		while ( availableInstanceIds[ availableInstanceIds.length - 1 ] === instanceInfo.length - 1 ) {
26967
26968			instanceInfo.pop();
26969			availableInstanceIds.pop();
26970
26971		}
26972
26973		// throw an error if it can't be shrunk to the desired size
26974		if ( maxInstanceCount < instanceInfo.length ) {
26975
26976			throw new Error( `BatchedMesh: Instance ids outside the range ${ maxInstanceCount } are being used. Cannot shrink instance count.` );
26977
26978		}
26979
26980		// copy the multi draw counts
26981		const multiDrawCounts = new Int32Array( maxInstanceCount );
26982		const multiDrawStarts = new Int32Array( maxInstanceCount );
26983		copyArrayContents( this._multiDrawCounts, multiDrawCounts );
26984		copyArrayContents( this._multiDrawStarts, multiDrawStarts );
26985
26986		this._multiDrawCounts = multiDrawCounts;
26987		this._multiDrawStarts = multiDrawStarts;
26988		this._maxInstanceCount = maxInstanceCount;
26989
26990		// update texture data for instance sampling
26991		const indirectTexture = this._indirectTexture;
26992		const matricesTexture = this._matricesTexture;
26993		const colorsTexture = this._colorsTexture;
26994
26995		indirectTexture.dispose();
26996		this._initIndirectTexture();
26997		copyArrayContents( indirectTexture.image.data, this._indirectTexture.image.data );
26998
26999		matricesTexture.dispose();
27000		this._initMatricesTexture();
27001		copyArrayContents( matricesTexture.image.data, this._matricesTexture.image.data );
27002
27003		if ( colorsTexture ) {
27004
27005			colorsTexture.dispose();
27006			this._initColorsTexture();
27007			copyArrayContents( colorsTexture.image.data, this._colorsTexture.image.data );
27008
27009		}
27010
27011	}
27012
27013	/**
27014	 * Resizes the available space in the batch's vertex and index buffer attributes to the provided sizes.
27015	 * If the provided arguments shrink the geometry buffers but there is not enough unused space at the
27016	 * end of the geometry attributes then an error is thrown.
27017	 *
27018	 * @param {number} maxVertexCount - The maximum number of vertices to be used by all unique geometries to resize to.
27019	 * @param {number} maxIndexCount - The maximum number of indices to be used by all unique geometries to resize to.
27020	*/
27021	setGeometrySize( maxVertexCount, maxIndexCount ) {
27022
27023		// Check if we can shrink to the requested vertex attribute size
27024		const validRanges = [ ...this._geometryInfo ].filter( info => info.active );
27025		const requiredVertexLength = Math.max( ...validRanges.map( range => range.vertexStart + range.reservedVertexCount ) );
27026		if ( requiredVertexLength > maxVertexCount ) {
27027
27028			throw new Error( `BatchedMesh: Geometry vertex values are being used outside the range ${ maxIndexCount }. Cannot shrink further.` );
27029
27030		}
27031
27032		// Check if we can shrink to the requested index attribute size
27033		if ( this.geometry.index ) {
27034
27035			const requiredIndexLength = Math.max( ...validRanges.map( range => range.indexStart + range.reservedIndexCount ) );
27036			if ( requiredIndexLength > maxIndexCount ) {
27037
27038				throw new Error( `BatchedMesh: Geometry index values are being used outside the range ${ maxIndexCount }. Cannot shrink further.` );
27039
27040			}
27041
27042		}
27043
27044		//
27045
27046		// dispose of the previous geometry
27047		const oldGeometry = this.geometry;
27048		oldGeometry.dispose();
27049
27050		// recreate the geometry needed based on the previous variant
27051		this._maxVertexCount = maxVertexCount;
27052		this._maxIndexCount = maxIndexCount;
27053
27054		if ( this._geometryInitialized ) {
27055
27056			this._geometryInitialized = false;
27057			this.geometry = new BufferGeometry();
27058			this._initializeGeometry( oldGeometry );
27059
27060		}
27061
27062		// copy data from the previous geometry
27063		const geometry = this.geometry;
27064		if ( oldGeometry.index ) {
27065
27066			copyArrayContents( oldGeometry.index.array, geometry.index.array );
27067
27068		}
27069
27070		for ( const key in oldGeometry.attributes ) {
27071
27072			copyArrayContents( oldGeometry.attributes[ key ].array, geometry.attributes[ key ].array );
27073
27074		}
27075
27076	}
27077
27078	raycast( raycaster, intersects ) {
27079
27080		const instanceInfo = this._instanceInfo;
27081		const geometryInfoList = this._geometryInfo;
27082		const matrixWorld = this.matrixWorld;
27083		const batchGeometry = this.geometry;
27084
27085		// iterate over each geometry
27086		_mesh.material = this.material;
27087		_mesh.geometry.index = batchGeometry.index;
27088		_mesh.geometry.attributes = batchGeometry.attributes;
27089		if ( _mesh.geometry.boundingBox === null ) {
27090
27091			_mesh.geometry.boundingBox = new Box3();
27092
27093		}
27094
27095		if ( _mesh.geometry.boundingSphere === null ) {
27096
27097			_mesh.geometry.boundingSphere = new Sphere();
27098
27099		}
27100
27101		for ( let i = 0, l = instanceInfo.length; i < l; i ++ ) {
27102
27103			if ( ! instanceInfo[ i ].visible || ! instanceInfo[ i ].active ) {
27104
27105				continue;
27106
27107			}
27108
27109			const geometryId = instanceInfo[ i ].geometryIndex;
27110			const geometryInfo = geometryInfoList[ geometryId ];
27111			_mesh.geometry.setDrawRange( geometryInfo.start, geometryInfo.count );
27112
27113			// get the intersects
27114			this.getMatrixAt( i, _mesh.matrixWorld ).premultiply( matrixWorld );
27115			this.getBoundingBoxAt( geometryId, _mesh.geometry.boundingBox );
27116			this.getBoundingSphereAt( geometryId, _mesh.geometry.boundingSphere );
27117			_mesh.raycast( raycaster, _batchIntersects );
27118
27119			// add batch id to the intersects
27120			for ( let j = 0, l = _batchIntersects.length; j < l; j ++ ) {
27121
27122				const intersect = _batchIntersects[ j ];
27123				intersect.object = this;
27124				intersect.batchId = i;
27125				intersects.push( intersect );
27126
27127			}
27128
27129			_batchIntersects.length = 0;
27130
27131		}
27132
27133		_mesh.material = null;
27134		_mesh.geometry.index = null;
27135		_mesh.geometry.attributes = {};
27136		_mesh.geometry.setDrawRange( 0, Infinity );
27137
27138	}
27139
27140	copy( source ) {
27141
27142		super.copy( source );
27143
27144		this.geometry = source.geometry.clone();
27145		this.perObjectFrustumCulled = source.perObjectFrustumCulled;
27146		this.sortObjects = source.sortObjects;
27147		this.boundingBox = source.boundingBox !== null ? source.boundingBox.clone() : null;
27148		this.boundingSphere = source.boundingSphere !== null ? source.boundingSphere.clone() : null;
27149
27150		this._geometryInfo = source._geometryInfo.map( info => ( {
27151			...info,
27152
27153			boundingBox: info.boundingBox !== null ? info.boundingBox.clone() : null,
27154			boundingSphere: info.boundingSphere !== null ? info.boundingSphere.clone() : null,
27155		} ) );
27156		this._instanceInfo = source._instanceInfo.map( info => ( { ...info } ) );
27157
27158		this._availableInstanceIds = source._availableInstanceIds.slice();
27159		this._availableGeometryIds = source._availableGeometryIds.slice();
27160
27161		this._nextIndexStart = source._nextIndexStart;
27162		this._nextVertexStart = source._nextVertexStart;
27163		this._geometryCount = source._geometryCount;
27164
27165		this._maxInstanceCount = source._maxInstanceCount;
27166		this._maxVertexCount = source._maxVertexCount;
27167		this._maxIndexCount = source._maxIndexCount;
27168
27169		this._geometryInitialized = source._geometryInitialized;
27170		this._multiDrawCounts = source._multiDrawCounts.slice();
27171		this._multiDrawStarts = source._multiDrawStarts.slice();
27172
27173		this._indirectTexture = source._indirectTexture.clone();
27174		this._indirectTexture.image.data = this._indirectTexture.image.data.slice();
27175
27176		this._matricesTexture = source._matricesTexture.clone();
27177		this._matricesTexture.image.data = this._matricesTexture.image.data.slice();
27178
27179		if ( this._colorsTexture !== null ) {
27180
27181			this._colorsTexture = source._colorsTexture.clone();
27182			this._colorsTexture.image.data = this._colorsTexture.image.data.slice();
27183
27184		}
27185
27186		return this;
27187
27188	}
27189
vendor: 10,171 bytes, lines 27190-27598
27190	/**
27191	 * Frees the GPU-related resources allocated by this instance. Call this
27192	 * method whenever this instance is no longer used in your app.
27193	 */
27194	dispose() {
27195
27196		// Assuming the geometry is not shared with other meshes
27197		this.geometry.dispose();
27198
27199		this._matricesTexture.dispose();
27200		this._matricesTexture = null;
27201
27202		this._indirectTexture.dispose();
27203		this._indirectTexture = null;
27204
27205		if ( this._colorsTexture !== null ) {
27206
27207			this._colorsTexture.dispose();
27208			this._colorsTexture = null;
27209
27210		}
27211
27212	}
27213
27214	onBeforeRender( renderer, scene, camera, geometry, material/*, _group*/ ) {
27215
27216		// if visibility has not changed and frustum culling and object sorting is not required
27217		// then skip iterating over all items
27218		if ( ! this._visibilityChanged && ! this.perObjectFrustumCulled && ! this.sortObjects ) {
27219
27220			return;
27221
27222		}
27223
27224		// the indexed version of the multi draw function requires specifying the start
27225		// offset in bytes.
27226		const index = geometry.getIndex();
27227		let bytesPerElement = index === null ? 1 : index.array.BYTES_PER_ELEMENT;
27228
27229
27230		// the "wireframe" attribute implicitly creates a line attribute in the renderer, which is double
27231		// the vertices to draw (3 lines per triangle) so we multiply the draw counts / starts and make
27232		// assumptions about the index buffer byte size.
27233		let multiDrawMultiplier = 1;
27234		if ( material.wireframe ) {
27235
27236			multiDrawMultiplier = 2;
27237			bytesPerElement = geometry.attributes.position.count > 65535 ? 4 : 2;
27238
27239		}
27240
27241		const instanceInfo = this._instanceInfo;
27242		const multiDrawStarts = this._multiDrawStarts;
27243		const multiDrawCounts = this._multiDrawCounts;
27244		const geometryInfoList = this._geometryInfo;
27245		const perObjectFrustumCulled = this.perObjectFrustumCulled;
27246		const indirectTexture = this._indirectTexture;
27247		const indirectArray = indirectTexture.image.data;
27248
27249		const frustum = camera.isArrayCamera ? _frustumArray : _frustum;
27250		// prepare the frustum in the local frame
27251		if ( perObjectFrustumCulled && ! camera.isArrayCamera ) {
27252
27253			_matrix$1
27254				.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse )
27255				.multiply( this.matrixWorld );
27256
27257			_frustum.setFromProjectionMatrix(
27258				_matrix$1,
27259				camera.coordinateSystem,
27260				camera.reversedDepth
27261			);
27262
27263		}
27264
27265		let multiDrawCount = 0;
27266		if ( this.sortObjects ) {
27267
27268			// get the camera position in the local frame
27269			_matrix$1.copy( this.matrixWorld ).invert();
27270			_vector$5.setFromMatrixPosition( camera.matrixWorld ).applyMatrix4( _matrix$1 );
27271			_forward$1.set( 0, 0, -1 ).transformDirection( camera.matrixWorld ).transformDirection( _matrix$1 );
27272
27273			for ( let i = 0, l = instanceInfo.length; i < l; i ++ ) {
27274
27275				if ( instanceInfo[ i ].visible && instanceInfo[ i ].active ) {
27276
27277					const geometryId = instanceInfo[ i ].geometryIndex;
27278
27279					// get the bounds in world space
27280					this.getMatrixAt( i, _matrix$1 );
27281					this.getBoundingSphereAt( geometryId, _sphere$2 ).applyMatrix4( _matrix$1 );
27282
27283					// determine whether the batched geometry is within the frustum
27284					let culled = false;
27285					if ( perObjectFrustumCulled ) {
27286
27287						culled = ! frustum.intersectsSphere( _sphere$2, camera );
27288
27289					}
27290
27291					if ( ! culled ) {
27292
27293						// get the distance from camera used for sorting
27294						const geometryInfo = geometryInfoList[ geometryId ];
27295						const z = _temp.subVectors( _sphere$2.center, _vector$5 ).dot( _forward$1 );
27296						_renderList.push( geometryInfo.start, geometryInfo.count, z, i );
27297
27298					}
27299
27300				}
27301
27302			}
27303
27304			// Sort the draw ranges and prep for rendering
27305			const list = _renderList.list;
27306			const customSort = this.customSort;
27307			if ( customSort === null ) {
27308
27309				list.sort( material.transparent ? sortTransparent : sortOpaque );
27310
27311			} else {
27312
27313				customSort.call( this, list, camera );
27314
27315			}
27316
27317			for ( let i = 0, l = list.length; i < l; i ++ ) {
27318
27319				const item = list[ i ];
27320				multiDrawStarts[ multiDrawCount ] = item.start * bytesPerElement * multiDrawMultiplier;
27321				multiDrawCounts[ multiDrawCount ] = item.count * multiDrawMultiplier;
27322				indirectArray[ multiDrawCount ] = item.index;
27323				multiDrawCount ++;
27324
27325			}
27326
27327			_renderList.reset();
27328
27329		} else {
27330
27331			for ( let i = 0, l = instanceInfo.length; i < l; i ++ ) {
27332
27333				if ( instanceInfo[ i ].visible && instanceInfo[ i ].active ) {
27334
27335					const geometryId = instanceInfo[ i ].geometryIndex;
27336
27337					// determine whether the batched geometry is within the frustum
27338					let culled = false;
27339					if ( perObjectFrustumCulled ) {
27340
27341						// get the bounds in world space
27342						this.getMatrixAt( i, _matrix$1 );
27343						this.getBoundingSphereAt( geometryId, _sphere$2 ).applyMatrix4( _matrix$1 );
27344						culled = ! frustum.intersectsSphere( _sphere$2, camera );
27345
27346					}
27347
27348					if ( ! culled ) {
27349
27350						const geometryInfo = geometryInfoList[ geometryId ];
27351						multiDrawStarts[ multiDrawCount ] = geometryInfo.start * bytesPerElement * multiDrawMultiplier;
27352						multiDrawCounts[ multiDrawCount ] = geometryInfo.count * multiDrawMultiplier;
27353						indirectArray[ multiDrawCount ] = i;
27354						multiDrawCount ++;
27355
27356					}
27357
27358				}
27359
27360			}
27361
27362		}
27363
27364		indirectTexture.needsUpdate = true;
27365		this._multiDrawCount = multiDrawCount;
27366		this._visibilityChanged = false;
27367
27368	}
27369
27370	onBeforeShadow( renderer, object, camera, shadowCamera, geometry, depthMaterial/* , group */ ) {
27371
27372		this.onBeforeRender( renderer, null, shadowCamera, geometry, depthMaterial );
27373
27374	}
27375
27376}
27377
27378/**
27379 * A material for rendering line primitives.
27380 *
27381 * Materials define the appearance of renderable 3D objects.
27382 *
27383 * ```js
27384 * const material = new THREE.LineBasicMaterial( { color: 0xffffff } );
27385 * ```
27386 *
27387 * @augments Material
27388 */
27389class LineBasicMaterial extends Material {
27390
27391	/**
27392	 * Constructs a new line basic material.
27393	 *
27394	 * @param {Object} [parameters] - An object with one or more properties
27395	 * defining the material's appearance. Any property of the material
27396	 * (including any property from inherited materials) can be passed
27397	 * in here. Color values can be passed any type of value accepted
27398	 * by {@link Color#set}.
27399	 */
27400	constructor( parameters ) {
27401
27402		super();
27403
27404		/**
27405		 * This flag can be used for type testing.
27406		 *
27407		 * @type {boolean}
27408		 * @readonly
27409		 * @default true
27410		 */
27411		this.isLineBasicMaterial = true;
27412
27413		this.type = 'LineBasicMaterial';
27414
27415		/**
27416		 * Color of the material.
27417		 *
27418		 * @type {Color}
27419		 * @default (1,1,1)
27420		 */
27421		this.color = new Color( 0xffffff );
27422
27423		/**
27424		 * Sets the color of the lines using data from a texture. The texture map
27425		 * color is modulated by the diffuse `color`.
27426		 *
27427		 * @type {?Texture}
27428		 * @default null
27429		 */
27430		this.map = null;
27431
27432		/**
27433		 * Controls line thickness or lines.
27434		 *
27435		 * Can only be used with {@link SVGRenderer}. WebGL and WebGPU
27436		 * ignore this setting and always render line primitives with a
27437		 * width of one pixel.
27438		 *
27439		 * @type {number}
27440		 * @default 1
27441		 */
27442		this.linewidth = 1;
27443
27444		/**
27445		 * Defines appearance of line ends.
27446		 *
27447		 * Can only be used with {@link SVGRenderer}.
27448		 *
27449		 * @type {('butt'|'round'|'square')}
27450		 * @default 'round'
27451		 */
27452		this.linecap = 'round';
27453
27454		/**
27455		 * Defines appearance of line joints.
27456		 *
27457		 * Can only be used with {@link SVGRenderer}.
27458		 *
27459		 * @type {('round'|'bevel'|'miter')}
27460		 * @default 'round'
27461		 */
27462		this.linejoin = 'round';
27463
27464		/**
27465		 * Whether the material is affected by fog or not.
27466		 *
27467		 * @type {boolean}
27468		 * @default true
27469		 */
27470		this.fog = true;
27471
27472		this.setValues( parameters );
27473
27474	}
27475
27476	copy( source ) {
27477
27478		super.copy( source );
27479
27480		this.color.copy( source.color );
27481
27482		this.map = source.map;
27483
27484		this.linewidth = source.linewidth;
27485		this.linecap = source.linecap;
27486		this.linejoin = source.linejoin;
27487
27488		this.fog = source.fog;
27489
27490		return this;
27491
27492	}
27493
27494}
27495
27496const _vStart = /*@__PURE__*/ new Vector3();
27497const _vEnd = /*@__PURE__*/ new Vector3();
27498
27499const _inverseMatrix$1 = /*@__PURE__*/ new Matrix4();
27500const _ray$1 = /*@__PURE__*/ new Ray();
27501const _sphere$1 = /*@__PURE__*/ new Sphere();
27502
27503const _intersectPointOnRay = /*@__PURE__*/ new Vector3();
27504const _intersectPointOnSegment = /*@__PURE__*/ new Vector3();
27505
27506/**
27507 * A continuous line. The line are rendered by connecting consecutive
27508 * vertices with straight lines.
27509 *
27510 * ```js
27511 * const material = new THREE.LineBasicMaterial( { color: 0x0000ff } );
27512 *
27513 * const points = [];
27514 * points.push( new THREE.Vector3( - 10, 0, 0 ) );
27515 * points.push( new THREE.Vector3( 0, 10, 0 ) );
27516 * points.push( new THREE.Vector3( 10, 0, 0 ) );
27517 *
27518 * const geometry = new THREE.BufferGeometry().setFromPoints( points );
27519 *
27520 * const line = new THREE.Line( geometry, material );
27521 * scene.add( line );
27522 * ```
27523 *
27524 * @augments Object3D
27525 */
27526class Line extends Object3D {
27527
27528	/**
27529	 * Constructs a new line.
27530	 *
27531	 * @param {BufferGeometry} [geometry] - The line geometry.
27532	 * @param {Material|Array<Material>} [material] - The line material.
27533	 */
27534	constructor( geometry = new BufferGeometry(), material = new LineBasicMaterial() ) {
27535
27536		super();
27537
27538		/**
27539		 * This flag can be used for type testing.
27540		 *
27541		 * @type {boolean}
27542		 * @readonly
27543		 * @default true
27544		 */
27545		this.isLine = true;
27546
27547		this.type = 'Line';
27548
27549		/**
27550		 * The line geometry.
27551		 *
27552		 * @type {BufferGeometry}
27553		 */
27554		this.geometry = geometry;
27555
27556		/**
27557		 * The line material.
27558		 *
27559		 * @type {Material|Array<Material>}
27560		 * @default LineBasicMaterial
27561		 */
27562		this.material = material;
27563
27564		/**
27565		 * A dictionary representing the morph targets in the geometry. The key is the
27566		 * morph targets name, the value its attribute index. This member is `undefined`
27567		 * by default and only set when morph targets are detected in the geometry.
27568		 *
27569		 * @type {Object<string,number>|undefined}
27570		 * @default undefined
27571		 */
27572		this.morphTargetDictionary = undefined;
27573
27574		/**
27575		 * An array of weights typically in the range `[0,1]` that specify how much of the morph
27576		 * is applied. This member is `undefined` by default and only set when morph targets are
27577		 * detected in the geometry.
27578		 *
27579		 * @type {Array<number>|undefined}
27580		 * @default undefined
27581		 */
27582		this.morphTargetInfluences = undefined;
27583
27584		this.updateMorphTargets();
27585
27586	}
27587
27588	copy( source, recursive ) {
27589
27590		super.copy( source, recursive );
27591
27592		this.material = Array.isArray( source.material ) ? source.material.slice() : source.material;
27593		this.geometry = source.geometry;
27594
27595		return this;
27596
27597	}
27598
vendor: 8,195 bytes, lines 27599-27941
27599	/**
27600	 * Computes an array of distance values which are necessary for rendering dashed lines.
27601	 * For each vertex in the geometry, the method calculates the cumulative length from the
27602	 * current point to the very beginning of the line.
27603	 *
27604	 * @return {Line} A reference to this line.
27605	 */
27606	computeLineDistances() {
27607
27608		const geometry = this.geometry;
27609
27610		// we assume non-indexed geometry
27611
27612		if ( geometry.index === null ) {
27613
27614			const positionAttribute = geometry.attributes.position;
27615			const lineDistances = [ 0 ];
27616
27617			for ( let i = 1, l = positionAttribute.count; i < l; i ++ ) {
27618
27619				_vStart.fromBufferAttribute( positionAttribute, i - 1 );
27620				_vEnd.fromBufferAttribute( positionAttribute, i );
27621
27622				lineDistances[ i ] = lineDistances[ i - 1 ];
27623				lineDistances[ i ] += _vStart.distanceTo( _vEnd );
27624
27625			}
27626
27627			geometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );
27628
27629		} else {
27630
27631			warn( 'Line.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );
27632
27633		}
27634
27635		return this;
27636
27637	}
27638
27639	/**
27640	 * Computes intersection points between a casted ray and this line.
27641	 *
27642	 * @param {Raycaster} raycaster - The raycaster.
27643	 * @param {Array<Object>} intersects - The target array that holds the intersection points.
27644	 */
27645	raycast( raycaster, intersects ) {
27646
27647		const geometry = this.geometry;
27648		const matrixWorld = this.matrixWorld;
27649		const threshold = raycaster.params.Line.threshold;
27650		const drawRange = geometry.drawRange;
27651
27652		// Checking boundingSphere distance to ray
27653
27654		if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
27655
27656		_sphere$1.copy( geometry.boundingSphere );
27657		_sphere$1.applyMatrix4( matrixWorld );
27658		_sphere$1.radius += threshold;
27659
27660		if ( raycaster.ray.intersectsSphere( _sphere$1 ) === false ) return;
27661
27662		//
27663
27664		_inverseMatrix$1.copy( matrixWorld ).invert();
27665		_ray$1.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$1 );
27666
27667		const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
27668		const localThresholdSq = localThreshold * localThreshold;
27669
27670		const step = this.isLineSegments ? 2 : 1;
27671
27672		const index = geometry.index;
27673		const attributes = geometry.attributes;
27674		const positionAttribute = attributes.position;
27675
27676		if ( index !== null ) {
27677
27678			const start = Math.max( 0, drawRange.start );
27679			const end = Math.min( index.count, ( drawRange.start + drawRange.count ) );
27680
27681			for ( let i = start, l = end - 1; i < l; i += step ) {
27682
27683				const a = index.getX( i );
27684				const b = index.getX( i + 1 );
27685
27686				const intersect = checkIntersection( this, raycaster, _ray$1, localThresholdSq, a, b, i );
27687
27688				if ( intersect ) {
27689
27690					intersects.push( intersect );
27691
27692				}
27693
27694			}
27695
27696			if ( this.isLineLoop ) {
27697
27698				const a = index.getX( end - 1 );
27699				const b = index.getX( start );
27700
27701				const intersect = checkIntersection( this, raycaster, _ray$1, localThresholdSq, a, b, end - 1 );
27702
27703				if ( intersect ) {
27704
27705					intersects.push( intersect );
27706
27707				}
27708
27709			}
27710
27711		} else {
27712
27713			const start = Math.max( 0, drawRange.start );
27714			const end = Math.min( positionAttribute.count, ( drawRange.start + drawRange.count ) );
27715
27716			for ( let i = start, l = end - 1; i < l; i += step ) {
27717
27718				const intersect = checkIntersection( this, raycaster, _ray$1, localThresholdSq, i, i + 1, i );
27719
27720				if ( intersect ) {
27721
27722					intersects.push( intersect );
27723
27724				}
27725
27726			}
27727
27728			if ( this.isLineLoop ) {
27729
27730				const intersect = checkIntersection( this, raycaster, _ray$1, localThresholdSq, end - 1, start, end - 1 );
27731
27732				if ( intersect ) {
27733
27734					intersects.push( intersect );
27735
27736				}
27737
27738			}
27739
27740		}
27741
27742	}
27743
27744	/**
27745	 * Sets the values of {@link Line#morphTargetDictionary} and {@link Line#morphTargetInfluences}
27746	 * to make sure existing morph targets can influence this 3D object.
27747	 */
27748	updateMorphTargets() {
27749
27750		const geometry = this.geometry;
27751
27752		const morphAttributes = geometry.morphAttributes;
27753		const keys = Object.keys( morphAttributes );
27754
27755		if ( keys.length > 0 ) {
27756
27757			const morphAttribute = morphAttributes[ keys[ 0 ] ];
27758
27759			if ( morphAttribute !== undefined ) {
27760
27761				this.morphTargetInfluences = [];
27762				this.morphTargetDictionary = {};
27763
27764				for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
27765
27766					const name = morphAttribute[ m ].name || String( m );
27767
27768					this.morphTargetInfluences.push( 0 );
27769					this.morphTargetDictionary[ name ] = m;
27770
27771				}
27772
27773			}
27774
27775		}
27776
27777	}
27778
27779}
27780
27781function checkIntersection( object, raycaster, ray, thresholdSq, a, b, i ) {
27782
27783	const positionAttribute = object.geometry.attributes.position;
27784
27785	_vStart.fromBufferAttribute( positionAttribute, a );
27786	_vEnd.fromBufferAttribute( positionAttribute, b );
27787
27788	const distSq = ray.distanceSqToSegment( _vStart, _vEnd, _intersectPointOnRay, _intersectPointOnSegment );
27789
27790	if ( distSq > thresholdSq ) return;
27791
27792	_intersectPointOnRay.applyMatrix4( object.matrixWorld ); // Move back to world space for distance calculation
27793
27794	const distance = raycaster.ray.origin.distanceTo( _intersectPointOnRay );
27795
27796	if ( distance < raycaster.near || distance > raycaster.far ) return;
27797
27798	return {
27799
27800		distance: distance,
27801		// What do we want? intersection point on the ray or on the segment??
27802		// point: raycaster.ray.at( distance ),
27803		point: _intersectPointOnSegment.clone().applyMatrix4( object.matrixWorld ),
27804		index: i,
27805		face: null,
27806		faceIndex: null,
27807		barycoord: null,
27808		object: object
27809
27810	};
27811
27812}
27813
27814const _start = /*@__PURE__*/ new Vector3();
27815const _end = /*@__PURE__*/ new Vector3();
27816
27817/**
27818 * A series of lines drawn between pairs of vertices.
27819 *
27820 * @augments Line
27821 */
27822class LineSegments extends Line {
27823
27824	/**
27825	 * Constructs a new line segments.
27826	 *
27827	 * @param {BufferGeometry} [geometry] - The line geometry.
27828	 * @param {Material|Array<Material>} [material] - The line material.
27829	 */
27830	constructor( geometry, material ) {
27831
27832		super( geometry, material );
27833
27834		/**
27835		 * This flag can be used for type testing.
27836		 *
27837		 * @type {boolean}
27838		 * @readonly
27839		 * @default true
27840		 */
27841		this.isLineSegments = true;
27842
27843		this.type = 'LineSegments';
27844
27845	}
27846
27847	computeLineDistances() {
27848
27849		const geometry = this.geometry;
27850
27851		// we assume non-indexed geometry
27852
27853		if ( geometry.index === null ) {
27854
27855			const positionAttribute = geometry.attributes.position;
27856			const lineDistances = [];
27857
27858			for ( let i = 0, l = positionAttribute.count; i < l; i += 2 ) {
27859
27860				_start.fromBufferAttribute( positionAttribute, i );
27861				_end.fromBufferAttribute( positionAttribute, i + 1 );
27862
27863				lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ];
27864				lineDistances[ i + 1 ] = lineDistances[ i ] + _start.distanceTo( _end );
27865
27866			}
27867
27868			geometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );
27869
27870		} else {
27871
27872			warn( 'LineSegments.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );
27873
27874		}
27875
27876		return this;
27877
27878	}
27879
27880}
27881
27882/**
27883 * A continuous line. This is nearly the same as {@link Line} the only difference
27884 * is that the last vertex is connected with the first vertex in order to close
27885 * the line to form a loop.
27886 *
27887 * @augments Line
27888 */
27889class LineLoop extends Line {
27890
27891	/**
27892	 * Constructs a new line loop.
27893	 *
27894	 * @param {BufferGeometry} [geometry] - The line geometry.
27895	 * @param {Material|Array<Material>} [material] - The line material.
27896	 */
27897	constructor( geometry, material ) {
27898
27899		super( geometry, material );
27900
27901		/**
27902		 * This flag can be used for type testing.
27903		 *
27904		 * @type {boolean}
27905		 * @readonly
27906		 * @default true
27907		 */
27908		this.isLineLoop = true;
27909
27910		this.type = 'LineLoop';
27911
27912	}
27913
27914}
27915
27916/**
27917 * A material for rendering point primitives.
27918 *
27919 * Materials define the appearance of renderable 3D objects.
27920 *
27921 * ```js
27922 * const vertices = [];
27923 *
27924 * for ( let i = 0; i < 10000; i ++ ) {
27925 * 	const x = THREE.MathUtils.randFloatSpread( 2000 );
27926 * 	const y = THREE.MathUtils.randFloatSpread( 2000 );
27927 * 	const z = THREE.MathUtils.randFloatSpread( 2000 );
27928 *
27929 * 	vertices.push( x, y, z );
27930 * }
27931 *
27932 * const geometry = new THREE.BufferGeometry();
27933 * geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) );
27934 * const material = new THREE.PointsMaterial( { color: 0x888888 } );
27935 * const points = new THREE.Points( geometry, material );
27936 * scene.add( points );
27937 * ```
27938 *
27939 * @augments Material
27940 */
27941class PointsMaterial extends Material
vendor: 8,535 bytes, lines 27941-28287
27941 {
27942
27943	/**
27944	 * Constructs a new points material.
27945	 *
27946	 * @param {Object} [parameters] - An object with one or more properties
27947	 * defining the material's appearance. Any property of the material
27948	 * (including any property from inherited materials) can be passed
27949	 * in here. Color values can be passed any type of value accepted
27950	 * by {@link Color#set}.
27951	 */
27952	constructor( parameters ) {
27953
27954		super();
27955
27956		/**
27957		 * This flag can be used for type testing.
27958		 *
27959		 * @type {boolean}
27960		 * @readonly
27961		 * @default true
27962		 */
27963		this.isPointsMaterial = true;
27964
27965		this.type = 'PointsMaterial';
27966
27967		/**
27968		 * Color of the material.
27969		 *
27970		 * @type {Color}
27971		 * @default (1,1,1)
27972		 */
27973		this.color = new Color( 0xffffff );
27974
27975		/**
27976		 * The color map. May optionally include an alpha channel, typically combined
27977		 * with {@link Material#transparent} or {@link Material#alphaTest}. The texture map
27978		 * color is modulated by the diffuse `color`.
27979		 *
27980		 * @type {?Texture}
27981		 * @default null
27982		 */
27983		this.map = null;
27984
27985		/**
27986		 * The alpha map is a grayscale texture that controls the opacity across the
27987		 * surface (black: fully transparent; white: fully opaque).
27988		 *
27989		 * Only the color of the texture is used, ignoring the alpha channel if one
27990		 * exists. For RGB and RGBA textures, the renderer will use the green channel
27991		 * when sampling this texture due to the extra bit of precision provided for
27992		 * green in DXT-compressed and uncompressed RGB 565 formats. Luminance-only and
27993		 * luminance/alpha textures will also still work as expected.
27994		 *
27995		 * @type {?Texture}
27996		 * @default null
27997		 */
27998		this.alphaMap = null;
27999
28000		/**
28001		 * Defines the size of the points in pixels.
28002		 *
28003		 * 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).
28004		 *
28005		 * @type {number}
28006		 * @default 1
28007		 */
28008		this.size = 1;
28009
28010		/**
28011		 * Specifies whether size of individual points is attenuated by the camera depth (perspective camera only).
28012		 *
28013		 * @type {boolean}
28014		 * @default true
28015		 */
28016		this.sizeAttenuation = true;
28017
28018		/**
28019		 * Whether the material is affected by fog or not.
28020		 *
28021		 * @type {boolean}
28022		 * @default true
28023		 */
28024		this.fog = true;
28025
28026		this.setValues( parameters );
28027
28028	}
28029
28030	copy( source ) {
28031
28032		super.copy( source );
28033
28034		this.color.copy( source.color );
28035
28036		this.map = source.map;
28037
28038		this.alphaMap = source.alphaMap;
28039
28040		this.size = source.size;
28041		this.sizeAttenuation = source.sizeAttenuation;
28042
28043		this.fog = source.fog;
28044
28045		return this;
28046
28047	}
28048
28049}
28050
28051const _inverseMatrix = /*@__PURE__*/ new Matrix4();
28052const _ray = /*@__PURE__*/ new Ray();
28053const _sphere = /*@__PURE__*/ new Sphere();
28054const _position$3 = /*@__PURE__*/ new Vector3();
28055
28056/**
28057 * A class for displaying points or point clouds.
28058 *
28059 * @augments Object3D
28060 */
28061class Points extends Object3D {
28062
28063	/**
28064	 * Constructs a new point cloud.
28065	 *
28066	 * @param {BufferGeometry} [geometry] - The points geometry.
28067	 * @param {Material|Array<Material>} [material] - The points material.
28068	 */
28069	constructor( geometry = new BufferGeometry(), material = new PointsMaterial() ) {
28070
28071		super();
28072
28073		/**
28074		 * This flag can be used for type testing.
28075		 *
28076		 * @type {boolean}
28077		 * @readonly
28078		 * @default true
28079		 */
28080		this.isPoints = true;
28081
28082		this.type = 'Points';
28083
28084		/**
28085		 * The points geometry.
28086		 *
28087		 * @type {BufferGeometry}
28088		 */
28089		this.geometry = geometry;
28090
28091		/**
28092		 * The line material.
28093		 *
28094		 * @type {Material|Array<Material>}
28095		 * @default PointsMaterial
28096		 */
28097		this.material = material;
28098
28099		/**
28100		 * A dictionary representing the morph targets in the geometry. The key is the
28101		 * morph targets name, the value its attribute index. This member is `undefined`
28102		 * by default and only set when morph targets are detected in the geometry.
28103		 *
28104		 * @type {Object<string,number>|undefined}
28105		 * @default undefined
28106		 */
28107		this.morphTargetDictionary = undefined;
28108
28109		/**
28110		 * An array of weights typically in the range `[0,1]` that specify how much of the morph
28111		 * is applied. This member is `undefined` by default and only set when morph targets are
28112		 * detected in the geometry.
28113		 *
28114		 * @type {Array<number>|undefined}
28115		 * @default undefined
28116		 */
28117		this.morphTargetInfluences = undefined;
28118
28119		this.updateMorphTargets();
28120
28121	}
28122
28123	copy( source, recursive ) {
28124
28125		super.copy( source, recursive );
28126
28127		this.material = Array.isArray( source.material ) ? source.material.slice() : source.material;
28128		this.geometry = source.geometry;
28129
28130		return this;
28131
28132	}
28133
28134	/**
28135	 * Computes intersection points between a casted ray and this point cloud.
28136	 *
28137	 * @param {Raycaster} raycaster - The raycaster.
28138	 * @param {Array<Object>} intersects - The target array that holds the intersection points.
28139	 */
28140	raycast( raycaster, intersects ) {
28141
28142		const geometry = this.geometry;
28143		const matrixWorld = this.matrixWorld;
28144		const threshold = raycaster.params.Points.threshold;
28145		const drawRange = geometry.drawRange;
28146
28147		// Checking boundingSphere distance to ray
28148
28149		if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
28150
28151		_sphere.copy( geometry.boundingSphere );
28152		_sphere.applyMatrix4( matrixWorld );
28153		_sphere.radius += threshold;
28154
28155		if ( raycaster.ray.intersectsSphere( _sphere ) === false ) return;
28156
28157		//
28158
28159		_inverseMatrix.copy( matrixWorld ).invert();
28160		_ray.copy( raycaster.ray ).applyMatrix4( _inverseMatrix );
28161
28162		const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
28163		const localThresholdSq = localThreshold * localThreshold;
28164
28165		const index = geometry.index;
28166		const attributes = geometry.attributes;
28167		const positionAttribute = attributes.position;
28168
28169		if ( index !== null ) {
28170
28171			const start = Math.max( 0, drawRange.start );
28172			const end = Math.min( index.count, ( drawRange.start + drawRange.count ) );
28173
28174			for ( let i = start, il = end; i < il; i ++ ) {
28175
28176				const a = index.getX( i );
28177
28178				_position$3.fromBufferAttribute( positionAttribute, a );
28179
28180				testPoint( _position$3, a, localThresholdSq, matrixWorld, raycaster, intersects, this );
28181
28182			}
28183
28184		} else {
28185
28186			const start = Math.max( 0, drawRange.start );
28187			const end = Math.min( positionAttribute.count, ( drawRange.start + drawRange.count ) );
28188
28189			for ( let i = start, l = end; i < l; i ++ ) {
28190
28191				_position$3.fromBufferAttribute( positionAttribute, i );
28192
28193				testPoint( _position$3, i, localThresholdSq, matrixWorld, raycaster, intersects, this );
28194
28195			}
28196
28197		}
28198
28199	}
28200
28201	/**
28202	 * Sets the values of {@link Points#morphTargetDictionary} and {@link Points#morphTargetInfluences}
28203	 * to make sure existing morph targets can influence this 3D object.
28204	 */
28205	updateMorphTargets() {
28206
28207		const geometry = this.geometry;
28208
28209		const morphAttributes = geometry.morphAttributes;
28210		const keys = Object.keys( morphAttributes );
28211
28212		if ( keys.length > 0 ) {
28213
28214			const morphAttribute = morphAttributes[ keys[ 0 ] ];
28215
28216			if ( morphAttribute !== undefined ) {
28217
28218				this.morphTargetInfluences = [];
28219				this.morphTargetDictionary = {};
28220
28221				for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
28222
28223					const name = morphAttribute[ m ].name || String( m );
28224
28225					this.morphTargetInfluences.push( 0 );
28226					this.morphTargetDictionary[ name ] = m;
28227
28228				}
28229
28230			}
28231
28232		}
28233
28234	}
28235
28236}
28237
28238function testPoint( point, index, localThresholdSq, matrixWorld, raycaster, intersects, object ) {
28239
28240	const rayPointDistanceSq = _ray.distanceSqToPoint( point );
28241
28242	if ( rayPointDistanceSq < localThresholdSq ) {
28243
28244		const intersectPoint = new Vector3();
28245
28246		_ray.closestPointToPoint( point, intersectPoint );
28247		intersectPoint.applyMatrix4( matrixWorld );
28248
28249		const distance = raycaster.ray.origin.distanceTo( intersectPoint );
28250
28251		if ( distance < raycaster.near || distance > raycaster.far ) return;
28252
28253		intersects.push( {
28254
28255			distance: distance,
28256			distanceToRay: Math.sqrt( rayPointDistanceSq ),
28257			point: intersectPoint,
28258			index: index,
28259			face: null,
28260			faceIndex: null,
28261			barycoord: null,
28262			object: object
28263
28264		} );
28265
28266	}
28267
28268}
28269
28270/**
28271 * A texture for use with a video.
28272 *
28273 * ```js
28274 * // assuming you have created a HTML video element with id="video"
28275 * const video = document.getElementById( 'video' );
28276 * const texture = new THREE.VideoTexture( video );
28277 * ```
28278 *
28279 * Note: When using video textures with {@link WebGPURenderer}, {@link Texture#colorSpace} must be
28280 * set to THREE.SRGBColorSpace.
28281 *
28282 * Note: After the initial use of a texture, its dimensions, format, and type
28283 * cannot be changed. Instead, call {@link Texture#dispose} on the texture and instantiate a new one.
28284 *
28285 * @augments Texture
28286 */
28287class VideoTexture extends Texture
vendor: 4,083 bytes, lines 28287-28434
28287 {
28288
28289	/**
28290	 * Constructs a new video texture.
28291	 *
28292	 * @param {HTMLVideoElement} video - The video element to use as a data source for the texture.
28293	 * @param {number} [mapping=Texture.DEFAULT_MAPPING] - The texture mapping.
28294	 * @param {number} [wrapS=ClampToEdgeWrapping] - The wrapS value.
28295	 * @param {number} [wrapT=ClampToEdgeWrapping] - The wrapT value.
28296	 * @param {number} [magFilter=LinearFilter] - The mag filter value.
28297	 * @param {number} [minFilter=LinearFilter] - The min filter value.
28298	 * @param {number} [format=RGBAFormat] - The texture format.
28299	 * @param {number} [type=UnsignedByteType] - The texture type.
28300	 * @param {number} [anisotropy=Texture.DEFAULT_ANISOTROPY] - The anisotropy value.
28301	 */
28302	constructor( video, mapping, wrapS, wrapT, magFilter = LinearFilter, minFilter = LinearFilter, format, type, anisotropy ) {
28303
28304		super( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
28305
28306		/**
28307		 * This flag can be used for type testing.
28308		 *
28309		 * @type {boolean}
28310		 * @readonly
28311		 * @default true
28312		 */
28313		this.isVideoTexture = true;
28314
28315		/**
28316		 * Whether to generate mipmaps (if possible) for a texture.
28317		 *
28318		 * Overwritten and set to `false` by default.
28319		 *
28320		 * @type {boolean}
28321		 * @default false
28322		 */
28323		this.generateMipmaps = false;
28324
28325		/**
28326		 * The video frame request callback identifier, which is a positive integer.
28327		 *
28328		 * Value of 0 represents no scheduled rVFC.
28329		 *
28330		 * @private
28331		 * @type {number}
28332		 */
28333		this._requestVideoFrameCallbackId = 0;
28334
28335		const scope = this;
28336
28337		function updateVideo() {
28338
28339			scope.needsUpdate = true;
28340			scope._requestVideoFrameCallbackId = video.requestVideoFrameCallback( updateVideo );
28341
28342		}
28343
28344		if ( 'requestVideoFrameCallback' in video ) {
28345
28346			this._requestVideoFrameCallbackId = video.requestVideoFrameCallback( updateVideo );
28347
28348		}
28349
28350	}
28351
28352	clone() {
28353
28354		return new this.constructor( this.image ).copy( this );
28355
28356	}
28357
28358	/**
28359	 * This method is called automatically by the renderer and sets {@link Texture#needsUpdate}
28360	 * to `true` every time a new frame is available.
28361	 *
28362	 * Only relevant if `requestVideoFrameCallback` is not supported in the browser.
28363	 */
28364	update() {
28365
28366		const video = this.image;
28367		const hasVideoFrameCallback = 'requestVideoFrameCallback' in video;
28368
28369		if ( hasVideoFrameCallback === false && video.readyState >= video.HAVE_CURRENT_DATA ) {
28370
28371			this.needsUpdate = true;
28372
28373		}
28374
28375	}
28376
28377	dispose() {
28378
28379		if ( this._requestVideoFrameCallbackId !== 0 ) {
28380
28381			this.source.data.cancelVideoFrameCallback( this._requestVideoFrameCallbackId );
28382
28383			this._requestVideoFrameCallbackId = 0;
28384
28385		}
28386
28387		super.dispose();
28388
28389	}
28390
28391}
28392
28393/**
28394 * This class can be used as an alternative way to define video data. Instead of using
28395 * an instance of `HTMLVideoElement` like with `VideoTexture`, `VideoFrameTexture` expects each frame is
28396 * defined manually via {@link VideoFrameTexture#setFrame}. A typical use case for this module is when
28397 * video frames are decoded with the WebCodecs API.
28398 *
28399 * ```js
28400 * const texture = new THREE.VideoFrameTexture();
28401 * texture.setFrame( frame );
28402 * ```
28403 *
28404 * @augments VideoTexture
28405 */
28406class VideoFrameTexture extends VideoTexture {
28407
28408	/**
28409	 * Constructs a new video frame texture.
28410	 *
28411	 * @param {number} [mapping=Texture.DEFAULT_MAPPING] - The texture mapping.
28412	 * @param {number} [wrapS=ClampToEdgeWrapping] - The wrapS value.
28413	 * @param {number} [wrapT=ClampToEdgeWrapping] - The wrapT value.
28414	 * @param {number} [magFilter=LinearFilter] - The mag filter value.
28415	 * @param {number} [minFilter=LinearFilter] - The min filter value.
28416	 * @param {number} [format=RGBAFormat] - The texture format.
28417	 * @param {number} [type=UnsignedByteType] - The texture type.
28418	 * @param {number} [anisotropy=Texture.DEFAULT_ANISOTROPY] - The anisotropy value.
28419	 */
28420	constructor( mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
28421
28422		super( {}, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
28423
28424		/**
28425		 * This flag can be used for type testing.
28426		 *
28427		 * @type {boolean}
28428		 * @readonly
28429		 * @default true
28430		 */
28431		this.isVideoFrameTexture = true;
28432
28433	}
28434
28435	/**
28436	 * This method overwritten with an empty implementation since
28437	 * this type of texture is updated via `setFrame()`.
28438	 */
28439	update() {}
28440
28441	clone() {
28442
28443		return new this.constructor().copy( this ); // restoring Texture.clone()
28444
28445	}
28446
28447	/**
28448	 * Sets the current frame of the video. This will automatically update the texture
28449	 * so the data can be used for rendering.
28450	 *
28451	 * @param {VideoFrame} frame - The video frame.
28452	 */
28453	setFrame( frame ) {
28454
28455		this.image = frame;
28456		this.needsUpdate = true;
28457
28458	}
28459
28460}
28461
28462/**
28463 * This class can only be used in combination with `copyFramebufferToTexture()` methods
28464 * of renderers. It extracts the contents of the current bound framebuffer and provides it
28465 * as a texture for further usage.
28466 *
28467 * ```js
28468 * const pixelRatio = window.devicePixelRatio;
28469 * const textureSize = 128 * pixelRatio;
28470 *
28471 * const frameTexture = new FramebufferTexture( textureSize, textureSize );
28472 *
28473 * // calculate start position for copying part of the frame data
28474 * const vector = new Vector2();
28475 * vector.x = ( window.innerWidth * pixelRatio / 2 ) - ( textureSize / 2 );
28476 * vector.y = ( window.innerHeight * pixelRatio / 2 ) - ( textureSize / 2 );
28477 *
28478 * renderer.render( scene, camera );
28479 *
28480 * // copy part of the rendered frame into the framebuffer texture
28481 * renderer.copyFramebufferToTexture( frameTexture, vector );
28482 * ```
28483 *
28484 * @augments Texture
28485 */
28486class FramebufferTexture extends Texture {
28487
28488	/**
28489	 * Constructs a new framebuffer texture.
28490	 *
28491	 * @param {number} [width] - The width of the texture.
28492	 * @param {number} [height] - The height of the texture.
28493	 */
28494	constructor( width, height ) {
28495
28496		super( { width, height } );
28497
28498		/**
28499		 * This flag can be used for type testing.
28500		 *
28501		 * @type {boolean}
28502		 * @readonly
28503		 * @default true
28504		 */
28505		this.isFramebufferTexture = true;
28506
28507		/**
28508		 * How the texture is sampled when a texel covers more than one pixel.
28509		 *
28510		 * Overwritten and set to `NearestFilter` by default to disable filtering.
28511		 *
28512		 * @type {(NearestFilter|NearestMipmapNearestFilter|NearestMipmapLinearFilter|LinearFilter|LinearMipmapNearestFilter|LinearMipmapLinearFilter)}
28513		 * @default NearestFilter
28514		 */
28515		this.magFilter = NearestFilter;
28516
28517		/**
28518		 * How the texture is sampled when a texel covers less than one pixel.
28519		 *
28520		 * Overwritten and set to `NearestFilter` by default to disable filtering.
28521		 *
28522		 * @type {(NearestFilter|NearestMipmapNearestFilter|NearestMipmapLinearFilter|LinearFilter|LinearMipmapNearestFilter|LinearMipmapLinearFilter)}
28523		 * @default NearestFilter
28524		 */
28525		this.minFilter = NearestFilter;
28526
28527		/**
28528		 * Whether to generate mipmaps (if possible) for a texture.
28529		 *
28530		 * Overwritten and set to `false` by default.
28531		 *
28532		 * @type {boolean}
28533		 * @default false
28534		 */
28535		this.generateMipmaps = false;
28536
28537		this.needsUpdate = true;
28538
28539	}
28540
28541}
28542
28543/**
28544 * Creates a texture based on data in compressed form.
28545 *
28546 * These texture are usually loaded with {@link CompressedTextureLoader}.
28547 *
28548 * @augments Texture
28549 */
28550class CompressedTexture extends Texture {
28551
28552	/**
28553	 * Constructs a new compressed texture.
28554	 *
28555	 * @param {Array<Object>} mipmaps - This array holds for all mipmaps (including the bases mip)
28556	 * the data and dimensions.
28557	 * @param {number} width - The width of the texture.
28558	 * @param {number} height - The height of the texture.
28559	 * @param {number} [format=RGBAFormat] - The texture format.
28560	 * @param {number} [type=UnsignedByteType] - The texture type.
28561	 * @param {number} [mapping=Texture.DEFAULT_MAPPING] - The texture mapping.
28562	 * @param {number} [wrapS=ClampToEdgeWrapping] - The wrapS value.
28563	 * @param {number} [wrapT=ClampToEdgeWrapping] - The wrapT value.
28564	 * @param {number} [magFilter=LinearFilter] - The mag filter value.
28565	 * @param {number} [minFilter=LinearMipmapLinearFilter] - The min filter value.
28566	 * @param {number} [anisotropy=Texture.DEFAULT_ANISOTROPY] - The anisotropy value.
28567	 * @param {string} [colorSpace=NoColorSpace] - The color space.
28568	 */
28569	constructor( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, colorSpace ) {
28570
28571		super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace );
28572
28573		/**
28574		 * This flag can be used for type testing.
28575		 *
28576		 * @type {boolean}
28577		 * @readonly
28578		 * @default true
28579		 */
28580		this.isCompressedTexture = true;
28581
28582		/**
28583		 * The image property of a compressed texture just defines its dimensions.
28584		 *
28585		 * @type {{width:number,height:number}}
28586		 */
28587		this.image = { width: width, height: height };
28588
28589		/**
28590		 * This array holds for all mipmaps (including the bases mip) the data and dimensions.
28591		 *
28592		 * @type {Array<Object>}
28593		 */
28594		this.mipmaps = mipmaps;
28595
28596		/**
28597		 * If set to `true`, the texture is flipped along the vertical axis when
28598		 * uploaded to the GPU.
28599		 *
28600		 * Overwritten and set to `false` by default since it is not possible to
28601		 * flip compressed textures.
28602		 *
28603		 * @type {boolean}
28604		 * @default false
28605		 * @readonly
28606		 */
28607		this.flipY = false;
28608
28609		/**
28610		 * Whether to generate mipmaps (if possible) for a texture.
28611		 *
28612		 * Overwritten and set to `false` by default since it is not
28613		 * possible to generate mipmaps for compressed data. Mipmaps
28614		 * must be embedded in the compressed texture file.
28615		 *
28616		 * @type {boolean}
28617		 * @default false
28618		 * @readonly
28619		 */
28620		this.generateMipmaps = false;
28621
28622	}
28623
28624}
28625
28626/**
28627 * Creates a texture 2D array based on data in compressed form.
28628 *
28629 * These texture are usually loaded with {@link CompressedTextureLoader}.
28630 *
28631 * @augments CompressedTexture
28632 */
28633class CompressedArrayTexture extends CompressedTexture {
28634
28635	/**
28636	 * Constructs a new compressed array texture.
28637	 *
28638	 * @param {Array<Object>} mipmaps - This array holds for all mipmaps (including the bases mip)
28639	 * the data and dimensions.
28640	 * @param {number} width - The width of the texture.
28641	 * @param {number} height - The height of the texture.
28642	 * @param {number} depth - The depth of the texture.
28643	 * @param {number} [format=RGBAFormat] - The min filter value.
28644	 * @param {number} [type=UnsignedByteType] - The min filter value.
28645	 */
28646	constructor( mipmaps, width, height, depth, format, type ) {
28647
28648		super( mipmaps, width, height, format, type );
28649
28650		/**
28651		 * This flag can be used for type testing.
28652		 *
28653		 * @type {boolean}
28654		 * @readonly
28655		 * @default true
28656		 */
28657		this.isCompressedArrayTexture = true;
28658
28659		/**
28660		 * The image property of a compressed texture just defines its dimensions.
28661		 *
28662		 * @name CompressedArrayTexture#image
28663		 * @type {{width:number,height:number,depth:number}}
28664		 */
28665		this.image.depth = depth;
28666
28667		/**
28668		 * This defines how the texture is wrapped in the depth and corresponds to
28669		 * *W* in UVW mapping.
28670		 *
28671		 * @type {(RepeatWrapping|ClampToEdgeWrapping|MirroredRepeatWrapping)}
28672		 * @default ClampToEdgeWrapping
28673		 */
28674		this.wrapR = ClampToEdgeWrapping;
28675
28676		/**
28677		 * A set of all layers which need to be updated in the texture.
28678		 *
28679		 * @type {Set<number>}
28680		 */
28681		this.layerUpdates = new Set();
28682
28683	}
28684
28685	/**
28686	 * Describes that a specific layer of the texture needs to be updated.
28687	 * Normally when {@link Texture#needsUpdate} is set to `true`, the
28688	 * entire compressed texture array is sent to the GPU. Marking specific
28689	 * layers will only transmit subsets of all mipmaps associated with a
28690	 * specific depth in the array which is often much more performant.
28691	 *
28692	 * @param {number} layerIndex - The layer index that should be updated.
28693	 */
28694	addLayerUpdate( layerIndex ) {
28695
28696		this.layerUpdates.add( layerIndex );
28697
28698	}
28699
28700	/**
28701	 * Resets the layer updates registry.
28702	 */
28703	clearLayerUpdates() {
28704
28705		this.layerUpdates.clear();
28706
28707	}
28708
28709}
28710
28711/**
28712 * Creates a cube texture based on data in compressed form.
28713 *
28714 * These texture are usually loaded with {@link CompressedTextureLoader}.
28715 *
28716 * @augments CompressedTexture
28717 */
28718class CompressedCubeTexture extends CompressedTexture {
28719
28720	/**
28721	 * Constructs a new compressed texture.
28722	 *
28723	 * @param {Array<CompressedTexture>} images - An array of compressed textures.
28724	 * @param {number} [format=RGBAFormat] - The texture format.
28725	 * @param {number} [type=UnsignedByteType] - The texture type.
28726	 */
28727	constructor( images, format, type ) {
28728
28729		super( undefined, images[ 0 ].width, images[ 0 ].height, format, type, CubeReflectionMapping );
28730
28731		/**
28732		 * This flag can be used for type testing.
28733		 *
28734		 * @type {boolean}
28735		 * @readonly
28736		 * @default true
28737		 */
28738		this.isCompressedCubeTexture = true;
28739
28740		/**
28741		 * This flag can be used for type testing.
28742		 *
28743		 * @type {boolean}
28744		 * @readonly
28745		 * @default true
28746		 */
28747		this.isCubeTexture = true;
28748
28749		this.image = images;
28750
28751	}
28752
28753}
28754
28755/**
28756 * Creates a cube texture made up of six images.
28757 *
28758 * ```js
28759 * const loader = new THREE.CubeTextureLoader();
28760 * loader.setPath( 'textures/cube/pisa/' );
28761 *
28762 * const textureCube = loader.load( [
28763 * 	'px.png', 'nx.png', 'py.png', 'ny.png', 'pz.png', 'nz.png'
28764 * ] );
28765 *
28766 * const material = new THREE.MeshBasicMaterial( { color: 0xffffff, envMap: textureCube } );
28767 * ```
28768 *
28769 * @augments Texture
28770 */
28771class CubeTexture extends Texture {
28772
28773	/**
28774	 * Constructs a new cube texture.
28775	 *
28776	 * @param {Array<Image>} [images=[]] - An array holding a image for each side of a cube.
28777	 * @param {number} [mapping=CubeReflectionMapping] - The texture mapping.
28778	 * @param {number} [wrapS=ClampToEdgeWrapping] - The wrapS value.
28779	 * @param {number} [wrapT=ClampToEdgeWrapping] - The wrapT value.
28780	 * @param {number} [magFilter=LinearFilter] - The mag filter value.
28781	 * @param {number} [minFilter=LinearMipmapLinearFilter] - The min filter value.
28782	 * @param {number} [format=RGBAFormat] - The texture format.
28783	 * @param {number} [type=UnsignedByteType] - The texture type.
28784	 * @param {number} [anisotropy=Texture.DEFAULT_ANISOTROPY] - The anisotropy value.
28785	 * @param {string}
vendor: 5,834 bytes, lines 28785-28998
28785 [colorSpace=NoColorSpace] - The color space value.
28786	 */
28787	constructor( images = [], mapping = CubeReflectionMapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ) {
28788
28789		super( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace );
28790
28791		/**
28792		 * This flag can be used for type testing.
28793		 *
28794		 * @type {boolean}
28795		 * @readonly
28796		 * @default true
28797		 */
28798		this.isCubeTexture = true;
28799
28800		/**
28801		 * If set to `true`, the texture is flipped along the vertical axis when
28802		 * uploaded to the GPU.
28803		 *
28804		 * Overwritten and set to `false` by default.
28805		 *
28806		 * @type {boolean}
28807		 * @default false
28808		 */
28809		this.flipY = false;
28810
28811	}
28812
28813	/**
28814	 * Alias for {@link CubeTexture#image}.
28815	 *
28816	 * @type {Array<Image>}
28817	 */
28818	get images() {
28819
28820		return this.image;
28821
28822	}
28823
28824	set images( value ) {
28825
28826		this.image = value;
28827
28828	}
28829
28830}
28831
28832/**
28833 * Creates a texture from a canvas element.
28834 *
28835 * This is almost the same as the base texture class, except that it sets {@link Texture#needsUpdate}
28836 * to `true` immediately since a canvas can directly be used for rendering.
28837 *
28838 * @augments Texture
28839 */
28840class CanvasTexture extends Texture {
28841
28842	/**
28843	 * Constructs a new texture.
28844	 *
28845	 * @param {HTMLCanvasElement} [canvas] - The HTML canvas element.
28846	 * @param {number} [mapping=Texture.DEFAULT_MAPPING] - The texture mapping.
28847	 * @param {number} [wrapS=ClampToEdgeWrapping] - The wrapS value.
28848	 * @param {number} [wrapT=ClampToEdgeWrapping] - The wrapT value.
28849	 * @param {number} [magFilter=LinearFilter] - The mag filter value.
28850	 * @param {number} [minFilter=LinearMipmapLinearFilter] - The min filter value.
28851	 * @param {number} [format=RGBAFormat] - The texture format.
28852	 * @param {number} [type=UnsignedByteType] - The texture type.
28853	 * @param {number} [anisotropy=Texture.DEFAULT_ANISOTROPY] - The anisotropy value.
28854	 */
28855	constructor( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
28856
28857		super( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
28858
28859		/**
28860		 * This flag can be used for type testing.
28861		 *
28862		 * @type {boolean}
28863		 * @readonly
28864		 * @default true
28865		 */
28866		this.isCanvasTexture = true;
28867
28868		this.needsUpdate = true;
28869
28870	}
28871
28872}
28873
28874/**
28875 * Creates a texture from an HTML element.
28876 *
28877 * This is almost the same as the base texture class, except that it sets {@link Texture#needsUpdate}
28878 * to `true` immediately and listens for the parent canvas's paint events to trigger updates.
28879 *
28880 * @augments Texture
28881 */
28882class HTMLTexture extends Texture {
28883
28884	/**
28885	 * Constructs a new texture.
28886	 *
28887	 * @param {HTMLElement} [element] - The HTML element.
28888	 * @param {number} [mapping=Texture.DEFAULT_MAPPING] - The texture mapping.
28889	 * @param {number} [wrapS=ClampToEdgeWrapping] - The wrapS value.
28890	 * @param {number} [wrapT=ClampToEdgeWrapping] - The wrapT value.
28891	 * @param {number} [magFilter=LinearFilter] - The mag filter value.
28892	 * @param {number} [minFilter=LinearMipmapLinearFilter] - The min filter value.
28893	 * @param {number} [format=RGBAFormat] - The texture format.
28894	 * @param {number} [type=UnsignedByteType] - The texture type.
28895	 * @param {number} [anisotropy=Texture.DEFAULT_ANISOTROPY] - The anisotropy value.
28896	 */
28897	constructor( element, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
28898
28899		super( element, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
28900
28901		/**
28902		 * This flag can be used for type testing.
28903		 *
28904		 * @type {boolean}
28905		 * @readonly
28906		 * @default true
28907		 */
28908		this.isHTMLTexture = true;
28909		this.generateMipmaps = false;
28910
28911		this.needsUpdate = true;
28912
28913		const parent = element ? element.parentNode : null;
28914
28915		if ( parent !== null && 'requestPaint' in parent ) {
28916
28917			parent.onpaint = () => {
28918
28919				this.needsUpdate = true;
28920
28921			};
28922
28923			parent.requestPaint();
28924
28925		}
28926
28927	}
28928
28929	dispose() {
28930
28931		const parent = this.image ? this.image.parentNode : null;
28932
28933		if ( parent !== null && 'onpaint' in parent ) {
28934
28935			parent.onpaint = null;
28936
28937		}
28938
28939		super.dispose();
28940
28941	}
28942
28943}
28944
28945/**
28946 * This class can be used to automatically save the depth information of a
28947 * rendering into a texture.
28948 *
28949 * @augments Texture
28950 */
28951class DepthTexture extends Texture {
28952
28953	/**
28954	 * Constructs a new depth texture.
28955	 *
28956	 * @param {number} width - The width of the texture.
28957	 * @param {number} height - The height of the texture.
28958	 * @param {number} [type=UnsignedIntType] - The texture type.
28959	 * @param {number} [mapping=Texture.DEFAULT_MAPPING] - The texture mapping.
28960	 * @param {number} [wrapS=ClampToEdgeWrapping] - The wrapS value.
28961	 * @param {number} [wrapT=ClampToEdgeWrapping] - The wrapT value.
28962	 * @param {number} [magFilter=LinearFilter] - The mag filter value.
28963	 * @param {number} [minFilter=LinearFilter] - The min filter value.
28964	 * @param {number} [anisotropy=Texture.DEFAULT_ANISOTROPY] - The anisotropy value.
28965	 * @param {number} [format=DepthFormat] - The texture format.
28966	 * @param {number} [depth=1] - The depth of the texture.
28967	 */
28968	constructor( width, height, type = UnsignedIntType, mapping, wrapS, wrapT, magFilter = NearestFilter, minFilter = NearestFilter, anisotropy, format = DepthFormat, depth = 1 ) {
28969
28970		if ( format !== DepthFormat && format !== DepthStencilFormat ) {
28971
28972			throw new Error( 'DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat' );
28973
28974		}
28975
28976		const image = { width: width, height: height, depth: depth };
28977
28978		super( image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
28979
28980		/**
28981		 * This flag can be used for type testing.
28982		 *
28983		 * @type {boolean}
28984		 * @readonly
28985		 * @default true
28986		 */
28987		this.isDepthTexture = true;
28988
28989		/**
28990		 * If set to `true`, the texture is flipped along the vertical axis when
28991		 * uploaded to the GPU.
28992		 *
28993		 * Overwritten and set to `false` by default.
28994		 *
28995		 * @type {boolean}
28996		 * @default false
28997		 */
28998		this.flipY = false;
vendor: 3,182 bytes, lines 28999-29123
28999
29000		/**
29001		 * Whether to generate mipmaps (if possible) for a texture.
29002		 *
29003		 * Overwritten and set to `false` by default.
29004		 *
29005		 * @type {boolean}
29006		 * @default false
29007		 */
29008		this.generateMipmaps = false;
29009
29010		/**
29011		 * Code corresponding to the depth compare function.
29012		 *
29013		 * @type {?(NeverCompare|LessCompare|EqualCompare|LessEqualCompare|GreaterCompare|NotEqualCompare|GreaterEqualCompare|AlwaysCompare)}
29014		 * @default null
29015		 */
29016		this.compareFunction = null;
29017
29018	}
29019
29020
29021	copy( source ) {
29022
29023		super.copy( source );
29024
29025		this.source = new Source( Object.assign( {}, source.image ) ); // see #30540
29026		this.compareFunction = source.compareFunction;
29027
29028		return this;
29029
29030	}
29031
29032	toJSON( meta ) {
29033
29034		const data = super.toJSON( meta );
29035
29036		if ( this.compareFunction !== null ) data.compareFunction = this.compareFunction;
29037
29038		return data;
29039
29040	}
29041
29042}
29043
29044/**
29045 * This class can be used to automatically save the depth information of a
29046 * cube rendering into a cube texture with depth format. Used for PointLight shadows.
29047 *
29048 * @augments DepthTexture
29049 */
29050class CubeDepthTexture extends DepthTexture {
29051
29052	/**
29053	 * Constructs a new cube depth texture.
29054	 *
29055	 * @param {number} size - The size (width and height) of each cube face.
29056	 * @param {number} [type=UnsignedIntType] - The texture type.
29057	 * @param {number} [mapping=CubeReflectionMapping] - The texture mapping.
29058	 * @param {number} [wrapS=ClampToEdgeWrapping] - The wrapS value.
29059	 * @param {number} [wrapT=ClampToEdgeWrapping] - The wrapT value.
29060	 * @param {number} [magFilter=NearestFilter] - The mag filter value.
29061	 * @param {number} [minFilter=NearestFilter] - The min filter value.
29062	 * @param {number} [anisotropy=Texture.DEFAULT_ANISOTROPY] - The anisotropy value.
29063	 * @param {number} [format=DepthFormat] - The texture format.
29064	 */
29065	constructor( size, type = UnsignedIntType, mapping = CubeReflectionMapping, wrapS, wrapT, magFilter = NearestFilter, minFilter = NearestFilter, anisotropy, format = DepthFormat ) {
29066
29067		// Create 6 identical image descriptors for the cube faces
29068		const image = { width: size, height: size, depth: 1 };
29069		const images = [ image, image, image, image, image, image ];
29070
29071		// Call DepthTexture constructor with width, height
29072		super( size, size, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format );
29073
29074		// Replace the single image with the array of 6 images
29075		this.image = images;
29076
29077		/**
29078		 * This flag can be used for type testing.
29079		 *
29080		 * @type {boolean}
29081		 * @readonly
29082		 * @default true
29083		 */
29084		this.isCubeDepthTexture = true;
29085
29086		/**
29087		 * Set to true for cube texture handling in WebGLTextures.
29088		 *
29089		 * @type {boolean}
29090		 * @readonly
29091		 * @default true
29092		 */
29093		this.isCubeTexture = true;
29094
29095	}
29096
29097	/**
29098	 * Alias for {@link CubeDepthTexture#image}.
29099	 *
29100	 * @type {Array<Image>}
29101	 */
29102	get images() {
29103
29104		return this.image;
29105
29106	}
29107
29108	set images( value ) {
29109
29110		this.image = value;
29111
29112	}
29113
29114}
29115
29116/**
29117 * Represents a texture created externally with the same renderer context.
29118 *
29119 * This may be a texture from a protected media stream, device camera feed,
29120 * or other data feeds like a depth sensor.
29121 *
29122 * Note that this class is only supported in {@link WebGLRenderer}, and in
29123 * the {@link WebGPURenderer} WebGPU backend
vendor: 165,892 bytes, lines 29123-36245
29123.
29124 *
29125 * @augments Texture
29126 */
29127class ExternalTexture extends Texture {
29128
29129	/**
29130	 * Creates a new raw texture.
29131	 *
29132	 * @param {?(WebGLTexture|GPUTexture)} [sourceTexture=null] - The external texture.
29133	 */
29134	constructor( sourceTexture = null ) {
29135
29136		super();
29137
29138		/**
29139		 * The external source texture.
29140		 *
29141		 * @type {?(WebGLTexture|GPUTexture)}
29142		 * @default null
29143		 */
29144		this.sourceTexture = sourceTexture;
29145
29146		/**
29147		 * This flag can be used for type testing.
29148		 *
29149		 * @type {boolean}
29150		 * @readonly
29151		 * @default true
29152		 */
29153		this.isExternalTexture = true;
29154
29155	}
29156
29157	copy( source ) {
29158
29159		super.copy( source );
29160
29161		this.sourceTexture = source.sourceTexture;
29162
29163		return this;
29164
29165	}
29166
29167}
29168
29169/**
29170 * A geometry class for a rectangular cuboid with a given width, height, and depth.
29171 * On creation, the cuboid is centred on the origin, with each edge parallel to one
29172 * of the axes.
29173 *
29174 * ```js
29175 * const geometry = new THREE.BoxGeometry( 1, 1, 1 );
29176 * const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
29177 * const cube = new THREE.Mesh( geometry, material );
29178 * scene.add( cube );
29179 * ```
29180 *
29181 * @augments BufferGeometry
29182 * @demo scenes/geometry-browser.html#BoxGeometry
29183 */
29184class BoxGeometry extends BufferGeometry {
29185
29186	/**
29187	 * Constructs a new box geometry.
29188	 *
29189	 * @param {number} [width=1] - The width. That is, the length of the edges parallel to the X axis.
29190	 * @param {number} [height=1] - The height. That is, the length of the edges parallel to the Y axis.
29191	 * @param {number} [depth=1] - The depth. That is, the length of the edges parallel to the Z axis.
29192	 * @param {number} [widthSegments=1] - Number of segmented rectangular faces along the width of the sides.
29193	 * @param {number} [heightSegments=1] - Number of segmented rectangular faces along the height of the sides.
29194	 * @param {number} [depthSegments=1] - Number of segmented rectangular faces along the depth of the sides.
29195	 */
29196	constructor( width = 1, height = 1, depth = 1, widthSegments = 1, heightSegments = 1, depthSegments = 1 ) {
29197
29198		super();
29199
29200		this.type = 'BoxGeometry';
29201
29202		/**
29203		 * Holds the constructor parameters that have been
29204		 * used to generate the geometry. Any modification
29205		 * after instantiation does not change the geometry.
29206		 *
29207		 * @type {Object}
29208		 */
29209		this.parameters = {
29210			width: width,
29211			height: height,
29212			depth: depth,
29213			widthSegments: widthSegments,
29214			heightSegments: heightSegments,
29215			depthSegments: depthSegments
29216		};
29217
29218		const scope = this;
29219
29220		// segments
29221
29222		widthSegments = Math.floor( widthSegments );
29223		heightSegments = Math.floor( heightSegments );
29224		depthSegments = Math.floor( depthSegments );
29225
29226		// buffers
29227
29228		const indices = [];
29229		const vertices = [];
29230		const normals = [];
29231		const uvs = [];
29232
29233		// helper variables
29234
29235		let numberOfVertices = 0;
29236		let groupStart = 0;
29237
29238		// build each side of the box geometry
29239
29240		buildPlane( 'z', 'y', 'x', -1, -1, depth, height, width, depthSegments, heightSegments, 0 ); // px
29241		buildPlane( 'z', 'y', 'x', 1, -1, depth, height, - width, depthSegments, heightSegments, 1 ); // nx
29242		buildPlane( 'x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2 ); // py
29243		buildPlane( 'x', 'z', 'y', 1, -1, width, depth, - height, widthSegments, depthSegments, 3 ); // ny
29244		buildPlane( 'x', 'y', 'z', 1, -1, width, height, depth, widthSegments, heightSegments, 4 ); // pz
29245		buildPlane( 'x', 'y', 'z', -1, -1, width, height, - depth, widthSegments, heightSegments, 5 ); // nz
29246
29247		// build geometry
29248
29249		this.setIndex( indices );
29250		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
29251		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
29252		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
29253
29254		function buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) {
29255
29256			const segmentWidth = width / gridX;
29257			const segmentHeight = height / gridY;
29258
29259			const widthHalf = width / 2;
29260			const heightHalf = height / 2;
29261			const depthHalf = depth / 2;
29262
29263			const gridX1 = gridX + 1;
29264			const gridY1 = gridY + 1;
29265
29266			let vertexCounter = 0;
29267			let groupCount = 0;
29268
29269			const vector = new Vector3();
29270
29271			// generate vertices, normals and uvs
29272
29273			for ( let iy = 0; iy < gridY1; iy ++ ) {
29274
29275				const y = iy * segmentHeight - heightHalf;
29276
29277				for ( let ix = 0; ix < gridX1; ix ++ ) {
29278
29279					const x = ix * segmentWidth - widthHalf;
29280
29281					// set values to correct vector component
29282
29283					vector[ u ] = x * udir;
29284					vector[ v ] = y * vdir;
29285					vector[ w ] = depthHalf;
29286
29287					// now apply vector to vertex buffer
29288
29289					vertices.push( vector.x, vector.y, vector.z );
29290
29291					// set values to correct vector component
29292
29293					vector[ u ] = 0;
29294					vector[ v ] = 0;
29295					vector[ w ] = depth > 0 ? 1 : -1;
29296
29297					// now apply vector to normal buffer
29298
29299					normals.push( vector.x, vector.y, vector.z );
29300
29301					// uvs
29302
29303					uvs.push( ix / gridX );
29304					uvs.push( 1 - ( iy / gridY ) );
29305
29306					// counters
29307
29308					vertexCounter += 1;
29309
29310				}
29311
29312			}
29313
29314			// indices
29315
29316			// 1. you need three indices to draw a single face
29317			// 2. a single segment consists of two faces
29318			// 3. so we need to generate six (2*3) indices per segment
29319
29320			for ( let iy = 0; iy < gridY; iy ++ ) {
29321
29322				for ( let ix = 0; ix < gridX; ix ++ ) {
29323
29324					const a = numberOfVertices + ix + gridX1 * iy;
29325					const b = numberOfVertices + ix + gridX1 * ( iy + 1 );
29326					const c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 );
29327					const d = numberOfVertices + ( ix + 1 ) + gridX1 * iy;
29328
29329					// faces
29330
29331					indices.push( a, b, d );
29332					indices.push( b, c, d );
29333
29334					// increase counter
29335
29336					groupCount += 6;
29337
29338				}
29339
29340			}
29341
29342			// add a group to the geometry. this will ensure multi material support
29343
29344			scope.addGroup( groupStart, groupCount, materialIndex );
29345
29346			// calculate new start value for groups
29347
29348			groupStart += groupCount;
29349
29350			// update total number of vertices
29351
29352			numberOfVertices += vertexCounter;
29353
29354		}
29355
29356	}
29357
29358	copy( source ) {
29359
29360		super.copy( source );
29361
29362		this.parameters = Object.assign( {}, source.parameters );
29363
29364		return this;
29365
29366	}
29367
29368	/**
29369	 * Factory method for creating an instance of this class from the given
29370	 * JSON object.
29371	 *
29372	 * @param {Object} data - A JSON object representing the serialized geometry.
29373	 * @return {BoxGeometry} A new instance.
29374	 */
29375	static fromJSON( data ) {
29376
29377		return new BoxGeometry( data.width, data.height, data.depth, data.widthSegments, data.heightSegments, data.depthSegments );
29378
29379	}
29380
29381}
29382
29383/**
29384 * A geometry class for representing a capsule.
29385 *
29386 * ```js
29387 * const geometry = new THREE.CapsuleGeometry( 1, 1, 4, 8, 1 );
29388 * const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
29389 * const capsule = new THREE.Mesh( geometry, material );
29390 * scene.add( capsule );
29391 * ```
29392 *
29393 * @augments BufferGeometry
29394 * @demo scenes/geometry-browser.html#CapsuleGeometry
29395 */
29396class CapsuleGeometry extends BufferGeometry {
29397
29398	/**
29399	 * Constructs a new capsule geometry.
29400	 *
29401	 * @param {number} [radius=1] - Radius of the capsule.
29402	 * @param {number} [height=1] - Height of the middle section.
29403	 * @param {number} [capSegments=4] - Number of curve segments used to build each cap.
29404	 * @param {number} [radialSegments=8] - Number of segmented faces around the circumference of the capsule. Must be an integer >= 3.
29405	 * @param {number} [heightSegments=1] - Number of rows of faces along the height of the middle section. Must be an integer >= 1.
29406	 */
29407	constructor( radius = 1, height = 1, capSegments = 4, radialSegments = 8, heightSegments = 1 ) {
29408
29409		super();
29410
29411		this.type = 'CapsuleGeometry';
29412
29413		/**
29414		 * Holds the constructor parameters that have been
29415		 * used to generate the geometry. Any modification
29416		 * after instantiation does not change the geometry.
29417		 *
29418		 * @type {Object}
29419		 */
29420		this.parameters = {
29421			radius: radius,
29422			height: height,
29423			capSegments: capSegments,
29424			radialSegments: radialSegments,
29425			heightSegments: heightSegments,
29426		};
29427
29428		height = Math.max( 0, height );
29429		capSegments = Math.max( 1, Math.floor( capSegments ) );
29430		radialSegments = Math.max( 3, Math.floor( radialSegments ) );
29431		heightSegments = Math.max( 1, Math.floor( heightSegments ) );
29432
29433		// buffers
29434
29435		const indices = [];
29436		const vertices = [];
29437		const normals = [];
29438		const uvs = [];
29439
29440		// helper variables
29441
29442		const halfHeight = height / 2;
29443		const capArcLength = ( Math.PI / 2 ) * radius;
29444		const cylinderPartLength = height;
29445		const totalArcLength = 2 * capArcLength + cylinderPartLength;
29446
29447		const numVerticalSegments = capSegments * 2 + heightSegments;
29448		const verticesPerRow = radialSegments + 1;
29449
29450		const normal = new Vector3();
29451		const vertex = new Vector3();
29452
29453		// generate vertices, normals, and uvs
29454
29455		for ( let iy = 0; iy <= numVerticalSegments; iy ++ ) {
29456
29457			let currentArcLength = 0;
29458			let profileY = 0;
29459			let profileRadius = 0;
29460			let normalYComponent = 0;
29461
29462			if ( iy <= capSegments ) {
29463
29464				// bottom cap
29465				const segmentProgress = iy / capSegments;
29466				const angle = ( segmentProgress * Math.PI ) / 2;
29467				profileY = - halfHeight - radius * Math.cos( angle );
29468				profileRadius = radius * Math.sin( angle );
29469				normalYComponent = - radius * Math.cos( angle );
29470				currentArcLength = segmentProgress * capArcLength;
29471
29472			} else if ( iy <= capSegments + heightSegments ) {
29473
29474				// middle section
29475				const segmentProgress = ( iy - capSegments ) / heightSegments;
29476				profileY = - halfHeight + segmentProgress * height;
29477				profileRadius = radius;
29478				normalYComponent = 0;
29479				currentArcLength = capArcLength + segmentProgress * cylinderPartLength;
29480
29481			} else {
29482
29483				// top cap
29484				const segmentProgress =
29485					( iy - capSegments - heightSegments ) / capSegments;
29486				const angle = ( segmentProgress * Math.PI ) / 2;
29487				profileY = halfHeight + radius * Math.sin( angle );
29488				profileRadius = radius * Math.cos( angle );
29489				normalYComponent = radius * Math.sin( angle );
29490				currentArcLength =
29491					capArcLength + cylinderPartLength + segmentProgress * capArcLength;
29492
29493			}
29494
29495			const v = Math.max( 0, Math.min( 1, currentArcLength / totalArcLength ) );
29496
29497
29498			// special case for the poles
29499
29500			let uOffset = 0;
29501
29502			if ( iy === 0 ) {
29503
29504				uOffset = 0.5 / radialSegments;
29505
29506			} else if ( iy === numVerticalSegments ) {
29507
29508				uOffset = -0.5 / radialSegments;
29509
29510			}
29511
29512			for ( let ix = 0; ix <= radialSegments; ix ++ ) {
29513
29514				const u = ix / radialSegments;
29515				const theta = u * Math.PI * 2;
29516
29517				const sinTheta = Math.sin( theta );
29518				const cosTheta = Math.cos( theta );
29519
29520				// vertex
29521
29522				vertex.x = - profileRadius * cosTheta;
29523				vertex.y = profileY;
29524				vertex.z = profileRadius * sinTheta;
29525				vertices.push( vertex.x, vertex.y, vertex.z );
29526
29527				// normal
29528
29529				normal.set(
29530					- profileRadius * cosTheta,
29531					normalYComponent,
29532					profileRadius * sinTheta
29533				);
29534				normal.normalize();
29535				normals.push( normal.x, normal.y, normal.z );
29536
29537				// uv
29538
29539				uvs.push( u + uOffset, v );
29540
29541			}
29542
29543			if ( iy > 0 ) {
29544
29545				const prevIndexRow = ( iy - 1 ) * verticesPerRow;
29546				for ( let ix = 0; ix < radialSegments; ix ++ ) {
29547
29548					const i1 = prevIndexRow + ix;
29549					const i2 = prevIndexRow + ix + 1;
29550					const i3 = iy * verticesPerRow + ix;
29551					const i4 = iy * verticesPerRow + ix + 1;
29552
29553					indices.push( i1, i2, i3 );
29554					indices.push( i2, i4, i3 );
29555
29556				}
29557
29558			}
29559
29560		}
29561
29562		// build geometry
29563
29564		this.setIndex( indices );
29565		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
29566		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
29567		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
29568
29569	}
29570
29571	copy( source ) {
29572
29573		super.copy( source );
29574
29575		this.parameters = Object.assign( {}, source.parameters );
29576
29577		return this;
29578
29579	}
29580
29581	/**
29582	 * Factory method for creating an instance of this class from the given
29583	 * JSON object.
29584	 *
29585	 * @param {Object} data - A JSON object representing the serialized geometry.
29586	 * @return {CapsuleGeometry} A new instance.
29587	 */
29588	static fromJSON( data ) {
29589
29590		return new CapsuleGeometry( data.radius, data.height, data.capSegments, data.radialSegments, data.heightSegments );
29591
29592	}
29593
29594}
29595
29596/**
29597 * A simple shape of Euclidean geometry. It is constructed from a
29598 * number of triangular segments that are oriented around a central point and
29599 * extend as far out as a given radius. It is built counter-clockwise from a
29600 * start angle and a given central angle. It can also be used to create
29601 * regular polygons, where the number of segments determines the number of
29602 * sides.
29603 *
29604 * ```js
29605 * const geometry = new THREE.CircleGeometry( 5, 32 );
29606 * const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
29607 * const circle = new THREE.Mesh( geometry, material );
29608 * scene.add( circle )
29609 * ```
29610 *
29611 * @augments BufferGeometry
29612 * @demo scenes/geometry-browser.html#CircleGeometry
29613 */
29614class CircleGeometry extends BufferGeometry {
29615
29616	/**
29617	 * Constructs a new circle geometry.
29618	 *
29619	 * @param {number} [radius=1] - Radius of the circle.
29620	 * @param {number} [segments=32] - Number of segments (triangles), minimum = `3`.
29621	 * @param {number} [thetaStart=0] - Start angle for first segment in radians.
29622	 * @param {number} [thetaLength=Math.PI*2] - The central angle, often called theta,
29623	 * of the circular sector in radians. The default value results in a complete circle.
29624	 */
29625	constructor( radius = 1, segments = 32, thetaStart = 0, thetaLength = Math.PI * 2 ) {
29626
29627		super();
29628
29629		this.type = 'CircleGeometry';
29630
29631		/**
29632		 * Holds the constructor parameters that have been
29633		 * used to generate the geometry. Any modification
29634		 * after instantiation does not change the geometry.
29635		 *
29636		 * @type {Object}
29637		 */
29638		this.parameters = {
29639			radius: radius,
29640			segments: segments,
29641			thetaStart: thetaStart,
29642			thetaLength: thetaLength
29643		};
29644
29645		segments = Math.max( 3, segments );
29646
29647		// buffers
29648
29649		const indices = [];
29650		const vertices = [];
29651		const normals = [];
29652		const uvs = [];
29653
29654		// helper variables
29655
29656		const vertex = new Vector3();
29657		const uv = new Vector2();
29658
29659		// center point
29660
29661		vertices.push( 0, 0, 0 );
29662		normals.push( 0, 0, 1 );
29663		uvs.push( 0.5, 0.5 );
29664
29665		for ( let s = 0, i = 3; s <= segments; s ++, i += 3 ) {
29666
29667			const segment = thetaStart + s / segments * thetaLength;
29668
29669			// vertex
29670
29671			vertex.x = radius * Math.cos( segment );
29672			vertex.y = radius * Math.sin( segment );
29673
29674			vertices.push( vertex.x, vertex.y, vertex.z );
29675
29676			// normal
29677
29678			normals.push( 0, 0, 1 );
29679
29680			// uvs
29681
29682			uv.x = ( vertices[ i ] / radius + 1 ) / 2;
29683			uv.y = ( vertices[ i + 1 ] / radius + 1 ) / 2;
29684
29685			uvs.push( uv.x, uv.y );
29686
29687		}
29688
29689		// indices
29690
29691		for ( let i = 1; i <= segments; i ++ ) {
29692
29693			indices.push( i, i + 1, 0 );
29694
29695		}
29696
29697		// build geometry
29698
29699		this.setIndex( indices );
29700		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
29701		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
29702		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
29703
29704	}
29705
29706	copy( source ) {
29707
29708		super.copy( source );
29709
29710		this.parameters = Object.assign( {}, source.parameters );
29711
29712		return this;
29713
29714	}
29715
29716	/**
29717	 * Factory method for creating an instance of this class from the given
29718	 * JSON object.
29719	 *
29720	 * @param {Object} data - A JSON object representing the serialized geometry.
29721	 * @return {CircleGeometry} A new instance.
29722	 */
29723	static fromJSON( data ) {
29724
29725		return new CircleGeometry( data.radius, data.segments, data.thetaStart, data.thetaLength );
29726
29727	}
29728
29729}
29730
29731/**
29732 * A geometry class for representing a cylinder.
29733 *
29734 * ```js
29735 * const geometry = new THREE.CylinderGeometry( 5, 5, 20, 32 );
29736 * const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
29737 * const cylinder = new THREE.Mesh( geometry, material );
29738 * scene.add( cylinder );
29739 * ```
29740 *
29741 * @augments BufferGeometry
29742 * @demo scenes/geometry-browser.html#CylinderGeometry
29743 */
29744class CylinderGeometry extends BufferGeometry {
29745
29746	/**
29747	 * Constructs a new cylinder geometry.
29748	 *
29749	 * @param {number} [radiusTop=1] - Radius of the cylinder at the top.
29750	 * @param {number} [radiusBottom=1] - Radius of the cylinder at the bottom.
29751	 * @param {number} [height=1] - Height of the cylinder.
29752	 * @param {number} [radialSegments=32] - Number of segmented faces around the circumference of the cylinder.
29753	 * @param {number} [heightSegments=1] - Number of rows of faces along the height of the cylinder.
29754	 * @param {boolean} [openEnded=false] - Whether the base of the cylinder is open or capped.
29755	 * @param {number} [thetaStart=0] - Start angle for first segment, in radians.
29756	 * @param {number} [thetaLength=Math.PI*2] - The central angle, often called theta, of the circular sector, in radians.
29757	 * The default value results in a complete cylinder.
29758	 */
29759	constructor( radiusTop = 1, radiusBottom = 1, height = 1, radialSegments = 32, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2 ) {
29760
29761		super();
29762
29763		this.type = 'CylinderGeometry';
29764
29765		/**
29766		 * Holds the constructor parameters that have been
29767		 * used to generate the geometry. Any modification
29768		 * after instantiation does not change the geometry.
29769		 *
29770		 * @type {Object}
29771		 */
29772		this.parameters = {
29773			radiusTop: radiusTop,
29774			radiusBottom: radiusBottom,
29775			height: height,
29776			radialSegments: radialSegments,
29777			heightSegments: heightSegments,
29778			openEnded: openEnded,
29779			thetaStart: thetaStart,
29780			thetaLength: thetaLength
29781		};
29782
29783		const scope = this;
29784
29785		radialSegments = Math.floor( radialSegments );
29786		heightSegments = Math.floor( heightSegments );
29787
29788		// buffers
29789
29790		const indices = [];
29791		const vertices = [];
29792		const normals = [];
29793		const uvs = [];
29794
29795		// helper variables
29796
29797		let index = 0;
29798		const indexArray = [];
29799		const halfHeight = height / 2;
29800		let groupStart = 0;
29801
29802		// generate geometry
29803
29804		generateTorso();
29805
29806		if ( openEnded === false ) {
29807
29808			if ( radiusTop > 0 ) generateCap( true );
29809			if ( radiusBottom > 0 ) generateCap( false );
29810
29811		}
29812
29813		// build geometry
29814
29815		this.setIndex( indices );
29816		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
29817		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
29818		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
29819
29820		function generateTorso() {
29821
29822			const normal = new Vector3();
29823			const vertex = new Vector3();
29824
29825			let groupCount = 0;
29826
29827			// this will be used to calculate the normal
29828			const slope = ( radiusBottom - radiusTop ) / height;
29829
29830			// generate vertices, normals and uvs
29831
29832			for ( let y = 0; y <= heightSegments; y ++ ) {
29833
29834				const indexRow = [];
29835
29836				const v = y / heightSegments;
29837
29838				// calculate the radius of the current row
29839
29840				const radius = v * ( radiusBottom - radiusTop ) + radiusTop;
29841
29842				for ( let x = 0; x <= radialSegments; x ++ ) {
29843
29844					const u = x / radialSegments;
29845
29846					const theta = u * thetaLength + thetaStart;
29847
29848					const sinTheta = Math.sin( theta );
29849					const cosTheta = Math.cos( theta );
29850
29851					// vertex
29852
29853					vertex.x = radius * sinTheta;
29854					vertex.y = - v * height + halfHeight;
29855					vertex.z = radius * cosTheta;
29856					vertices.push( vertex.x, vertex.y, vertex.z );
29857
29858					// normal
29859
29860					normal.set( sinTheta, slope, cosTheta ).normalize();
29861					normals.push( normal.x, normal.y, normal.z );
29862
29863					// uv
29864
29865					uvs.push( u, 1 - v );
29866
29867					// save index of vertex in respective row
29868
29869					indexRow.push( index ++ );
29870
29871				}
29872
29873				// now save vertices of the row in our index array
29874
29875				indexArray.push( indexRow );
29876
29877			}
29878
29879			// generate indices
29880
29881			for ( let x = 0; x < radialSegments; x ++ ) {
29882
29883				for ( let y = 0; y < heightSegments; y ++ ) {
29884
29885					// we use the index array to access the correct indices
29886
29887					const a = indexArray[ y ][ x ];
29888					const b = indexArray[ y + 1 ][ x ];
29889					const c = indexArray[ y + 1 ][ x + 1 ];
29890					const d = indexArray[ y ][ x + 1 ];
29891
29892					// faces
29893
29894					if ( radiusTop > 0 || y !== 0 ) {
29895
29896						indices.push( a, b, d );
29897						groupCount += 3;
29898
29899					}
29900
29901					if ( radiusBottom > 0 || y !== heightSegments - 1 ) {
29902
29903						indices.push( b, c, d );
29904						groupCount += 3;
29905
29906					}
29907
29908				}
29909
29910			}
29911
29912			// add a group to the geometry. this will ensure multi material support
29913
29914			scope.addGroup( groupStart, groupCount, 0 );
29915
29916			// calculate new start value for groups
29917
29918			groupStart += groupCount;
29919
29920		}
29921
29922		function generateCap( top ) {
29923
29924			// save the index of the first center vertex
29925			const centerIndexStart = index;
29926
29927			const uv = new Vector2();
29928			const vertex = new Vector3();
29929
29930			let groupCount = 0;
29931
29932			const radius = ( top === true ) ? radiusTop : radiusBottom;
29933			const sign = ( top === true ) ? 1 : -1;
29934
29935			// first we generate the center vertex data of the cap.
29936			// because the geometry needs one set of uvs per face,
29937			// we must generate a center vertex per face/segment
29938
29939			for ( let x = 1; x <= radialSegments; x ++ ) {
29940
29941				// vertex
29942
29943				vertices.push( 0, halfHeight * sign, 0 );
29944
29945				// normal
29946
29947				normals.push( 0, sign, 0 );
29948
29949				// uv
29950
29951				uvs.push( 0.5, 0.5 );
29952
29953				// increase index
29954
29955				index ++;
29956
29957			}
29958
29959			// save the index of the last center vertex
29960			const centerIndexEnd = index;
29961
29962			// now we generate the surrounding vertices, normals and uvs
29963
29964			for ( let x = 0; x <= radialSegments; x ++ ) {
29965
29966				const u = x / radialSegments;
29967				const theta = u * thetaLength + thetaStart;
29968
29969				const cosTheta = Math.cos( theta );
29970				const sinTheta = Math.sin( theta );
29971
29972				// vertex
29973
29974				vertex.x = radius * sinTheta;
29975				vertex.y = halfHeight * sign;
29976				vertex.z = radius * cosTheta;
29977				vertices.push( vertex.x, vertex.y, vertex.z );
29978
29979				// normal
29980
29981				normals.push( 0, sign, 0 );
29982
29983				// uv
29984
29985				uv.x = ( cosTheta * 0.5 ) + 0.5;
29986				uv.y = ( sinTheta * 0.5 * sign ) + 0.5;
29987				uvs.push( uv.x, uv.y );
29988
29989				// increase index
29990
29991				index ++;
29992
29993			}
29994
29995			// generate indices
29996
29997			for ( let x = 0; x < radialSegments; x ++ ) {
29998
29999				const c = centerIndexStart + x;
30000				const i = centerIndexEnd + x;
30001
30002				if ( top === true ) {
30003
30004					// face top
30005
30006					indices.push( i, i + 1, c );
30007
30008				} else {
30009
30010					// face bottom
30011
30012					indices.push( i + 1, i, c );
30013
30014				}
30015
30016				groupCount += 3;
30017
30018			}
30019
30020			// add a group to the geometry. this will ensure multi material support
30021
30022			scope.addGroup( groupStart, groupCount, top === true ? 1 : 2 );
30023
30024			// calculate new start value for groups
30025
30026			groupStart += groupCount;
30027
30028		}
30029
30030	}
30031
30032	copy( source ) {
30033
30034		super.copy( source );
30035
30036		this.parameters = Object.assign( {}, source.parameters );
30037
30038		return this;
30039
30040	}
30041
30042	/**
30043	 * Factory method for creating an instance of this class from the given
30044	 * JSON object.
30045	 *
30046	 * @param {Object} data - A JSON object representing the serialized geometry.
30047	 * @return {CylinderGeometry} A new instance.
30048	 */
30049	static fromJSON( data ) {
30050
30051		return new CylinderGeometry( data.radiusTop, data.radiusBottom, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength );
30052
30053	}
30054
30055}
30056
30057/**
30058 * A geometry class for representing a cone.
30059 *
30060 * ```js
30061 * const geometry = new THREE.ConeGeometry( 5, 20, 32 );
30062 * const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
30063 * const cone = new THREE.Mesh(geometry, material );
30064 * scene.add( cone );
30065 * ```
30066 *
30067 * @augments CylinderGeometry
30068 * @demo scenes/geometry-browser.html#ConeGeometry
30069 */
30070class ConeGeometry extends CylinderGeometry {
30071
30072	/**
30073	 * Constructs a new cone geometry.
30074	 *
30075	 * @param {number} [radius=1] - Radius of the cone base.
30076	 * @param {number} [height=1] - Height of the cone.
30077	 * @param {number} [radialSegments=32] - Number of segmented faces around the circumference of the cone.
30078	 * @param {number} [heightSegments=1] - Number of rows of faces along the height of the cone.
30079	 * @param {boolean} [openEnded=false] - Whether the base of the cone is open or capped.
30080	 * @param {number} [thetaStart=0] - Start angle for first segment, in radians.
30081	 * @param {number} [thetaLength=Math.PI*2] - The central angle, often called theta, of the circular sector, in radians.
30082	 * The default value results in a complete cone.
30083	 */
30084	constructor( radius = 1, height = 1, radialSegments = 32, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2 ) {
30085
30086		super( 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength );
30087
30088		this.type = 'ConeGeometry';
30089
30090		/**
30091		 * Holds the constructor parameters that have been
30092		 * used to generate the geometry. Any modification
30093		 * after instantiation does not change the geometry.
30094		 *
30095		 * @type {Object}
30096		 */
30097		this.parameters = {
30098			radius: radius,
30099			height: height,
30100			radialSegments: radialSegments,
30101			heightSegments: heightSegments,
30102			openEnded: openEnded,
30103			thetaStart: thetaStart,
30104			thetaLength: thetaLength
30105		};
30106
30107	}
30108
30109	/**
30110	 * Factory method for creating an instance of this class from the given
30111	 * JSON object.
30112	 *
30113	 * @param {Object} data - A JSON object representing the serialized geometry.
30114	 * @return {ConeGeometry} A new instance.
30115	 */
30116	static fromJSON( data ) {
30117
30118		return new ConeGeometry( data.radius, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength );
30119
30120	}
30121
30122}
30123
30124/**
30125 * A polyhedron is a solid in three dimensions with flat faces. This class
30126 * will take an array of vertices, project them onto a sphere, and then
30127 * divide them up to the desired level of detail.
30128 *
30129 * @augments BufferGeometry
30130 */
30131class PolyhedronGeometry extends BufferGeometry {
30132
30133	/**
30134	 * Constructs a new polyhedron geometry.
30135	 *
30136	 * @param {Array<number>} [vertices] - A flat array of vertices describing the base shape.
30137	 * @param {Array<number>} [indices] - A flat array of indices describing the base shape.
30138	 * @param {number} [radius=1] - The radius of the shape.
30139	 * @param {number} [detail=0] - How many levels to subdivide the geometry. The more detail, the smoother the shape.
30140	 */
30141	constructor( vertices = [], indices = [], radius = 1, detail = 0 ) {
30142
30143		super();
30144
30145		this.type = 'PolyhedronGeometry';
30146
30147		/**
30148		 * Holds the constructor parameters that have been
30149		 * used to generate the geometry. Any modification
30150		 * after instantiation does not change the geometry.
30151		 *
30152		 * @type {Object}
30153		 */
30154		this.parameters = {
30155			vertices: vertices,
30156			indices: indices,
30157			radius: radius,
30158			detail: detail
30159		};
30160
30161		// default buffer data
30162
30163		const vertexBuffer = [];
30164		const uvBuffer = [];
30165
30166		// the subdivision creates the vertex buffer data
30167
30168		subdivide( detail );
30169
30170		// all vertices should lie on a conceptual sphere with a given radius
30171
30172		applyRadius( radius );
30173
30174		// finally, create the uv data
30175
30176		generateUVs();
30177
30178		// build non-indexed geometry
30179
30180		this.setAttribute( 'position', new Float32BufferAttribute( vertexBuffer, 3 ) );
30181		this.setAttribute( 'normal', new Float32BufferAttribute( vertexBuffer.slice(), 3 ) );
30182		this.setAttribute( 'uv', new Float32BufferAttribute( uvBuffer, 2 ) );
30183
30184		if ( detail === 0 ) {
30185
30186			this.computeVertexNormals(); // flat normals
30187
30188		} else {
30189
30190			this.normalizeNormals(); // smooth normals
30191
30192		}
30193
30194		// helper functions
30195
30196		function subdivide( detail ) {
30197
30198			const a = new Vector3();
30199			const b = new Vector3();
30200			const c = new Vector3();
30201
30202			// iterate over all faces and apply a subdivision with the given detail value
30203
30204			for ( let i = 0; i < indices.length; i += 3 ) {
30205
30206				// get the vertices of the face
30207
30208				getVertexByIndex( indices[ i + 0 ], a );
30209				getVertexByIndex( indices[ i + 1 ], b );
30210				getVertexByIndex( indices[ i + 2 ], c );
30211
30212				// perform subdivision
30213
30214				subdivideFace( a, b, c, detail );
30215
30216			}
30217
30218		}
30219
30220		function subdivideFace( a, b, c, detail ) {
30221
30222			const cols = detail + 1;
30223
30224			// we use this multidimensional array as a data structure for creating the subdivision
30225
30226			const v = [];
30227
30228			// construct all of the vertices for this subdivision
30229
30230			for ( let i = 0; i <= cols; i ++ ) {
30231
30232				v[ i ] = [];
30233
30234				const aj = a.clone().lerp( c, i / cols );
30235				const bj = b.clone().lerp( c, i / cols );
30236
30237				const rows = cols - i;
30238
30239				for ( let j = 0; j <= rows; j ++ ) {
30240
30241					if ( j === 0 && i === cols ) {
30242
30243						v[ i ][ j ] = aj;
30244
30245					} else {
30246
30247						v[ i ][ j ] = aj.clone().lerp( bj, j / rows );
30248
30249					}
30250
30251				}
30252
30253			}
30254
30255			// construct all of the faces
30256
30257			for ( let i = 0; i < cols; i ++ ) {
30258
30259				for ( let j = 0; j < 2 * ( cols - i ) - 1; j ++ ) {
30260
30261					const k = Math.floor( j / 2 );
30262
30263					if ( j % 2 === 0 ) {
30264
30265						pushVertex( v[ i ][ k + 1 ] );
30266						pushVertex( v[ i + 1 ][ k ] );
30267						pushVertex( v[ i ][ k ] );
30268
30269					} else {
30270
30271						pushVertex( v[ i ][ k + 1 ] );
30272						pushVertex( v[ i + 1 ][ k + 1 ] );
30273						pushVertex( v[ i + 1 ][ k ] );
30274
30275					}
30276
30277				}
30278
30279			}
30280
30281		}
30282
30283		function applyRadius( radius ) {
30284
30285			const vertex = new Vector3();
30286
30287			// iterate over the entire buffer and apply the radius to each vertex
30288
30289			for ( let i = 0; i < vertexBuffer.length; i += 3 ) {
30290
30291				vertex.x = vertexBuffer[ i + 0 ];
30292				vertex.y = vertexBuffer[ i + 1 ];
30293				vertex.z = vertexBuffer[ i + 2 ];
30294
30295				vertex.normalize().multiplyScalar( radius );
30296
30297				vertexBuffer[ i + 0 ] = vertex.x;
30298				vertexBuffer[ i + 1 ] = vertex.y;
30299				vertexBuffer[ i + 2 ] = vertex.z;
30300
30301			}
30302
30303		}
30304
30305		function generateUVs() {
30306
30307			const vertex = new Vector3();
30308
30309			for ( let i = 0; i < vertexBuffer.length; i += 3 ) {
30310
30311				vertex.x = vertexBuffer[ i + 0 ];
30312				vertex.y = vertexBuffer[ i + 1 ];
30313				vertex.z = vertexBuffer[ i + 2 ];
30314
30315				const u = azimuth( vertex ) / 2 / Math.PI + 0.5;
30316				const v = inclination( vertex ) / Math.PI + 0.5;
30317				uvBuffer.push( u, 1 - v );
30318
30319			}
30320
30321			correctUVs();
30322
30323			correctSeam();
30324
30325		}
30326
30327		function correctSeam() {
30328
30329			// handle case when face straddles the seam, see #3269
30330
30331			for ( let i = 0; i < uvBuffer.length; i += 6 ) {
30332
30333				// uv data of a single face
30334
30335				const x0 = uvBuffer[ i + 0 ];
30336				const x1 = uvBuffer[ i + 2 ];
30337				const x2 = uvBuffer[ i + 4 ];
30338
30339				const max = Math.max( x0, x1, x2 );
30340				const min = Math.min( x0, x1, x2 );
30341
30342				// 0.9 is somewhat arbitrary
30343
30344				if ( max > 0.9 && min < 0.1 ) {
30345
30346					if ( x0 < 0.2 ) uvBuffer[ i + 0 ] += 1;
30347					if ( x1 < 0.2 ) uvBuffer[ i + 2 ] += 1;
30348					if ( x2 < 0.2 ) uvBuffer[ i + 4 ] += 1;
30349
30350				}
30351
30352			}
30353
30354		}
30355
30356		function pushVertex( vertex ) {
30357
30358			vertexBuffer.push( vertex.x, vertex.y, vertex.z );
30359
30360		}
30361
30362		function getVertexByIndex( index, vertex ) {
30363
30364			const stride = index * 3;
30365
30366			vertex.x = vertices[ stride + 0 ];
30367			vertex.y = vertices[ stride + 1 ];
30368			vertex.z = vertices[ stride + 2 ];
30369
30370		}
30371
30372		function correctUVs() {
30373
30374			const a = new Vector3();
30375			const b = new Vector3();
30376			const c = new Vector3();
30377
30378			const centroid = new Vector3();
30379
30380			const uvA = new Vector2();
30381			const uvB = new Vector2();
30382			const uvC = new Vector2();
30383
30384			for ( let i = 0, j = 0; i < vertexBuffer.length; i += 9, j += 6 ) {
30385
30386				a.set( vertexBuffer[ i + 0 ], vertexBuffer[ i + 1 ], vertexBuffer[ i + 2 ] );
30387				b.set( vertexBuffer[ i + 3 ], vertexBuffer[ i + 4 ], vertexBuffer[ i + 5 ] );
30388				c.set( vertexBuffer[ i + 6 ], vertexBuffer[ i + 7 ], vertexBuffer[ i + 8 ] );
30389
30390				uvA.set( uvBuffer[ j + 0 ], uvBuffer[ j + 1 ] );
30391				uvB.set( uvBuffer[ j + 2 ], uvBuffer[ j + 3 ] );
30392				uvC.set( uvBuffer[ j + 4 ], uvBuffer[ j + 5 ] );
30393
30394				centroid.copy( a ).add( b ).add( c ).divideScalar( 3 );
30395
30396				const azi = azimuth( centroid );
30397
30398				correctUV( uvA, j + 0, a, azi );
30399				correctUV( uvB, j + 2, b, azi );
30400				correctUV( uvC, j + 4, c, azi );
30401
30402			}
30403
30404		}
30405
30406		function correctUV( uv, stride, vector, azimuth ) {
30407
30408			if ( ( azimuth < 0 ) && ( uv.x === 1 ) ) {
30409
30410				uvBuffer[ stride ] = uv.x - 1;
30411
30412			}
30413
30414			if ( ( vector.x === 0 ) && ( vector.z === 0 ) ) {
30415
30416				uvBuffer[ stride ] = azimuth / 2 / Math.PI + 0.5;
30417
30418			}
30419
30420		}
30421
30422		// Angle around the Y axis, counter-clockwise when looking from above.
30423
30424		function azimuth( vector ) {
30425
30426			return Math.atan2( vector.z, - vector.x );
30427
30428		}
30429
30430
30431		// Angle above the XZ plane.
30432
30433		function inclination( vector ) {
30434
30435			return Math.atan2( - vector.y, Math.sqrt( ( vector.x * vector.x ) + ( vector.z * vector.z ) ) );
30436
30437		}
30438
30439	}
30440
30441	copy( source ) {
30442
30443		super.copy( source );
30444
30445		this.parameters = Object.assign( {}, source.parameters );
30446
30447		return this;
30448
30449	}
30450
30451	/**
30452	 * Factory method for creating an instance of this class from the given
30453	 * JSON object.
30454	 *
30455	 * @param {Object} data - A JSON object representing the serialized geometry.
30456	 * @return {PolyhedronGeometry} A new instance.
30457	 */
30458	static fromJSON( data ) {
30459
30460		return new PolyhedronGeometry( data.vertices, data.indices, data.radius, data.detail );
30461
30462	}
30463
30464}
30465
30466/**
30467 * A geometry class for representing a dodecahedron.
30468 *
30469 * ```js
30470 * const geometry = new THREE.DodecahedronGeometry();
30471 * const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
30472 * const dodecahedron = new THREE.Mesh( geometry, material );
30473 * scene.add( dodecahedron );
30474 * ```
30475 *
30476 * @augments PolyhedronGeometry
30477 * @demo scenes/geometry-browser.html#DodecahedronGeometry
30478 */
30479class DodecahedronGeometry extends PolyhedronGeometry {
30480
30481	/**
30482	 * Constructs a new dodecahedron geometry.
30483	 *
30484	 * @param {number} [radius=1] - Radius of the dodecahedron.
30485	 * @param {number} [detail=0] - Setting this to a value greater than `0` adds vertices making it no longer a dodecahedron.
30486	 */
30487	constructor( radius = 1, detail = 0 ) {
30488
30489		const t = ( 1 + Math.sqrt( 5 ) ) / 2;
30490		const r = 1 / t;
30491
30492		const vertices = [
30493
30494			// (±1, ±1, ±1)
30495			-1, -1, -1,	-1, -1, 1,
30496			-1, 1, -1, -1, 1, 1,
30497			1, -1, -1, 1, -1, 1,
30498			1, 1, -1, 1, 1, 1,
30499
30500			// (0, ±1/φ, ±φ)
30501			0, - r, - t, 0, - r, t,
30502			0, r, - t, 0, r, t,
30503
30504			// (±1/φ, ±φ, 0)
30505			- r, - t, 0, - r, t, 0,
30506			r, - t, 0, r, t, 0,
30507
30508			// (±φ, 0, ±1/φ)
30509			- t, 0, - r, t, 0, - r,
30510			- t, 0, r, t, 0, r
30511		];
30512
30513		const indices = [
30514			3, 11, 7, 	3, 7, 15, 	3, 15, 13,
30515			7, 19, 17, 	7, 17, 6, 	7, 6, 15,
30516			17, 4, 8, 	17, 8, 10, 	17, 10, 6,
30517			8, 0, 16, 	8, 16, 2, 	8, 2, 10,
30518			0, 12, 1, 	0, 1, 18, 	0, 18, 16,
30519			6, 10, 2, 	6, 2, 13, 	6, 13, 15,
30520			2, 16, 18, 	2, 18, 3, 	2, 3, 13,
30521			18, 1, 9, 	18, 9, 11, 	18, 11, 3,
30522			4, 14, 12, 	4, 12, 0, 	4, 0, 8,
30523			11, 9, 5, 	11, 5, 19, 	11, 19, 7,
30524			19, 5, 14, 	19, 14, 4, 	19, 4, 17,
30525			1, 12, 14, 	1, 14, 5, 	1, 5, 9
30526		];
30527
30528		super( vertices, indices, radius, detail );
30529
30530		this.type = 'DodecahedronGeometry';
30531
30532		/**
30533		 * Holds the constructor parameters that have been
30534		 * used to generate the geometry. Any modification
30535		 * after instantiation does not change the geometry.
30536		 *
30537		 * @type {Object}
30538		 */
30539		this.parameters = {
30540			radius: radius,
30541			detail: detail
30542		};
30543
30544	}
30545
30546	/**
30547	 * Factory method for creating an instance of this class from the given
30548	 * JSON object.
30549	 *
30550	 * @param {Object} data - A JSON object representing the serialized geometry.
30551	 * @return {DodecahedronGeometry} A new instance.
30552	 */
30553	static fromJSON( data ) {
30554
30555		return new DodecahedronGeometry( data.radius, data.detail );
30556
30557	}
30558
30559}
30560
30561const _v0 = /*@__PURE__*/ new Vector3();
30562const _v1$1 = /*@__PURE__*/ new Vector3();
30563const _normal = /*@__PURE__*/ new Vector3();
30564const _triangle = /*@__PURE__*/ new Triangle();
30565
30566/**
30567 * Can be used as a helper object to view the edges of a geometry.
30568 *
30569 * ```js
30570 * const geometry = new THREE.BoxGeometry();
30571 * const edges = new THREE.EdgesGeometry( geometry );
30572 * const line = new THREE.LineSegments( edges );
30573 * scene.add( line );
30574 * ```
30575 *
30576 * Note: It is not yet possible to serialize/deserialize instances of this class.
30577 *
30578 * @augments BufferGeometry
30579 */
30580class EdgesGeometry extends BufferGeometry {
30581
30582	/**
30583	 * Constructs a new edges geometry.
30584	 *
30585	 * @param {?BufferGeometry} [geometry=null] - The geometry.
30586	 * @param {number} [thresholdAngle=1] - An edge is only rendered if the angle (in degrees)
30587	 * between the face normals of the adjoining faces exceeds this value.
30588	 */
30589	constructor( geometry = null, thresholdAngle = 1 ) {
30590
30591		super();
30592
30593		this.type = 'EdgesGeometry';
30594
30595		/**
30596		 * Holds the constructor parameters that have been
30597		 * used to generate the geometry. Any modification
30598		 * after instantiation does not change the geometry.
30599		 *
30600		 * @type {Object}
30601		 */
30602		this.parameters = {
30603			geometry: geometry,
30604			thresholdAngle: thresholdAngle
30605		};
30606
30607		if ( geometry !== null ) {
30608
30609			const precisionPoints = 4;
30610			const precision = Math.pow( 10, precisionPoints );
30611			const thresholdDot = Math.cos( DEG2RAD * thresholdAngle );
30612
30613			const indexAttr = geometry.getIndex();
30614			const positionAttr = geometry.getAttribute( 'position' );
30615			const indexCount = indexAttr ? indexAttr.count : positionAttr.count;
30616
30617			const indexArr = [ 0, 0, 0 ];
30618			const vertKeys = [ 'a', 'b', 'c' ];
30619			const hashes = new Array( 3 );
30620
30621			const edgeData = {};
30622			const vertices = [];
30623			for ( let i = 0; i < indexCount; i += 3 ) {
30624
30625				if ( indexAttr ) {
30626
30627					indexArr[ 0 ] = indexAttr.getX( i );
30628					indexArr[ 1 ] = indexAttr.getX( i + 1 );
30629					indexArr[ 2 ] = indexAttr.getX( i + 2 );
30630
30631				} else {
30632
30633					indexArr[ 0 ] = i;
30634					indexArr[ 1 ] = i + 1;
30635					indexArr[ 2 ] = i + 2;
30636
30637				}
30638
30639				const { a, b, c } = _triangle;
30640				a.fromBufferAttribute( positionAttr, indexArr[ 0 ] );
30641				b.fromBufferAttribute( positionAttr, indexArr[ 1 ] );
30642				c.fromBufferAttribute( positionAttr, indexArr[ 2 ] );
30643				_triangle.getNormal( _normal );
30644
30645				// create hashes for the edge from the vertices
30646				hashes[ 0 ] = `${ Math.round( a.x * precision ) },${ Math.round( a.y * precision ) },${ Math.round( a.z * precision ) }`;
30647				hashes[ 1 ] = `${ Math.round( b.x * precision ) },${ Math.round( b.y * precision ) },${ Math.round( b.z * precision ) }`;
30648				hashes[ 2 ] = `${ Math.round( c.x * precision ) },${ Math.round( c.y * precision ) },${ Math.round( c.z * precision ) }`;
30649
30650				// skip degenerate triangles
30651				if ( hashes[ 0 ] === hashes[ 1 ] || hashes[ 1 ] === hashes[ 2 ] || hashes[ 2 ] === hashes[ 0 ] ) {
30652
30653					continue;
30654
30655				}
30656
30657				// iterate over every edge
30658				for ( let j = 0; j < 3; j ++ ) {
30659
30660					// get the first and next vertex making up the edge
30661					const jNext = ( j + 1 ) % 3;
30662					const vecHash0 = hashes[ j ];
30663					const vecHash1 = hashes[ jNext ];
30664					const v0 = _triangle[ vertKeys[ j ] ];
30665					const v1 = _triangle[ vertKeys[ jNext ] ];
30666
30667					const hash = `${ vecHash0 }_${ vecHash1 }`;
30668					const reverseHash = `${ vecHash1 }_${ vecHash0 }`;
30669
30670					if ( reverseHash in edgeData && edgeData[ reverseHash ] ) {
30671
30672						// if we found a sibling edge add it into the vertex array if
30673						// it meets the angle threshold and delete the edge from the map.
30674						if ( _normal.dot( edgeData[ reverseHash ].normal ) <= thresholdDot ) {
30675
30676							vertices.push( v0.x, v0.y, v0.z );
30677							vertices.push( v1.x, v1.y, v1.z );
30678
30679						}
30680
30681						edgeData[ reverseHash ] = null;
30682
30683					} else if ( ! ( hash in edgeData ) ) {
30684
30685						// if we've already got an edge here then skip adding a new one
30686						edgeData[ hash ] = {
30687
30688							index0: indexArr[ j ],
30689							index1: indexArr[ jNext ],
30690							normal: _normal.clone(),
30691
30692						};
30693
30694					}
30695
30696				}
30697
30698			}
30699
30700			// iterate over all remaining, unmatched edges and add them to the vertex array
30701			for ( const key in edgeData ) {
30702
30703				if ( edgeData[ key ] ) {
30704
30705					const { index0, index1 } = edgeData[ key ];
30706					_v0.fromBufferAttribute( positionAttr, index0 );
30707					_v1$1.fromBufferAttribute( positionAttr, index1 );
30708
30709					vertices.push( _v0.x, _v0.y, _v0.z );
30710					vertices.push( _v1$1.x, _v1$1.y, _v1$1.z );
30711
30712				}
30713
30714			}
30715
30716			this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
30717
30718		}
30719
30720	}
30721
30722	copy( source ) {
30723
30724		super.copy( source );
30725
30726		this.parameters = Object.assign( {}, source.parameters );
30727
30728		return this;
30729
30730	}
30731
30732}
30733
30734/**
30735 * An abstract base class for creating an analytic curve object that contains methods
30736 * for interpolation.
30737 *
30738 * @abstract
30739 */
30740class Curve {
30741
30742	/**
30743	 * Constructs a new curve.
30744	 */
30745	constructor() {
30746
30747		/**
30748		 * The type property is used for detecting the object type
30749		 * in context of serialization/deserialization.
30750		 *
30751		 * @type {string}
30752		 * @readonly
30753		 */
30754		this.type = 'Curve';
30755
30756		/**
30757		 * This value determines the amount of divisions when calculating the
30758		 * cumulative segment lengths of a curve via {@link Curve#getLengths}. To ensure
30759		 * precision when using methods like {@link Curve#getSpacedPoints}, it is
30760		 * recommended to increase the value of this property if the curve is very large.
30761		 *
30762		 * @type {number}
30763		 * @default 200
30764		 */
30765		this.arcLengthDivisions = 200;
30766
30767		/**
30768		 * Must be set to `true` if the curve parameters have changed.
30769		 *
30770		 * @type {boolean}
30771		 * @default false
30772		 */
30773		this.needsUpdate = false;
30774
30775		/**
30776		 * An internal cache that holds precomputed curve length values.
30777		 *
30778		 * @private
30779		 * @type {?Array<number>}
30780		 * @default null
30781		 */
30782		this.cacheArcLengths = null;
30783
30784	}
30785
30786	/**
30787	 * This method returns a vector in 2D or 3D space (depending on the curve definition)
30788	 * for the given interpolation factor.
30789	 *
30790	 * @abstract
30791	 * @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
30792	 * @param {(Vector2|Vector3)} [optionalTarget] - The optional target vector the result is written to.
30793	 * @return {(Vector2|Vector3)} The position on the curve. It can be a 2D or 3D vector depending on the curve definition.
30794	 */
30795	getPoint( /* t, optionalTarget */ ) {
30796
30797		warn( 'Curve: .getPoint() not implemented.' );
30798
30799	}
30800
30801	/**
30802	 * This method returns a vector in 2D or 3D space (depending on the curve definition)
30803	 * for the given interpolation factor. Unlike {@link Curve#getPoint}, this method honors the length
30804	 * of the curve which equidistant samples.
30805	 *
30806	 * @param {number} u - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
30807	 * @param {(Vector2|Vector3)} [optionalTarget] - The optional target vector the result is written to.
30808	 * @return {(Vector2|Vector3)} The position on the curve. It can be a 2D or 3D vector depending on the curve definition.
30809	 */
30810	getPointAt( u, optionalTarget ) {
30811
30812		const t = this.getUtoTmapping( u );
30813		return this.getPoint( t, optionalTarget );
30814
30815	}
30816
30817	/**
30818	 * This method samples the curve via {@link Curve#getPoint} and returns an array of points representing
30819	 * the curve shape.
30820	 *
30821	 * @param {number} [divisions=5] - The number of divisions.
30822	 * @return {Array<(Vector2|Vector3)>} An array holding the sampled curve values. The number of points is `divisions + 1`.
30823	 */
30824	getPoints( divisions = 5 ) {
30825
30826		const points = [];
30827
30828		for ( let d = 0; d <= divisions; d ++ ) {
30829
30830			points.push( this.getPoint( d / divisions ) );
30831
30832		}
30833
30834		return points;
30835
30836	}
30837
30838	// Get sequence of points using getPointAt( u )
30839
30840	/**
30841	 * This method samples the curve via {@link Curve#getPointAt} and returns an array of points representing
30842	 * the curve shape. Unlike {@link Curve#getPoints}, this method returns equi-spaced points across the entire
30843	 * curve.
30844	 *
30845	 * @param {number} [divisions=5] - The number of divisions.
30846	 * @return {Array<(Vector2|Vector3)>} An array holding the sampled curve values. The number of points is `divisions + 1`.
30847	 */
30848	getSpacedPoints( divisions = 5 ) {
30849
30850		const points = [];
30851
30852		for ( let d = 0; d <= divisions; d ++ ) {
30853
30854			points.push( this.getPointAt( d / divisions ) );
30855
30856		}
30857
30858		return points;
30859
30860	}
30861
30862	/**
30863	 * Returns the total arc length of the curve.
30864	 *
30865	 * @return {number} The length of the curve.
30866	 */
30867	getLength() {
30868
30869		const lengths = this.getLengths();
30870		return lengths[ lengths.length - 1 ];
30871
30872	}
30873
30874	/**
30875	 * Returns an array of cumulative segment lengths of the curve.
30876	 *
30877	 * @param {number} [divisions=this.arcLengthDivisions] - The number of divisions.
30878	 * @return {Array<number>} An array holding the cumulative segment lengths.
30879	 */
30880	getLengths( divisions = this.arcLengthDivisions ) {
30881
30882		if ( this.cacheArcLengths &&
30883			( this.cacheArcLengths.length === divisions + 1 ) &&
30884			! this.needsUpdate ) {
30885
30886			return this.cacheArcLengths;
30887
30888		}
30889
30890		this.needsUpdate = false;
30891
30892		const cache = [];
30893		let current, last = this.getPoint( 0 );
30894		let sum = 0;
30895
30896		cache.push( 0 );
30897
30898		for ( let p = 1; p <= divisions; p ++ ) {
30899
30900			current = this.getPoint( p / divisions );
30901			sum += current.distanceTo( last );
30902			cache.push( sum );
30903			last = current;
30904
30905		}
30906
30907		this.cacheArcLengths = cache;
30908
30909		return cache; // { sums: cache, sum: sum }; Sum is in the last element.
30910
30911	}
30912
30913	/**
30914	 * Update the cumulative segment distance cache. The method must be called
30915	 * every time curve parameters are changed. If an updated curve is part of a
30916	 * composed curve like {@link CurvePath}, this method must be called on the
30917	 * composed curve, too.
30918	 */
30919	updateArcLengths() {
30920
30921		this.needsUpdate = true;
30922		this.getLengths();
30923
30924	}
30925
30926	/**
30927	 * Given an interpolation factor in the range `[0,1]`, this method returns an updated
30928	 * interpolation factor in the same range that can be ued to sample equidistant points
30929	 * from a curve.
30930	 *
30931	 * @param {number} u - The interpolation factor.
30932	 * @param {?number} distance - An optional distance on the curve.
30933	 * @return {number} The updated interpolation factor.
30934	 */
30935	getUtoTmapping( u, distance = null ) {
30936
30937		const arcLengths = this.getLengths();
30938
30939		let i = 0;
30940		const il = arcLengths.length;
30941
30942		let targetArcLength; // The targeted u distance value to get
30943
30944		if ( distance ) {
30945
30946			targetArcLength = distance;
30947
30948		} else {
30949
30950			targetArcLength = u * arcLengths[ il - 1 ];
30951
30952		}
30953
30954		// binary search for the index with largest value smaller than target u distance
30955
30956		let low = 0, high = il - 1, comparison;
30957
30958		while ( low <= high ) {
30959
30960			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
30961
30962			comparison = arcLengths[ i ] - targetArcLength;
30963
30964			if ( comparison < 0 ) {
30965
30966				low = i + 1;
30967
30968			} else if ( comparison > 0 ) {
30969
30970				high = i - 1;
30971
30972			} else {
30973
30974				high = i;
30975				break;
30976
30977				// DONE
30978
30979			}
30980
30981		}
30982
30983		i = high;
30984
30985		if ( arcLengths[ i ] === targetArcLength ) {
30986
30987			return i / ( il - 1 );
30988
30989		}
30990
30991		// we could get finer grain at lengths, or use simple interpolation between two points
30992
30993		const lengthBefore = arcLengths[ i ];
30994		const lengthAfter = arcLengths[ i + 1 ];
30995
30996		const segmentLength = lengthAfter - lengthBefore;
30997
30998		// determine where we are between the 'before' and 'after' points
30999
31000		const segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength;
31001
31002		// add that fractional amount to t
31003
31004		const t = ( i + segmentFraction ) / ( il - 1 );
31005
31006		return t;
31007
31008	}
31009
31010	/**
31011	 * Returns a unit vector tangent for the given interpolation factor.
31012	 * If the derived curve does not implement its tangent derivation,
31013	 * two points a small delta apart will be used to find its gradient
31014	 * which seems to give a reasonable approximation.
31015	 *
31016	 * @param {number} t - The interpolation factor.
31017	 * @param {(Vector2|Vector3)} [optionalTarget] - The optional target vector the result is written to.
31018	 * @return {(Vector2|Vector3)} The tangent vector.
31019	 */
31020	getTangent( t, optionalTarget ) {
31021
31022		const delta = 0.0001;
31023		let t1 = t - delta;
31024		let t2 = t + delta;
31025
31026		// Capping in case of danger
31027
31028		if ( t1 < 0 ) t1 = 0;
31029		if ( t2 > 1 ) t2 = 1;
31030
31031		const pt1 = this.getPoint( t1 );
31032		const pt2 = this.getPoint( t2 );
31033
31034		const tangent = optionalTarget || ( ( pt1.isVector2 ) ? new Vector2() : new Vector3() );
31035
31036		tangent.copy( pt2 ).sub( pt1 ).normalize();
31037
31038		return tangent;
31039
31040	}
31041
31042	/**
31043	 * Same as {@link Curve#getTangent} but with equidistant samples.
31044	 *
31045	 * @param {number} u - The interpolation factor.
31046	 * @param {(Vector2|Vector3)} [optionalTarget] - The optional target vector the result is written to.
31047	 * @return {(Vector2|Vector3)} The tangent vector.
31048	 * @see {@link Curve#getPointAt}
31049	 */
31050	getTangentAt( u, optionalTarget ) {
31051
31052		const t = this.getUtoTmapping( u );
31053		return this.getTangent( t, optionalTarget );
31054
31055	}
31056
31057	/**
31058	 * Generates the Frenet Frames. Requires a curve definition in 3D space. Used
31059	 * in geometries like {@link TubeGeometry} or {@link ExtrudeGeometry}.
31060	 *
31061	 * @param {number} segments - The number of segments.
31062	 * @param {boolean} [closed=false] - Whether the curve is closed or not.
31063	 * @return {{tangents: Array<Vector3>, normals: Array<Vector3>, binormals: Array<Vector3>}} The Frenet Frames.
31064	 */
31065	computeFrenetFrames( segments, closed = false ) {
31066
31067		// see http://www.cs.indiana.edu/pub/techreports/TR425.pdf
31068
31069		const normal = new Vector3();
31070
31071		const tangents = [];
31072		const normals = [];
31073		const binormals = [];
31074
31075		const vec = new Vector3();
31076		const mat = new Matrix4();
31077
31078		// compute the tangent vectors for each segment on the curve
31079
31080		for ( let i = 0; i <= segments; i ++ ) {
31081
31082			const u = i / segments;
31083
31084			tangents[ i ] = this.getTangentAt( u, new Vector3() );
31085
31086		}
31087
31088		// select an initial normal vector perpendicular to the first tangent vector,
31089		// and in the direction of the minimum tangent xyz component
31090
31091		normals[ 0 ] = new Vector3();
31092		binormals[ 0 ] = new Vector3();
31093		let min = Number.MAX_VALUE;
31094		const tx = Math.abs( tangents[ 0 ].x );
31095		const ty = Math.abs( tangents[ 0 ].y );
31096		const tz = Math.abs( tangents[ 0 ].z );
31097
31098		if ( tx <= min ) {
31099
31100			min = tx;
31101			normal.set( 1, 0, 0 );
31102
31103		}
31104
31105		if ( ty <= min ) {
31106
31107			min = ty;
31108			normal.set( 0, 1, 0 );
31109
31110		}
31111
31112		if ( tz <= min ) {
31113
31114			normal.set( 0, 0, 1 );
31115
31116		}
31117
31118		vec.crossVectors( tangents[ 0 ], normal ).normalize();
31119
31120		normals[ 0 ].crossVectors( tangents[ 0 ], vec );
31121		binormals[ 0 ].crossVectors( tangents[ 0 ], normals[ 0 ] );
31122
31123
31124		// compute the slowly-varying normal and binormal vectors for each segment on the curve
31125
31126		for ( let i = 1; i <= segments; i ++ ) {
31127
31128			normals[ i ] = normals[ i - 1 ].clone();
31129
31130			binormals[ i ] = binormals[ i - 1 ].clone();
31131
31132			vec.crossVectors( tangents[ i - 1 ], tangents[ i ] );
31133
31134			if ( vec.length() > Number.EPSILON ) {
31135
31136				vec.normalize();
31137
31138				const theta = Math.acos( clamp( tangents[ i - 1 ].dot( tangents[ i ] ), -1, 1 ) ); // clamp for floating pt errors
31139
31140				normals[ i ].applyMatrix4( mat.makeRotationAxis( vec, theta ) );
31141
31142			}
31143
31144			binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
31145
31146		}
31147
31148		// if the curve is closed, postprocess the vectors so the first and last normal vectors are the same
31149
31150		if ( closed === true ) {
31151
31152			let theta = Math.acos( clamp( normals[ 0 ].dot( normals[ segments ] ), -1, 1 ) );
31153			theta /= segments;
31154
31155			if ( tangents[ 0 ].dot( vec.crossVectors( normals[ 0 ], normals[ segments ] ) ) > 0 ) {
31156
31157				theta = - theta;
31158
31159			}
31160
31161			for ( let i = 1; i <= segments; i ++ ) {
31162
31163				// twist a little...
31164				normals[ i ].applyMatrix4( mat.makeRotationAxis( tangents[ i ], theta * i ) );
31165				binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
31166
31167			}
31168
31169		}
31170
31171		return {
31172			tangents: tangents,
31173			normals: normals,
31174			binormals: binormals
31175		};
31176
31177	}
31178
31179	/**
31180	 * Returns a new curve with copied values from this instance.
31181	 *
31182	 * @return {Curve} A clone of this instance.
31183	 */
31184	clone() {
31185
31186		return new this.constructor().copy( this );
31187
31188	}
31189
31190	/**
31191	 * Copies the values of the given curve to this instance.
31192	 *
31193	 * @param {Curve} source - The curve to copy.
31194	 * @return {Curve} A reference to this curve.
31195	 */
31196	copy( source ) {
31197
31198		this.arcLengthDivisions = source.arcLengthDivisions;
31199
31200		return this;
31201
31202	}
31203
31204	/**
31205	 * Serializes the curve into JSON.
31206	 *
31207	 * @return {Object} A JSON object representing the serialized curve.
31208	 * @see {@link ObjectLoader#parse}
31209	 */
31210	toJSON() {
31211
31212		const data = {
31213			metadata: {
31214				version: 4.7,
31215				type: 'Curve',
31216				generator: 'Curve.toJSON'
31217			}
31218		};
31219
31220		data.arcLengthDivisions = this.arcLengthDivisions;
31221		data.type = this.type;
31222
31223		return data;
31224
31225	}
31226
31227	/**
31228	 * Deserializes the curve from the given JSON.
31229	 *
31230	 * @param {Object} json - The JSON holding the serialized curve.
31231	 * @return {Curve} A reference to this curve.
31232	 */
31233	fromJSON( json ) {
31234
31235		this.arcLengthDivisions = json.arcLengthDivisions;
31236
31237		return this;
31238
31239	}
31240
31241}
31242
31243/**
31244 * A curve representing an ellipse.
31245 *
31246 * ```js
31247 * const curve = new THREE.EllipseCurve(
31248 * 	0, 0,
31249 * 	10, 10,
31250 * 	0, 2 * Math.PI,
31251 * 	false,
31252 * 	0
31253 * );
31254 *
31255 * const points = curve.getPoints( 50 );
31256 * const geometry = new THREE.BufferGeometry().setFromPoints( points );
31257 *
31258 * const material = new THREE.LineBasicMaterial( { color: 0xff0000 } );
31259 *
31260 * // Create the final object to add to the scene
31261 * const ellipse = new THREE.Line( geometry, material );
31262 * ```
31263 *
31264 * @augments Curve
31265 */
31266class EllipseCurve extends Curve {
31267
31268	/**
31269	 * Constructs a new ellipse curve.
31270	 *
31271	 * @param {number} [aX=0] - The X center of the ellipse.
31272	 * @param {number} [aY=0] - The Y center of the ellipse.
31273	 * @param {number} [xRadius=1] - The radius of the ellipse in the x direction.
31274	 * @param {number} [yRadius=1] - The radius of the ellipse in the y direction.
31275	 * @param {number} [aStartAngle=0] - The start angle of the curve in radians starting from the positive X axis.
31276	 * @param {number} [aEndAngle=Math.PI*2] - The end angle of the curve in radians starting from the positive X axis.
31277	 * @param {boolean} [aClockwise=false] - Whether the ellipse is drawn clockwise or not.
31278	 * @param {number} [aRotation=0] - The rotation angle of the ellipse in radians, counterclockwise from the positive X axis.
31279	 */
31280	constructor( aX = 0, aY = 0, xRadius = 1, yRadius = 1, aStartAngle = 0, aEndAngle = Math.PI * 2, aClockwise = false, aRotation = 0 ) {
31281
31282		super();
31283
31284		/**
31285		 * This flag can be used for type testing.
31286		 *
31287		 * @type {boolean}
31288		 * @readonly
31289		 * @default true
31290		 */
31291		this.isEllipseCurve = true;
31292
31293		this.type = 'EllipseCurve';
31294
31295		/**
31296		 * The X center of the ellipse.
31297		 *
31298		 * @type {number}
31299		 * @default 0
31300		 */
31301		this.aX = aX;
31302
31303		/**
31304		 * The Y center of the ellipse.
31305		 *
31306		 * @type {number}
31307		 * @default 0
31308		 */
31309		this.aY = aY;
31310
31311		/**
31312		 * The radius of the ellipse in the x direction.
31313		 * Setting the this value equal to the {@link EllipseCurve#yRadius} will result in a circle.
31314		 *
31315		 * @type {number}
31316		 * @default 1
31317		 */
31318		this.xRadius = xRadius;
31319
31320		/**
31321		 * The radius of the ellipse in the y direction.
31322		 * Setting the this value equal to the {@link EllipseCurve#xRadius} will result in a circle.
31323		 *
31324		 * @type {number}
31325		 * @default 1
31326		 */
31327		this.yRadius = yRadius;
31328
31329		/**
31330		 * The start angle of the curve in radians starting from the positive X axis.
31331		 *
31332		 * @type {number}
31333		 * @default 0
31334		 */
31335		this.aStartAngle = aStartAngle;
31336
31337		/**
31338		 * The end angle of the curve in radians starting from the positive X axis.
31339		 *
31340		 * @type {number}
31341		 * @default Math.PI*2
31342		 */
31343		this.aEndAngle = aEndAngle;
31344
31345		/**
31346		 * Whether the ellipse is drawn clockwise or not.
31347		 *
31348		 * @type {boolean}
31349		 * @default false
31350		 */
31351		this.aClockwise = aClockwise;
31352
31353		/**
31354		 * The rotation angle of the ellipse in radians, counterclockwise from the positive X axis.
31355		 *
31356		 * @type {number}
31357		 * @default 0
31358		 */
31359		this.aRotation = aRotation;
31360
31361	}
31362
31363	/**
31364	 * Returns a point on the curve.
31365	 *
31366	 * @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
31367	 * @param {Vector2} [optionalTarget] - The optional target vector the result is written to.
31368	 * @return {Vector2} The position on the curve.
31369	 */
31370	getPoint( t, optionalTarget = new Vector2() ) {
31371
31372		const point = optionalTarget;
31373
31374		const twoPi = Math.PI * 2;
31375		let deltaAngle = this.aEndAngle - this.aStartAngle;
31376		const samePoints = Math.abs( deltaAngle ) < Number.EPSILON;
31377
31378		// ensures that deltaAngle is 0 .. 2 PI
31379		while ( deltaAngle < 0 ) deltaAngle += twoPi;
31380		while ( deltaAngle > twoPi ) deltaAngle -= twoPi;
31381
31382		if ( deltaAngle < Number.EPSILON ) {
31383
31384			if ( samePoints ) {
31385
31386				deltaAngle = 0;
31387
31388			} else {
31389
31390				deltaAngle = twoPi;
31391
31392			}
31393
31394		}
31395
31396		if ( this.aClockwise === true && ! samePoints ) {
31397
31398			if ( deltaAngle === twoPi ) {
31399
31400				deltaAngle = - twoPi;
31401
31402			} else {
31403
31404				deltaAngle = deltaAngle - twoPi;
31405
31406			}
31407
31408		}
31409
31410		const angle = this.aStartAngle + t * deltaAngle;
31411		let x = this.aX + this.xRadius * Math.cos( angle );
31412		let y = this.aY + this.yRadius * Math.sin( angle );
31413
31414		if ( this.aRotation !== 0 ) {
31415
31416			const cos = Math.cos( this.aRotation );
31417			const sin = Math.sin( this.aRotation );
31418
31419			const tx = x - this.aX;
31420			const ty = y - this.aY;
31421
31422			// Rotate the point about the center of the ellipse.
31423			x = tx * cos - ty * sin + this.aX;
31424			y = tx * sin + ty * cos + this.aY;
31425
31426		}
31427
31428		return point.set( x, y );
31429
31430	}
31431
31432	copy( source ) {
31433
31434		super.copy( source );
31435
31436		this.aX = source.aX;
31437		this.aY = source.aY;
31438
31439		this.xRadius = source.xRadius;
31440		this.yRadius = source.yRadius;
31441
31442		this.aStartAngle = source.aStartAngle;
31443		this.aEndAngle = source.aEndAngle;
31444
31445		this.aClockwise = source.aClockwise;
31446
31447		this.aRotation = source.aRotation;
31448
31449		return this;
31450
31451	}
31452
31453	toJSON() {
31454
31455		const data = super.toJSON();
31456
31457		data.aX = this.aX;
31458		data.aY = this.aY;
31459
31460		data.xRadius = this.xRadius;
31461		data.yRadius = this.yRadius;
31462
31463		data.aStartAngle = this.aStartAngle;
31464		data.aEndAngle = this.aEndAngle;
31465
31466		data.aClockwise = this.aClockwise;
31467
31468		data.aRotation = this.aRotation;
31469
31470		return data;
31471
31472	}
31473
31474	fromJSON( json ) {
31475
31476		super.fromJSON( json );
31477
31478		this.aX = json.aX;
31479		this.aY = json.aY;
31480
31481		this.xRadius = json.xRadius;
31482		this.yRadius = json.yRadius;
31483
31484		this.aStartAngle = json.aStartAngle;
31485		this.aEndAngle = json.aEndAngle;
31486
31487		this.aClockwise = json.aClockwise;
31488
31489		this.aRotation = json.aRotation;
31490
31491		return this;
31492
31493	}
31494
31495}
31496
31497/**
31498 * A curve representing an arc.
31499 *
31500 * @augments EllipseCurve
31501 */
31502class ArcCurve extends EllipseCurve {
31503
31504	/**
31505	 * Constructs a new arc curve.
31506	 *
31507	 * @param {number} [aX=0] - The X center of the ellipse.
31508	 * @param {number} [aY=0] - The Y center of the ellipse.
31509	 * @param {number} [aRadius=1] - The radius of the ellipse in the x direction.
31510	 * @param {number} [aStartAngle=0] - The start angle of the curve in radians starting from the positive X axis.
31511	 * @param {number} [aEndAngle=Math.PI*2] - The end angle of the curve in radians starting from the positive X axis.
31512	 * @param {boolean} [aClockwise=false] - Whether the ellipse is drawn clockwise or not.
31513	 */
31514	constructor( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
31515
31516		super( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
31517
31518		/**
31519		 * This flag can be used for type testing.
31520		 *
31521		 * @type {boolean}
31522		 * @readonly
31523		 * @default true
31524		 */
31525		this.isArcCurve = true;
31526
31527		this.type = 'ArcCurve';
31528
31529	}
31530
31531}
31532
31533function CubicPoly() {
31534
31535	/**
31536	 * Centripetal CatmullRom Curve - which is useful for avoiding
31537	* cusps and self-intersections in non-uniform catmull rom curves.
31538	* http://www.cemyuksel.com/research/catmullrom_param/catmullrom.pdf
31539	*
31540	* curve.type accepts centripetal(default), chordal and catmullrom
31541	* curve.tension is used for catmullrom which defaults to 0.5
31542	*/
31543
31544	/*
31545	Based on an optimized c++ solution in
31546	- http://stackoverflow.com/questions/9489736/catmull-rom-curve-with-no-cusps-and-no-self-intersections/
31547	- http://ideone.com/NoEbVM
31548
31549	This CubicPoly class could be used for reusing some variables and calculations,
31550	but for three.js curve use, it could be possible inlined and flatten into a single function call
31551	which can be placed in CurveUtils.
31552	*/
31553
31554	let c0 = 0, c1 = 0, c2 = 0, c3 = 0;
31555
31556	/*
31557	 * Compute coefficients for a cubic polynomial
31558	 *   p(s) = c0 + c1*s + c2*s^2 + c3*s^3
31559	 * such that
31560	 *   p(0) = x0, p(1) = x1
31561	 *  and
31562	 *   p'(0) = t0, p'(1) = t1.
31563	 */
31564	function init( x0, x1, t0, t1 ) {
31565
31566		c0 = x0;
31567		c1 = t0;
31568		c2 = -3 * x0 + 3 * x1 - 2 * t0 - t1;
31569		c3 = 2 * x0 - 2 * x1 + t0 + t1;
31570
31571	}
31572
31573	return {
31574
31575		initCatmullRom: function ( x0, x1, x2, x3, tension ) {
31576
31577			init( x1, x2, tension * ( x2 - x0 ), tension * ( x3 - x1 ) );
31578
31579		},
31580
31581		initNonuniformCatmullRom: function ( x0, x1, x2, x3, dt0, dt1, dt2 ) {
31582
31583			// compute tangents when parameterized in [t1,t2]
31584			let t1 = ( x1 - x0 ) / dt0 - ( x2 - x0 ) / ( dt0 + dt1 ) + ( x2 - x1 ) / dt1;
31585			let t2 = ( x2 - x1 ) / dt1 - ( x3 - x1 ) / ( dt1 + dt2 ) + ( x3 - x2 ) / dt2;
31586
31587			// rescale tangents for parametrization in [0,1]
31588			t1 *= dt1;
31589			t2 *= dt1;
31590
31591			init( x1, x2, t1, t2 );
31592
31593		},
31594
31595		calc: function ( t ) {
31596
31597			const t2 = t * t;
31598			const t3 = t2 * t;
31599			return c0 + c1 * t + c2 * t2 + c3 * t3;
31600
31601		}
31602
31603	};
31604
31605}
31606
31607//
31608
31609const tmp = /*@__PURE__*/ new Vector3();
31610const tmp2 = /*@__PURE__*/ new Vector3();
31611const px = /*@__PURE__*/ new CubicPoly();
31612const py = /*@__PURE__*/ new CubicPoly();
31613const pz = /*@__PURE__*/ new CubicPoly();
31614
31615/**
31616 * A curve representing a Catmull-Rom spline.
31617 *
31618 * ```js
31619 * //Create a closed wavey loop
31620 * const curve = new THREE.CatmullRomCurve3( [
31621 * 	new THREE.Vector3( -10, 0, 10 ),
31622 * 	new THREE.Vector3( -5, 5, 5 ),
31623 * 	new THREE.Vector3( 0, 0, 0 ),
31624 * 	new THREE.Vector3( 5, -5, 5 ),
31625 * 	new THREE.Vector3( 10, 0, 10 )
31626 * ] );
31627 *
31628 * const points = curve.getPoints( 50 );
31629 * const geometry = new THREE.BufferGeometry().setFromPoints( points );
31630 *
31631 * const material = new THREE.LineBasicMaterial( { color: 0xff0000 } );
31632 *
31633 * // Create the final object to add to the scene
31634 * const curveObject = new THREE.Line( geometry, material );
31635 * ```
31636 *
31637 * @augments Curve
31638 */
31639class CatmullRomCurve3 extends Curve {
31640
31641	/**
31642	 * Constructs a new Catmull-Rom curve.
31643	 *
31644	 * @param {Array<Vector3>} [points] - An array of 3D points defining the curve.
31645	 * @param {boolean} [closed=false] - Whether the curve is closed or not.
31646	 * @param {('centripetal'|'chordal'|'catmullrom')} [curveType='centripetal'] - The curve type.
31647	 * @param {number} [tension=0.5] - Tension of the curve.
31648	 */
31649	constructor( points = [], closed = false, curveType = 'centripetal', tension = 0.5 ) {
31650
31651		super();
31652
31653		/**
31654		 * This flag can be used for type testing.
31655		 *
31656		 * @type {boolean}
31657		 * @readonly
31658		 * @default true
31659		 */
31660		this.isCatmullRomCurve3 = true;
31661
31662		this.type = 'CatmullRomCurve3';
31663
31664		/**
31665		 * An array of 3D points defining the curve.
31666		 *
31667		 * @type {Array<Vector3>}
31668		 */
31669		this.points = points;
31670
31671		/**
31672		 * Whether the curve is closed or not.
31673		 *
31674		 * @type {boolean}
31675		 * @default false
31676		 */
31677		this.closed = closed;
31678
31679		/**
31680		 * The curve type.
31681		 *
31682		 * @type {('centripetal'|'chordal'|'catmullrom')}
31683		 * @default 'centripetal'
31684		 */
31685		this.curveType = curveType;
31686
31687		/**
31688		 * Tension of the curve.
31689		 *
31690		 * @type {number}
31691		 * @default 0.5
31692		 */
31693		this.tension = tension;
31694
31695	}
31696
31697	/**
31698	 * Returns a point on the curve.
31699	 *
31700	 * @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
31701	 * @param {Vector3} [optionalTarget] - The optional target vector the result is written to.
31702	 * @return {Vector3} The position on the curve.
31703	 */
31704	getPoint( t, optionalTarget = new Vector3() ) {
31705
31706		const point = optionalTarget;
31707
31708		const points = this.points;
31709		const l = points.length;
31710
31711		const p = ( l - ( this.closed ? 0 : 1 ) ) * t;
31712		let intPoint = Math.floor( p );
31713		let weight = p - intPoint;
31714
31715		if ( this.closed ) {
31716
31717			intPoint += intPoint > 0 ? 0 : ( Math.floor( Math.abs( intPoint ) / l ) + 1 ) * l;
31718
31719		} else if ( weight === 0 && intPoint === l - 1 ) {
31720
31721			intPoint = l - 2;
31722			weight = 1;
31723
31724		}
31725
31726		let p0, p3; // 4 points (p1 & p2 defined below)
31727
31728		if ( this.closed || intPoint > 0 ) {
31729
31730			p0 = points[ ( intPoint - 1 ) % l ];
31731
31732		} else {
31733
31734			// extrapolate first point
31735			tmp2.subVectors( points[ 0 ], points[ 1 ] ).add( points[ 0 ] );
31736			p0 = tmp2;
31737
31738		}
31739
31740		const p1 = points[ intPoint % l ];
31741		const p2 = points[ ( intPoint + 1 ) % l ];
31742
31743		if ( this.closed || intPoint + 2 < l ) {
31744
31745			p3 = points[ ( intPoint + 2 ) % l ];
31746
31747		} else {
31748
31749			// extrapolate last point
31750			tmp.subVectors( points[ l - 1 ], points[ l - 2 ] ).add( points[ l - 1 ] );
31751			p3 = tmp;
31752
31753		}
31754
31755		if ( this.curveType === 'centripetal' || this.curveType === 'chordal' ) {
31756
31757			// init Centripetal / Chordal Catmull-Rom
31758			const pow = this.curveType === 'chordal' ? 0.5 : 0.25;
31759			let dt0 = Math.pow( p0.distanceToSquared( p1 ), pow );
31760			let dt1 = Math.pow( p1.distanceToSquared( p2 ), pow );
31761			let dt2 = Math.pow( p2.distanceToSquared( p3 ), pow );
31762
31763			// safety check for repeated points
31764			if ( dt1 < 1e-4 ) dt1 = 1.0;
31765			if ( dt0 < 1e-4 ) dt0 = dt1;
31766			if ( dt2 < 1e-4 ) dt2 = dt1;
31767
31768			px.initNonuniformCatmullRom( p0.x, p1.x, p2.x, p3.x, dt0, dt1, dt2 );
31769			py.initNonuniformCatmullRom( p0.y, p1.y, p2.y, p3.y, dt0, dt1, dt2 );
31770			pz.initNonuniformCatmullRom( p0.z, p1.z, p2.z, p3.z, dt0, dt1, dt2 );
31771
31772		} else if ( this.curveType === 'catmullrom' ) {
31773
31774			px.initCatmullRom( p0.x, p1.x, p2.x, p3.x, this.tension );
31775			py.initCatmullRom( p0.y, p1.y, p2.y, p3.y, this.tension );
31776			pz.initCatmullRom( p0.z, p1.z, p2.z, p3.z, this.tension );
31777
31778		}
31779
31780		point.set(
31781			px.calc( weight ),
31782			py.calc( weight ),
31783			pz.calc( weight )
31784		);
31785
31786		return point;
31787
31788	}
31789
31790	copy( source ) {
31791
31792		super.copy( source );
31793
31794		this.points = [];
31795
31796		for ( let i = 0, l = source.points.length; i < l; i ++ ) {
31797
31798			const point = source.points[ i ];
31799
31800			this.points.push( point.clone() );
31801
31802		}
31803
31804		this.closed = source.closed;
31805		this.curveType = source.curveType;
31806		this.tension = source.tension;
31807
31808		return this;
31809
31810	}
31811
31812	toJSON() {
31813
31814		const data = super.toJSON();
31815
31816		data.points = [];
31817
31818		for ( let i = 0, l = this.points.length; i < l; i ++ ) {
31819
31820			const point = this.points[ i ];
31821			data.points.push( point.toArray() );
31822
31823		}
31824
31825		data.closed = this.closed;
31826		data.curveType = this.curveType;
31827		data.tension = this.tension;
31828
31829		return data;
31830
31831	}
31832
31833	fromJSON( json ) {
31834
31835		super.fromJSON( json );
31836
31837		this.points = [];
31838
31839		for ( let i = 0, l = json.points.length; i < l; i ++ ) {
31840
31841			const point = json.points[ i ];
31842			this.points.push( new Vector3().fromArray( point ) );
31843
31844		}
31845
31846		this.closed = json.closed;
31847		this.curveType = json.curveType;
31848		this.tension = json.tension;
31849
31850		return this;
31851
31852	}
31853
31854}
31855
31856/**
31857 * Interpolations contains spline and Bézier functions internally used by concrete curve classes.
31858 *
31859 * Bezier Curves formulas obtained from: https://en.wikipedia.org/wiki/B%C3%A9zier_curve
31860 *
31861 * @module Interpolations
31862 */
31863
31864/**
31865 * Computes a point on a Catmull-Rom spline.
31866 *
31867 * @param {number} t - The interpolation factor.
31868 * @param {number} p0 - The first control point.
31869 * @param {number} p1 - The second control point.
31870 * @param {number} p2 - The third control point.
31871 * @param {number} p3 - The fourth control point.
31872 * @return {number} The calculated point on a Catmull-Rom spline.
31873 */
31874function CatmullRom( t, p0, p1, p2, p3 ) {
31875
31876	const v0 = ( p2 - p0 ) * 0.5;
31877	const v1 = ( p3 - p1 ) * 0.5;
31878	const t2 = t * t;
31879	const t3 = t * t2;
31880	return ( 2 * p1 - 2 * p2 + v0 + v1 ) * t3 + ( -3 * p1 + 3 * p2 - 2 * v0 - v1 ) * t2 + v0 * t + p1;
31881
31882}
31883
31884//
31885
31886function QuadraticBezierP0( t, p ) {
31887
31888	const k = 1 - t;
31889	return k * k * p;
31890
31891}
31892
31893function QuadraticBezierP1( t, p ) {
31894
31895	return 2 * ( 1 - t ) * t * p;
31896
31897}
31898
31899function QuadraticBezierP2( t, p ) {
31900
31901	return t * t * p;
31902
31903}
31904
31905/**
31906 * Computes a point on a Quadratic Bezier curve.
31907 *
31908 * @param {number} t - The interpolation factor.
31909 * @param {number} p0 - The first control point.
31910 * @param {number} p1 - The second control point.
31911 * @param {number} p2 - The third control point.
31912 * @return {number} The calculated point on a Quadratic Bezier curve.
31913 */
31914function QuadraticBezier( t, p0, p1, p2 ) {
31915
31916	return QuadraticBezierP0( t, p0 ) + QuadraticBezierP1( t, p1 ) +
31917		QuadraticBezierP2( t, p2 );
31918
31919}
31920
31921//
31922
31923function CubicBezierP0( t, p ) {
31924
31925	const k = 1 - t;
31926	return k * k * k * p;
31927
31928}
31929
31930function CubicBezierP1( t, p ) {
31931
31932	const k = 1 - t;
31933	return 3 * k * k * t * p;
31934
31935}
31936
31937function CubicBezierP2( t, p ) {
31938
31939	return 3 * ( 1 - t ) * t * t * p;
31940
31941}
31942
31943function CubicBezierP3( t, p ) {
31944
31945	return t * t * t * p;
31946
31947}
31948
31949/**
31950 * Computes a point on a Cubic Bezier curve.
31951 *
31952 * @param {number} t - The interpolation factor.
31953 * @param {number} p0 - The first control point.
31954 * @param {number} p1 - The second control point.
31955 * @param {number} p2 - The third control point.
31956 * @param {number} p3 - The fourth control point.
31957 * @return {number} The calculated point on a Cubic Bezier curve.
31958 */
31959function CubicBezier( t, p0, p1, p2, p3 ) {
31960
31961	return CubicBezierP0( t, p0 ) + CubicBezierP1( t, p1 ) + CubicBezierP2( t, p2 ) +
31962		CubicBezierP3( t, p3 );
31963
31964}
31965
31966/**
31967 * A curve representing a 2D Cubic Bezier curve.
31968 *
31969 * ```js
31970 * const curve = new THREE.CubicBezierCurve(
31971 * 	new THREE.Vector2( - 0, 0 ),
31972 * 	new THREE.Vector2( - 5, 15 ),
31973 * 	new THREE.Vector2( 20, 15 ),
31974 * 	new THREE.Vector2( 10, 0 )
31975 * );
31976 *
31977 * const points = curve.getPoints( 50 );
31978 * const geometry = new THREE.BufferGeometry().setFromPoints( points );
31979 *
31980 * const material = new THREE.LineBasicMaterial( { color: 0xff0000 } );
31981 *
31982 * // Create the final object to add to the scene
31983 * const curveObject = new THREE.Line( geometry, material );
31984 * ```
31985 *
31986 * @augments Curve
31987 */
31988class CubicBezierCurve extends Curve {
31989
31990	/**
31991	 * Constructs a new Cubic Bezier curve.
31992	 *
31993	 * @param {Vector2} [v0] - The start point.
31994	 * @param {Vector2} [v1] - The first control point.
31995	 * @param {Vector2} [v2] - The second control point.
31996	 * @param {Vector2} [v3] - The end point.
31997	 */
31998	constructor( v0 = new Vector2(), v1 = new Vector2(), v2 = new Vector2(), v3 = new Vector2() ) {
31999
32000		super();
32001
32002		/**
32003		 * This flag can be used for type testing.
32004		 *
32005		 * @type {boolean}
32006		 * @readonly
32007		 * @default true
32008		 */
32009		this.isCubicBezierCurve = true;
32010
32011		this.type = 'CubicBezierCurve';
32012
32013		/**
32014		 * The start point.
32015		 *
32016		 * @type {Vector2}
32017		 */
32018		this.v0 = v0;
32019
32020		/**
32021		 * The first control point.
32022		 *
32023		 * @type {Vector2}
32024		 */
32025		this.v1 = v1;
32026
32027		/**
32028		 * The second control point.
32029		 *
32030		 * @type {Vector2}
32031		 */
32032		this.v2 = v2;
32033
32034		/**
32035		 * The end point.
32036		 *
32037		 * @type {Vector2}
32038		 */
32039		this.v3 = v3;
32040
32041	}
32042
32043	/**
32044	 * Returns a point on the curve.
32045	 *
32046	 * @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
32047	 * @param {Vector2} [optionalTarget] - The optional target vector the result is written to.
32048	 * @return {Vector2} The position on the curve.
32049	 */
32050	getPoint( t, optionalTarget = new Vector2() ) {
32051
32052		const point = optionalTarget;
32053
32054		const v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3;
32055
32056		point.set(
32057			CubicBezier( t, v0.x, v1.x, v2.x, v3.x ),
32058			CubicBezier( t, v0.y, v1.y, v2.y, v3.y )
32059		);
32060
32061		return point;
32062
32063	}
32064
32065	copy( source ) {
32066
32067		super.copy( source );
32068
32069		this.v0.copy( source.v0 );
32070		this.v1.copy( source.v1 );
32071		this.v2.copy( source.v2 );
32072		this.v3.copy( source.v3 );
32073
32074		return this;
32075
32076	}
32077
32078	toJSON() {
32079
32080		const data = super.toJSON();
32081
32082		data.v0 = this.v0.toArray();
32083		data.v1 = this.v1.toArray();
32084		data.v2 = this.v2.toArray();
32085		data.v3 = this.v3.toArray();
32086
32087		return data;
32088
32089	}
32090
32091	fromJSON( json ) {
32092
32093		super.fromJSON( json );
32094
32095		this.v0.fromArray( json.v0 );
32096		this.v1.fromArray( json.v1 );
32097		this.v2.fromArray( json.v2 );
32098		this.v3.fromArray( json.v3 );
32099
32100		return this;
32101
32102	}
32103
32104}
32105
32106/**
32107 * A curve representing a 3D Cubic Bezier curve.
32108 *
32109 * @augments Curve
32110 */
32111class CubicBezierCurve3 extends Curve {
32112
32113	/**
32114	 * Constructs a new Cubic Bezier curve.
32115	 *
32116	 * @param {Vector3} [v0] - The start point.
32117	 * @param {Vector3} [v1] - The first control point.
32118	 * @param {Vector3} [v2] - The second control point.
32119	 * @param {Vector3} [v3] - The end point.
32120	 */
32121	constructor( v0 = new Vector3(), v1 = new Vector3(), v2 = new Vector3(), v3 = new Vector3() ) {
32122
32123		super();
32124
32125		/**
32126		 * This flag can be used for type testing.
32127		 *
32128		 * @type {boolean}
32129		 * @readonly
32130		 * @default true
32131		 */
32132		this.isCubicBezierCurve3 = true;
32133
32134		this.type = 'CubicBezierCurve3';
32135
32136		/**
32137		 * The start point.
32138		 *
32139		 * @type {Vector3}
32140		 */
32141		this.v0 = v0;
32142
32143		/**
32144		 * The first control point.
32145		 *
32146		 * @type {Vector3}
32147		 */
32148		this.v1 = v1;
32149
32150		/**
32151		 * The second control point.
32152		 *
32153		 * @type {Vector3}
32154		 */
32155		this.v2 = v2;
32156
32157		/**
32158		 * The end point.
32159		 *
32160		 * @type {Vector3}
32161		 */
32162		this.v3 = v3;
32163
32164	}
32165
32166	/**
32167	 * Returns a point on the curve.
32168	 *
32169	 * @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
32170	 * @param {Vector3} [optionalTarget] - The optional target vector the result is written to.
32171	 * @return {Vector3} The position on the curve.
32172	 */
32173	getPoint( t, optionalTarget = new Vector3() ) {
32174
32175		const point = optionalTarget;
32176
32177		const v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3;
32178
32179		point.set(
32180			CubicBezier( t, v0.x, v1.x, v2.x, v3.x ),
32181			CubicBezier( t, v0.y, v1.y, v2.y, v3.y ),
32182			CubicBezier( t, v0.z, v1.z, v2.z, v3.z )
32183		);
32184
32185		return point;
32186
32187	}
32188
32189	copy( source ) {
32190
32191		super.copy( source );
32192
32193		this.v0.copy( source.v0 );
32194		this.v1.copy( source.v1 );
32195		this.v2.copy( source.v2 );
32196		this.v3.copy( source.v3 );
32197
32198		return this;
32199
32200	}
32201
32202	toJSON() {
32203
32204		const data = super.toJSON();
32205
32206		data.v0 = this.v0.toArray();
32207		data.v1 = this.v1.toArray();
32208		data.v2 = this.v2.toArray();
32209		data.v3 = this.v3.toArray();
32210
32211		return data;
32212
32213	}
32214
32215	fromJSON( json ) {
32216
32217		super.fromJSON( json );
32218
32219		this.v0.fromArray( json.v0 );
32220		this.v1.fromArray( json.v1 );
32221		this.v2.fromArray( json.v2 );
32222		this.v3.fromArray( json.v3 );
32223
32224		return this;
32225
32226	}
32227
32228}
32229
32230/**
32231 * A curve representing a 2D line segment.
32232 *
32233 * @augments Curve
32234 */
32235class LineCurve extends Curve {
32236
32237	/**
32238	 * Constructs a new line curve.
32239	 *
32240	 * @param {Vector2} [v1] - The start point.
32241	 * @param {Vector2} [v2] - The end point.
32242	 */
32243	constructor( v1 = new Vector2(), v2 = new Vector2() ) {
32244
32245		super();
32246
32247		/**
32248		 * This flag can be used for type testing.
32249		 *
32250		 * @type {boolean}
32251		 * @readonly
32252		 * @default true
32253		 */
32254		this.isLineCurve = true;
32255
32256		this.type = 'LineCurve';
32257
32258		/**
32259		 * The start point.
32260		 *
32261		 * @type {Vector2}
32262		 */
32263		this.v1 = v1;
32264
32265		/**
32266		 * The end point.
32267		 *
32268		 * @type {Vector2}
32269		 */
32270		this.v2 = v2;
32271
32272	}
32273
32274	/**
32275	 * Returns a point on the line.
32276	 *
32277	 * @param {number} t - A interpolation factor representing a position on the line. Must be in the range `[0,1]`.
32278	 * @param {Vector2} [optionalTarget] - The optional target vector the result is written to.
32279	 * @return {Vector2} The position on the line.
32280	 */
32281	getPoint( t, optionalTarget = new Vector2() ) {
32282
32283		const point = optionalTarget;
32284
32285		if ( t === 1 ) {
32286
32287			point.copy( this.v2 );
32288
32289		} else {
32290
32291			point.copy( this.v2 ).sub( this.v1 );
32292			point.multiplyScalar( t ).add( this.v1 );
32293
32294		}
32295
32296		return point;
32297
32298	}
32299
32300	// Line curve is linear, so we can overwrite default getPointAt
32301	getPointAt( u, optionalTarget ) {
32302
32303		return this.getPoint( u, optionalTarget );
32304
32305	}
32306
32307	getTangent( t, optionalTarget = new Vector2() ) {
32308
32309		return optionalTarget.subVectors( this.v2, this.v1 ).normalize();
32310
32311	}
32312
32313	getTangentAt( u, optionalTarget ) {
32314
32315		return this.getTangent( u, optionalTarget );
32316
32317	}
32318
32319	copy( source ) {
32320
32321		super.copy( source );
32322
32323		this.v1.copy( source.v1 );
32324		this.v2.copy( source.v2 );
32325
32326		return this;
32327
32328	}
32329
32330	toJSON() {
32331
32332		const data = super.toJSON();
32333
32334		data.v1 = this.v1.toArray();
32335		data.v2 = this.v2.toArray();
32336
32337		return data;
32338
32339	}
32340
32341	fromJSON( json ) {
32342
32343		super.fromJSON( json );
32344
32345		this.v1.fromArray( json.v1 );
32346		this.v2.fromArray( json.v2 );
32347
32348		return this;
32349
32350	}
32351
32352}
32353
32354/**
32355 * A curve representing a 3D line segment.
32356 *
32357 * @augments Curve
32358 */
32359class LineCurve3 extends Curve {
32360
32361	/**
32362	 * Constructs a new line curve.
32363	 *
32364	 * @param {Vector3} [v1] - The start point.
32365	 * @param {Vector3} [v2] - The end point.
32366	 */
32367	constructor( v1 = new Vector3(), v2 = new Vector3() ) {
32368
32369		super();
32370
32371		/**
32372		 * This flag can be used for type testing.
32373		 *
32374		 * @type {boolean}
32375		 * @readonly
32376		 * @default true
32377		 */
32378		this.isLineCurve3 = true;
32379
32380		this.type = 'LineCurve3';
32381
32382		/**
32383		 * The start point.
32384		 *
32385		 * @type {Vector3}
32386		 */
32387		this.v1 = v1;
32388
32389		/**
32390		 * The end point.
32391		 *
32392		 * @type {Vector2}
32393		 */
32394		this.v2 = v2;
32395
32396	}
32397
32398	/**
32399	 * Returns a point on the line.
32400	 *
32401	 * @param {number} t - A interpolation factor representing a position on the line. Must be in the range `[0,1]`.
32402	 * @param {Vector3} [optionalTarget] - The optional target vector the result is written to.
32403	 * @return {Vector3} The position on the line.
32404	 */
32405	getPoint( t, optionalTarget = new Vector3() ) {
32406
32407		const point = optionalTarget;
32408
32409		if ( t === 1 ) {
32410
32411			point.copy( this.v2 );
32412
32413		} else {
32414
32415			point.copy( this.v2 ).sub( this.v1 );
32416			point.multiplyScalar( t ).add( this.v1 );
32417
32418		}
32419
32420		return point;
32421
32422	}
32423
32424	// Line curve is linear, so we can overwrite default getPointAt
32425	getPointAt( u, optionalTarget ) {
32426
32427		return this.getPoint( u, optionalTarget );
32428
32429	}
32430
32431	getTangent( t, optionalTarget = new Vector3() ) {
32432
32433		return optionalTarget.subVectors( this.v2, this.v1 ).normalize();
32434
32435	}
32436
32437	getTangentAt( u, optionalTarget ) {
32438
32439		return this.getTangent( u, optionalTarget );
32440
32441	}
32442
32443	copy( source ) {
32444
32445		super.copy( source );
32446
32447		this.v1.copy( source.v1 );
32448		this.v2.copy( source.v2 );
32449
32450		return this;
32451
32452	}
32453
32454	toJSON() {
32455
32456		const data = super.toJSON();
32457
32458		data.v1 = this.v1.toArray();
32459		data.v2 = this.v2.toArray();
32460
32461		return data;
32462
32463	}
32464
32465	fromJSON( json ) {
32466
32467		super.fromJSON( json );
32468
32469		this.v1.fromArray( json.v1 );
32470		this.v2.fromArray( json.v2 );
32471
32472		return this;
32473
32474	}
32475
32476}
32477
32478/**
32479 * A curve representing a 2D Quadratic Bezier curve.
32480 *
32481 * ```js
32482 * const curve = new THREE.QuadraticBezierCurve(
32483 * 	new THREE.Vector2( - 10, 0 ),
32484 * 	new THREE.Vector2( 20, 15 ),
32485 * 	new THREE.Vector2( 10, 0 )
32486 * )
32487 *
32488 * const points = curve.getPoints( 50 );
32489 * const geometry = new THREE.BufferGeometry().setFromPoints( points );
32490 *
32491 * const material = new THREE.LineBasicMaterial( { color: 0xff0000 } );
32492 *
32493 * // Create the final object to add to the scene
32494 * const curveObject = new THREE.Line( geometry, material );
32495 * ```
32496 *
32497 * @augments Curve
32498 */
32499class QuadraticBezierCurve extends Curve {
32500
32501	/**
32502	 * Constructs a new Quadratic Bezier curve.
32503	 *
32504	 * @param {Vector2} [v0] - The start point.
32505	 * @param {Vector2} [v1] - The control point.
32506	 * @param {Vector2} [v2] - The end point.
32507	 */
32508	constructor( v0 = new Vector2(), v1 = new Vector2(), v2 = new Vector2() ) {
32509
32510		super();
32511
32512		/**
32513		 * This flag can be used for type testing.
32514		 *
32515		 * @type {boolean}
32516		 * @readonly
32517		 * @default true
32518		 */
32519		this.isQuadraticBezierCurve = true;
32520
32521		this.type = 'QuadraticBezierCurve';
32522
32523		/**
32524		 * The start point.
32525		 *
32526		 * @type {Vector2}
32527		 */
32528		this.v0 = v0;
32529
32530		/**
32531		 * The control point.
32532		 *
32533		 * @type {Vector2}
32534		 */
32535		this.v1 = v1;
32536
32537		/**
32538		 * The end point.
32539		 *
32540		 * @type {Vector2}
32541		 */
32542		this.v2 = v2;
32543
32544	}
32545
32546	/**
32547	 * Returns a point on the curve.
32548	 *
32549	 * @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
32550	 * @param {Vector2} [optionalTarget] - The optional target vector the result is written to.
32551	 * @return {Vector2} The position on the curve.
32552	 */
32553	getPoint( t, optionalTarget = new Vector2() ) {
32554
32555		const point = optionalTarget;
32556
32557		const v0 = this.v0, v1 = this.v1, v2 = this.v2;
32558
32559		point.set(
32560			QuadraticBezier( t, v0.x, v1.x, v2.x ),
32561			QuadraticBezier( t, v0.y, v1.y, v2.y )
32562		);
32563
32564		return point;
32565
32566	}
32567
32568	copy( source ) {
32569
32570		super.copy( source );
32571
32572		this.v0.copy( source.v0 );
32573		this.v1.copy( source.v1 );
32574		this.v2.copy( source.v2 );
32575
32576		return this;
32577
32578	}
32579
32580	toJSON() {
32581
32582		const data = super.toJSON();
32583
32584		data.v0 = this.v0.toArray();
32585		data.v1 = this.v1.toArray();
32586		data.v2 = this.v2.toArray();
32587
32588		return data;
32589
32590	}
32591
32592	fromJSON( json ) {
32593
32594		super.fromJSON( json );
32595
32596		this.v0.fromArray( json.v0 );
32597		this.v1.fromArray( json.v1 );
32598		this.v2.fromArray( json.v2 );
32599
32600		return this;
32601
32602	}
32603
32604}
32605
32606/**
32607 * A curve representing a 3D Quadratic Bezier curve.
32608 *
32609 * @augments Curve
32610 */
32611class QuadraticBezierCurve3 extends Curve {
32612
32613	/**
32614	 * Constructs a new Quadratic Bezier curve.
32615	 *
32616	 * @param {Vector3} [v0] - The start point.
32617	 * @param {Vector3} [v1] - The control point.
32618	 * @param {Vector3} [v2] - The end point.
32619	 */
32620	constructor( v0 = new Vector3(), v1 = new Vector3(), v2 = new Vector3() ) {
32621
32622		super();
32623
32624		/**
32625		 * This flag can be used for type testing.
32626		 *
32627		 * @type {boolean}
32628		 * @readonly
32629		 * @default true
32630		 */
32631		this.isQuadraticBezierCurve3 = true;
32632
32633		this.type = 'QuadraticBezierCurve3';
32634
32635		/**
32636		 * The start point.
32637		 *
32638		 * @type {Vector3}
32639		 */
32640		this.v0 = v0;
32641
32642		/**
32643		 * The control point.
32644		 *
32645		 * @type {Vector3}
32646		 */
32647		this.v1 = v1;
32648
32649		/**
32650		 * The end point.
32651		 *
32652		 * @type {Vector3}
32653		 */
32654		this.v2 = v2;
32655
32656	}
32657
32658	/**
32659	 * Returns a point on the curve.
32660	 *
32661	 * @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
32662	 * @param {Vector3} [optionalTarget] - The optional target vector the result is written to.
32663	 * @return {Vector3} The position on the curve.
32664	 */
32665	getPoint( t, optionalTarget = new Vector3() ) {
32666
32667		const point = optionalTarget;
32668
32669		const v0 = this.v0, v1 = this.v1, v2 = this.v2;
32670
32671		point.set(
32672			QuadraticBezier( t, v0.x, v1.x, v2.x ),
32673			QuadraticBezier( t, v0.y, v1.y, v2.y ),
32674			QuadraticBezier( t, v0.z, v1.z, v2.z )
32675		);
32676
32677		return point;
32678
32679	}
32680
32681	copy( source ) {
32682
32683		super.copy( source );
32684
32685		this.v0.copy( source.v0 );
32686		this.v1.copy( source.v1 );
32687		this.v2.copy( source.v2 );
32688
32689		return this;
32690
32691	}
32692
32693	toJSON() {
32694
32695		const data = super.toJSON();
32696
32697		data.v0 = this.v0.toArray();
32698		data.v1 = this.v1.toArray();
32699		data.v2 = this.v2.toArray();
32700
32701		return data;
32702
32703	}
32704
32705	fromJSON( json ) {
32706
32707		super.fromJSON( json );
32708
32709		this.v0.fromArray( json.v0 );
32710		this.v1.fromArray( json.v1 );
32711		this.v2.fromArray( json.v2 );
32712
32713		return this;
32714
32715	}
32716
32717}
32718
32719/**
32720 * A curve representing a 2D spline curve.
32721 *
32722 * ```js
32723 * // Create a sine-like wave
32724 * const curve = new THREE.SplineCurve( [
32725 * 	new THREE.Vector2( -10, 0 ),
32726 * 	new THREE.Vector2( -5, 5 ),
32727 * 	new THREE.Vector2( 0, 0 ),
32728 * 	new THREE.Vector2( 5, -5 ),
32729 * 	new THREE.Vector2( 10, 0 )
32730 * ] );
32731 *
32732 * const points = curve.getPoints( 50 );
32733 * const geometry = new THREE.BufferGeometry().setFromPoints( points );
32734 *
32735 * const material = new THREE.LineBasicMaterial( { color: 0xff0000 } );
32736 *
32737 * // Create the final object to add to the scene
32738 * const splineObject = new THREE.Line( geometry, material );
32739 * ```
32740 *
32741 * @augments Curve
32742 */
32743class SplineCurve extends Curve {
32744
32745	/**
32746	 * Constructs a new 2D spline curve.
32747	 *
32748	 * @param {Array<Vector2>} [points] -  An array of 2D points defining the curve.
32749	 */
32750	constructor( points = [] ) {
32751
32752		super();
32753
32754		/**
32755		 * This flag can be used for type testing.
32756		 *
32757		 * @type {boolean}
32758		 * @readonly
32759		 * @default true
32760		 */
32761		this.isSplineCurve = true;
32762
32763		this.type = 'SplineCurve';
32764
32765		/**
32766		 * An array of 2D points defining the curve.
32767		 *
32768		 * @type {Array<Vector2>}
32769		 */
32770		this.points = points;
32771
32772	}
32773
32774	/**
32775	 * Returns a point on the curve.
32776	 *
32777	 * @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
32778	 * @param {Vector2} [optionalTarget] - The optional target vector the result is written to.
32779	 * @return {Vector2} The position on the curve.
32780	 */
32781	getPoint( t, optionalTarget = new Vector2() ) {
32782
32783		const point = optionalTarget;
32784
32785		const points = this.points;
32786		const p = ( points.length - 1 ) * t;
32787
32788		const intPoint = Math.floor( p );
32789		const weight = p - intPoint;
32790
32791		const p0 = points[ intPoint === 0 ? intPoint : intPoint - 1 ];
32792		const p1 = points[ intPoint ];
32793		const p2 = points[ intPoint > points.length - 2 ? points.length - 1 : intPoint + 1 ];
32794		const p3 = points[ intPoint > points.length - 3 ? points.length - 1 : intPoint + 2 ];
32795
32796		point.set(
32797			CatmullRom( weight, p0.x, p1.x, p2.x, p3.x ),
32798			CatmullRom( weight, p0.y, p1.y, p2.y, p3.y )
32799		);
32800
32801		return point;
32802
32803	}
32804
32805	copy( source ) {
32806
32807		super.copy( source );
32808
32809		this.points = [];
32810
32811		for ( let i = 0, l = source.points.length; i < l; i ++ ) {
32812
32813			const point = source.points[ i ];
32814
32815			this.points.push( point.clone() );
32816
32817		}
32818
32819		return this;
32820
32821	}
32822
32823	toJSON() {
32824
32825		const data = super.toJSON();
32826
32827		data.points = [];
32828
32829		for ( let i = 0, l = this.points.length; i < l; i ++ ) {
32830
32831			const point = this.points[ i ];
32832			data.points.push( point.toArray() );
32833
32834		}
32835
32836		return data;
32837
32838	}
32839
32840	fromJSON( json ) {
32841
32842		super.fromJSON( json );
32843
32844		this.points = [];
32845
32846		for ( let i = 0, l = json.points.length; i < l; i ++ ) {
32847
32848			const point = json.points[ i ];
32849			this.points.push( new Vector2().fromArray( point ) );
32850
32851		}
32852
32853		return this;
32854
32855	}
32856
32857}
32858
32859var Curves = /*#__PURE__*/Object.freeze({
32860	__proto__: null,
32861	ArcCurve: ArcCurve,
32862	CatmullRomCurve3: CatmullRomCurve3,
32863	CubicBezierCurve: CubicBezierCurve,
32864	CubicBezierCurve3: CubicBezierCurve3,
32865	EllipseCurve: EllipseCurve,
32866	LineCurve: LineCurve,
32867	LineCurve3: LineCurve3,
32868	QuadraticBezierCurve: QuadraticBezierCurve,
32869	QuadraticBezierCurve3: QuadraticBezierCurve3,
32870	SplineCurve: SplineCurve
32871});
32872
32873/**
32874 * A base class extending {@link Curve}. `CurvePath` is simply an
32875 * array of connected curves, but retains the API of a curve.
32876 *
32877 * @augments Curve
32878 */
32879class CurvePath extends Curve {
32880
32881	/**
32882	 * Constructs a new curve path.
32883	 */
32884	constructor() {
32885
32886		super();
32887
32888		this.type = 'CurvePath';
32889
32890		/**
32891		 * An array of curves defining the
32892		 * path.
32893		 *
32894		 * @type {Array<Curve>}
32895		 */
32896		this.curves = [];
32897
32898		/**
32899		 * Whether the path should automatically be closed
32900		 * by a line curve.
32901		 *
32902		 * @type {boolean}
32903		 * @default false
32904		 */
32905		this.autoClose = false;
32906
32907	}
32908
32909	/**
32910	 * Adds a curve to this curve path.
32911	 *
32912	 * @param {Curve} curve - The curve to add.
32913	 */
32914	add( curve ) {
32915
32916		this.curves.push( curve );
32917
32918	}
32919
32920	/**
32921	 * Adds a line curve to close the path.
32922	 *
32923	 * @return {CurvePath} A reference to this curve path.
32924	 */
32925	closePath() {
32926
32927		// Add a line curve if start and end of lines are not connected
32928		const startPoint = this.curves[ 0 ].getPoint( 0 );
32929		const endPoint = this.curves[ this.curves.length - 1 ].getPoint( 1 );
32930
32931		if ( ! startPoint.equals( endPoint ) ) {
32932
32933			const lineType = ( startPoint.isVector2 === true ) ? 'LineCurve' : 'LineCurve3';
32934			this.curves.push( new Curves[ lineType ]( endPoint, startPoint ) );
32935
32936		}
32937
32938		return this;
32939
32940	}
32941
32942	/**
32943	 * This method returns a vector in 2D or 3D space (depending on the curve definitions)
32944	 * for the given interpolation factor.
32945	 *
32946	 * @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
32947	 * @param {(Vector2|Vector3)} [optionalTarget] - The optional target vector the result is written to.
32948	 * @return {?(Vector2|Vector3)} The position on the curve. It can be a 2D or 3D vector depending on the curve definition.
32949	 */
32950	getPoint( t, optionalTarget ) {
32951
32952		// To get accurate point with reference to
32953		// entire path distance at time t,
32954		// following has to be done:
32955
32956		// 1. Length of each sub path have to be known
32957		// 2. Locate and identify type of curve
32958		// 3. Get t for the curve
32959		// 4. Return curve.getPointAt(t')
32960
32961		const d = t * this.getLength();
32962		const curveLengths = this.getCurveLengths();
32963		let i = 0;
32964
32965		// To think about boundaries points.
32966
32967		while ( i < curveLengths.length ) {
32968
32969			if ( curveLengths[ i ] >= d ) {
32970
32971				const diff = curveLengths[ i ] - d;
32972				const curve = this.curves[ i ];
32973
32974				const segmentLength = curve.getLength();
32975				const u = segmentLength === 0 ? 0 : 1 - diff / segmentLength;
32976
32977				return curve.getPointAt( u, optionalTarget );
32978
32979			}
32980
32981			i ++;
32982
32983		}
32984
32985		return null;
32986
32987		// loop where sum != 0, sum > d , sum+1 <d
32988
32989	}
32990
32991	getLength() {
32992
32993		// We cannot use the default THREE.Curve getPoint() with getLength() because in
32994		// THREE.Curve, getLength() depends on getPoint() but in THREE.CurvePath
32995		// getPoint() depends on getLength
32996
32997		const lens = this.getCurveLengths();
32998		return lens[ lens.length - 1 ];
32999
33000	}
33001
33002	updateArcLengths() {
33003
33004		// cacheLengths must be recalculated.
33005
33006		this.needsUpdate = true;
33007		this.cacheLengths = null;
33008		this.getCurveLengths();
33009
33010	}
33011
33012	/**
33013	 * Returns list of cumulative curve lengths of the defined curves.
33014	 *
33015	 * @return {Array<number>} The curve lengths.
33016	 */
33017	getCurveLengths() {
33018
33019		// Compute lengths and cache them
33020		// We cannot overwrite getLengths() because UtoT mapping uses it.
33021		// We use cache values if curves and cache array are same length
33022
33023		if ( this.cacheLengths && this.cacheLengths.length === this.curves.length ) {
33024
33025			return this.cacheLengths;
33026
33027		}
33028
33029		// Get length of sub-curve
33030		// Push sums into cached array
33031
33032		const lengths = [];
33033		let sums = 0;
33034
33035		for ( let i = 0, l = this.curves.length; i < l; i ++ ) {
33036
33037			sums += this.curves[ i ].getLength();
33038			lengths.push( sums );
33039
33040		}
33041
33042		this.cacheLengths = lengths;
33043
33044		return lengths;
33045
33046	}
33047
33048	getSpacedPoints( divisions = 40 ) {
33049
33050		const points = [];
33051
33052		for ( let i = 0; i <= divisions; i ++ ) {
33053
33054			points.push( this.getPoint( i / divisions ) );
33055
33056		}
33057
33058		if ( this.autoClose ) {
33059
33060			points.push( points[ 0 ] );
33061
33062		}
33063
33064		return points;
33065
33066	}
33067
33068	getPoints( divisions = 12 ) {
33069
33070		const points = [];
33071		let last;
33072
33073		for ( let i = 0, curves = this.curves; i < curves.length; i ++ ) {
33074
33075			const curve = curves[ i ];
33076			const resolution = curve.isEllipseCurve ? divisions * 2
33077				: ( curve.isLineCurve || curve.isLineCurve3 ) ? 1
33078					: curve.isSplineCurve ? divisions * curve.points.length
33079						: divisions;
33080
33081			const pts = curve.getPoints( resolution );
33082
33083			for ( let j = 0; j < pts.length; j ++ ) {
33084
33085				const point = pts[ j ];
33086
33087				if ( last && last.equals( point ) ) continue; // ensures no consecutive points are duplicates
33088
33089				points.push( point );
33090				last = point;
33091
33092			}
33093
33094		}
33095
33096		if ( this.autoClose && points.length > 1 && ! points[ points.length - 1 ].equals( points[ 0 ] ) ) {
33097
33098			points.push( points[ 0 ] );
33099
33100		}
33101
33102		return points;
33103
33104	}
33105
33106	copy( source ) {
33107
33108		super.copy( source );
33109
33110		this.curves = [];
33111
33112		for ( let i = 0, l = source.curves.length; i < l; i ++ ) {
33113
33114			const curve = source.curves[ i ];
33115
33116			this.curves.push( curve.clone() );
33117
33118		}
33119
33120		this.autoClose = source.autoClose;
33121
33122		return this;
33123
33124	}
33125
33126	toJSON() {
33127
33128		const data = super.toJSON();
33129
33130		data.autoClose = this.autoClose;
33131		data.curves = [];
33132
33133		for ( let i = 0, l = this.curves.length; i < l; i ++ ) {
33134
33135			const curve = this.curves[ i ];
33136			data.curves.push( curve.toJSON() );
33137
33138		}
33139
33140		return data;
33141
33142	}
33143
33144	fromJSON( json ) {
33145
33146		super.fromJSON( json );
33147
33148		this.autoClose = json.autoClose;
33149		this.curves = [];
33150
33151		for ( let i = 0, l = json.curves.length; i < l; i ++ ) {
33152
33153			const curve = json.curves[ i ];
33154			this.curves.push( new Curves[ curve.type ]().fromJSON( curve ) );
33155
33156		}
33157
33158		return this;
33159
33160	}
33161
33162}
33163
33164/**
33165 * A 2D path representation. The class provides methods for creating paths
33166 * and contours of 2D shapes similar to the 2D Canvas API.
33167 *
33168 * ```js
33169 * const path = new THREE.Path();
33170 *
33171 * path.lineTo( 0, 0.8 );
33172 * path.quadraticCurveTo( 0, 1, 0.2, 1 );
33173 * path.lineTo( 1, 1 );
33174 *
33175 * const points = path.getPoints();
33176 *
33177 * const geometry = new THREE.BufferGeometry().setFromPoints( points );
33178 * const material = new THREE.LineBasicMaterial( { color: 0xffffff } );
33179 *
33180 * const line = new THREE.Line( geometry, material );
33181 * scene.add( line );
33182 * ```
33183 *
33184 * @augments CurvePath
33185 */
33186class Path extends CurvePath {
33187
33188	/**
33189	 * Constructs a new path.
33190	 *
33191	 * @param {Array<Vector2>} [points] - An array of 2D points defining the path.
33192	 */
33193	constructor( points ) {
33194
33195		super();
33196
33197		this.type = 'Path';
33198
33199		/**
33200		 * The current offset of the path. Any new curve added will start here.
33201		 *
33202		 * @type {Vector2}
33203		 */
33204		this.currentPoint = new Vector2();
33205
33206		if ( points ) {
33207
33208			this.setFromPoints( points );
33209
33210		}
33211
33212	}
33213
33214	/**
33215	 * Creates a path from the given list of points. The points are added
33216	 * to the path as instances of {@link LineCurve}.
33217	 *
33218	 * @param {Array<Vector2>} points - An array of 2D points.
33219	 * @return {Path} A reference to this path.
33220	 */
33221	setFromPoints( points ) {
33222
33223		this.moveTo( points[ 0 ].x, points[ 0 ].y );
33224
33225		for ( let i = 1, l = points.length; i < l; i ++ ) {
33226
33227			this.lineTo( points[ i ].x, points[ i ].y );
33228
33229		}
33230
33231		return this;
33232
33233	}
33234
33235	/**
33236	 * Moves {@link Path#currentPoint} to the given point.
33237	 *
33238	 * @param {number} x - The x coordinate.
33239	 * @param {number} y - The y coordinate.
33240	 * @return {Path} A reference to this path.
33241	 */
33242	moveTo( x, y ) {
33243
33244		this.currentPoint.set( x, y ); // TODO consider referencing vectors instead of copying?
33245
33246		return this;
33247
33248	}
33249
33250	/**
33251	 * Adds an instance of {@link LineCurve} to the path by connecting
33252	 * the current point with the given one.
33253	 *
33254	 * @param {number} x - The x coordinate of the end point.
33255	 * @param {number} y - The y coordinate of the end point.
33256	 * @return {Path} A reference to this path.
33257	 */
33258	lineTo( x, y ) {
33259
33260		const curve = new LineCurve( this.currentPoint.clone(), new Vector2( x, y ) );
33261		this.curves.push( curve );
33262
33263		this.currentPoint.set( x, y );
33264
33265		return this;
33266
33267	}
33268
33269	/**
33270	 * Adds an instance of {@link QuadraticBezierCurve} to the path by connecting
33271	 * the current point with the given one.
33272	 *
33273	 * @param {number} aCPx - The x coordinate of the control point.
33274	 * @param {number} aCPy - The y coordinate of the control point.
33275	 * @param {number} aX - The x coordinate of the end point.
33276	 * @param {number} aY - The y coordinate of the end point.
33277	 * @return {Path} A reference to this path.
33278	 */
33279	quadraticCurveTo( aCPx, aCPy, aX, aY ) {
33280
33281		const curve = new QuadraticBezierCurve(
33282			this.currentPoint.clone(),
33283			new Vector2( aCPx, aCPy ),
33284			new Vector2( aX, aY )
33285		);
33286
33287		this.curves.push( curve );
33288
33289		this.currentPoint.set( aX, aY );
33290
33291		return this;
33292
33293	}
33294
33295	/**
33296	 * Adds an instance of {@link CubicBezierCurve} to the path by connecting
33297	 * the current point with the given one.
33298	 *
33299	 * @param {number} aCP1x - The x coordinate of the first control point.
33300	 * @param {number} aCP1y - The y coordinate of the first control point.
33301	 * @param {number} aCP2x - The x coordinate of the second control point.
33302	 * @param {number} aCP2y - The y coordinate of the second control point.
33303	 * @param {number} aX - The x coordinate of the end point.
33304	 * @param {number} aY - The y coordinate of the end point.
33305	 * @return {Path} A reference to this path.
33306	 */
33307	bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) {
33308
33309		const curve = new CubicBezierCurve(
33310			this.currentPoint.clone(),
33311			new Vector2( aCP1x, aCP1y ),
33312			new Vector2( aCP2x, aCP2y ),
33313			new Vector2( aX, aY )
33314		);
33315
33316		this.curves.push( curve );
33317
33318		this.currentPoint.set( aX, aY );
33319
33320		return this;
33321
33322	}
33323
33324	/**
33325	 * Adds an instance of {@link SplineCurve} to the path by connecting
33326	 * the current point with the given list of points.
33327	 *
33328	 * @param {Array<Vector2>} pts - An array of points in 2D space.
33329	 * @return {Path} A reference to this path.
33330	 */
33331	splineThru( pts ) {
33332
33333		const npts = [ this.currentPoint.clone() ].concat( pts );
33334
33335		const curve = new SplineCurve( npts );
33336		this.curves.push( curve );
33337
33338		this.currentPoint.copy( pts[ pts.length - 1 ] );
33339
33340		return this;
33341
33342	}
33343
33344	/**
33345	 * Adds an arc as an instance of {@link EllipseCurve} to the path, positioned relative
33346	 * to the current point.
33347	 *
33348	 * @param {number} [aX=0] - The x coordinate of the center of the arc offsetted from the previous curve.
33349	 * @param {number} [aY=0] - The y coordinate of the center of the arc offsetted from the previous curve.
33350	 * @param {number} [aRadius=1] - The radius of the arc.
33351	 * @param {number} [aStartAngle=0] - The start angle in radians.
33352	 * @param {number} [aEndAngle=Math.PI*2] - The end angle in radians.
33353	 * @param {boolean} [aClockwise=false] - Whether to sweep the arc clockwise or not.
33354	 * @return {Path} A reference to this path.
33355	 */
33356	arc( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
33357
33358		const x0 = this.currentPoint.x;
33359		const y0 = this.currentPoint.y;
33360
33361		this.absarc( aX + x0, aY + y0, aRadius,
33362			aStartAngle, aEndAngle, aClockwise );
33363
33364		return this;
33365
33366	}
33367
33368	/**
33369	 * Adds an absolutely positioned arc as an instance of {@link EllipseCurve} to the path.
33370	 *
33371	 * @param {number} [aX=0] - The x coordinate of the center of the arc.
33372	 * @param {number} [aY=0] - The y coordinate of the center of the arc.
33373	 * @param {number} [aRadius=1] - The radius of the arc.
33374	 * @param {number} [aStartAngle=0] - The start angle in radians.
33375	 * @param {number} [aEndAngle=Math.PI*2] - The end angle in radians.
33376	 * @param {boolean} [aClockwise=false] - Whether to sweep the arc clockwise or not.
33377	 * @return {Path} A reference to this path.
33378	 */
33379	absarc( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
33380
33381		this.absellipse( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
33382
33383		return this;
33384
33385	}
33386
33387	/**
33388	 * Adds an ellipse as an instance of {@link EllipseCurve} to the path, positioned relative
33389	 * to the current point
33390	 *
33391	 * @param {number} [aX=0] - The x coordinate of the center of the ellipse offsetted from the previous curve.
33392	 * @param {number} [aY=0] - The y coordinate of the center of the ellipse offsetted from the previous curve.
33393	 * @param {number} [xRadius=1] - The radius of the ellipse in the x axis.
33394	 * @param {number} [yRadius=1] - The radius of the ellipse in the y axis.
33395	 * @param {number} [aStartAngle=0] - The start angle in radians.
33396	 * @param {number} [aEndAngle=Math.PI*2] - The end angle in radians.
33397	 * @param {boolean} [aClockwise=false] - Whether to sweep the ellipse clockwise or not.
33398	 * @param {number} [aRotation=0] - The rotation angle of the ellipse in radians, counterclockwise from the positive X axis.
33399	 * @return {Path} A reference to this path.
33400	 */
33401	ellipse( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
33402
33403		const x0 = this.currentPoint.x;
33404		const y0 = this.currentPoint.y;
33405
33406		this.absellipse( aX + x0, aY + y0, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
33407
33408		return this;
33409
33410	}
33411
33412	/**
33413	 * Adds an absolutely positioned ellipse as an instance of {@link EllipseCurve} to the path.
33414	 *
33415	 * @param {number} [aX=0] - The x coordinate of the absolute center of the ellipse.
33416	 * @param {number} [aY=0] - The y coordinate of the absolute center of the ellipse.
33417	 * @param {number} [xRadius=1] - The radius of the ellipse in the x axis.
33418	 * @param {number} [yRadius=1] - The radius of the ellipse in the y axis.
33419	 * @param {number} [aStartAngle=0] - The start angle in radians.
33420	 * @param {number} [aEndAngle=Math.PI*2] - The end angle in radians.
33421	 * @param {boolean} [aClockwise=false] - Whether to sweep the ellipse clockwise or not.
33422	 * @param {number} [aRotation=0] - The rotation angle of the ellipse in radians, counterclockwise from the positive X axis.
33423	 * @return {Path} A reference to this path.
33424	 */
33425	absellipse( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
33426
33427		const curve = new EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
33428
33429		if ( this.curves.length > 0 ) {
33430
33431			// if a previous curve is present, attempt to join
33432			const firstPoint = curve.getPoint( 0 );
33433
33434			if ( ! firstPoint.equals( this.currentPoint ) ) {
33435
33436				this.lineTo( firstPoint.x, firstPoint.y );
33437
33438			}
33439
33440		}
33441
33442		this.curves.push( curve );
33443
33444		const lastPoint = curve.getPoint( 1 );
33445		this.currentPoint.copy( lastPoint );
33446
33447		return this;
33448
33449	}
33450
33451	copy( source ) {
33452
33453		super.copy( source );
33454
33455		this.currentPoint.copy( source.currentPoint );
33456
33457		return this;
33458
33459	}
33460
33461	toJSON() {
33462
33463		const data = super.toJSON();
33464
33465		data.currentPoint = this.currentPoint.toArray();
33466
33467		return data;
33468
33469	}
33470
33471	fromJSON( json ) {
33472
33473		super.fromJSON( json );
33474
33475		this.currentPoint.fromArray( json.currentPoint );
33476
33477		return this;
33478
33479	}
33480
33481}
33482
33483/**
33484 * Defines an arbitrary 2d shape plane using paths with optional holes. It
33485 * can be used with {@link ExtrudeGeometry}, {@link ShapeGeometry}, to get
33486 * points, or to get triangulated faces.
33487 *
33488 * ```js
33489 * const heartShape = new THREE.Shape();
33490 *
33491 * heartShape.moveTo( 25, 25 );
33492 * heartShape.bezierCurveTo( 25, 25, 20, 0, 0, 0 );
33493 * heartShape.bezierCurveTo( - 30, 0, - 30, 35, - 30, 35 );
33494 * heartShape.bezierCurveTo( - 30, 55, - 10, 77, 25, 95 );
33495 * heartShape.bezierCurveTo( 60, 77, 80, 55, 80, 35 );
33496 * heartShape.bezierCurveTo( 80, 35, 80, 0, 50, 0 );
33497 * heartShape.bezierCurveTo( 35, 0, 25, 25, 25, 25 );
33498 *
33499 * const extrudeSettings = {
33500 * 	depth: 8,
33501 * 	bevelEnabled: true,
33502 * 	bevelSegments: 2,
33503 * 	steps: 2,
33504 * 	bevelSize: 1,
33505 * 	bevelThickness: 1
33506 * };
33507 *
33508 * const geometry = new THREE.ExtrudeGeometry( heartShape, extrudeSettings );
33509 * const mesh = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial() );
33510 * ```
33511 *
33512 * @augments Path
33513 */
33514class Shape extends Path {
33515
33516	/**
33517	 * Constructs a new shape.
33518	 *
33519	 * @param {Array<Vector2>} [points] - An array of 2D points defining the shape.
33520	 */
33521	constructor( points ) {
33522
33523		super( points );
33524
33525		/**
33526		 * The UUID of the shape.
33527		 *
33528		 * @type {string}
33529		 * @readonly
33530		 */
33531		this.uuid = generateUUID();
33532
33533		this.type = 'Shape';
33534
33535		/**
33536		 * Defines the holes in the shape. Hole definitions must use the
33537		 * opposite winding order (CW/CCW) than the outer shape.
33538		 *
33539		 * @type {Array<Path>}
33540		 * @readonly
33541		 */
33542		this.holes = [];
33543
33544	}
33545
33546	/**
33547	 * Returns an array representing each contour of the holes
33548	 * as a list of 2D points.
33549	 *
33550	 * @param {number} divisions - The fineness of the result.
33551	 * @return {Array<Array<Vector2>>} The holes as a series of 2D points.
33552	 */
33553	getPointsHoles( divisions ) {
33554
33555		const holesPts = [];
33556
33557		for ( let i = 0, l = this.holes.length; i < l; i ++ ) {
33558
33559			holesPts[ i ] = this.holes[ i ].getPoints( divisions );
33560
33561		}
33562
33563		return holesPts;
33564
33565	}
33566
33567	// get points of shape and holes (keypoints based on segments parameter)
33568
33569	/**
33570	 * Returns an object that holds contour data for the shape and its holes as
33571	 * arrays of 2D points.
33572	 *
33573	 * @param {number} divisions - The fineness of the result.
33574	 * @return {{shape:Array<Vector2>,holes:Array<Array<Vector2>>}} An object with contour data.
33575	 */
33576	extractPoints( divisions ) {
33577
33578		return {
33579
33580			shape: this.getPoints( divisions ),
33581			holes: this.getPointsHoles( divisions )
33582
33583		};
33584
33585	}
33586
33587	copy( source ) {
33588
33589		super.copy( source );
33590
33591		this.holes = [];
33592
33593		for ( let i = 0, l = source.holes.length; i < l; i ++ ) {
33594
33595			const hole = source.holes[ i ];
33596
33597			this.holes.push( hole.clone() );
33598
33599		}
33600
33601		return this;
33602
33603	}
33604
33605	toJSON() {
33606
33607		const data = super.toJSON();
33608
33609		data.uuid = this.uuid;
33610		data.holes = [];
33611
33612		for ( let i = 0, l = this.holes.length; i < l; i ++ ) {
33613
33614			const hole = this.holes[ i ];
33615			data.holes.push( hole.toJSON() );
33616
33617		}
33618
33619		return data;
33620
33621	}
33622
33623	fromJSON( json ) {
33624
33625		super.fromJSON( json );
33626
33627		this.uuid = json.uuid;
33628		this.holes = [];
33629
33630		for ( let i = 0, l = json.holes.length; i < l; i ++ ) {
33631
33632			const hole = json.holes[ i ];
33633			this.holes.push( new Path().fromJSON( hole ) );
33634
33635		}
33636
33637		return this;
33638
33639	}
33640
33641}
33642
33643/* eslint-disable */
33644// copy of mapbox/earcut version 3.0.2
33645// https://github.com/mapbox/earcut/tree/v3.0.2
33646
33647function earcut(data, holeIndices, dim = 2) {
33648
33649    const hasHoles = holeIndices && holeIndices.length;
33650    const outerLen = hasHoles ? holeIndices[0] * dim : data.length;
33651    let outerNode = linkedList(data, 0, outerLen, dim, true);
33652    const triangles = [];
33653
33654    if (!outerNode || outerNode.next === outerNode.prev) return triangles;
33655
33656    let minX, minY, invSize;
33657
33658    if (hasHoles) outerNode = eliminateHoles(data, holeIndices, outerNode, dim);
33659
33660    // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox
33661    if (data.length > 80 * dim) {
33662        minX = data[0];
33663        minY = data[1];
33664        let maxX = minX;
33665        let maxY = minY;
33666
33667        for (let i = dim; i < outerLen; i += dim) {
33668            const x = data[i];
33669            const y = data[i + 1];
33670            if (x < minX) minX = x;
33671            if (y < minY) minY = y;
33672            if (x > maxX) maxX = x;
33673            if (y > maxY) maxY = y;
33674        }
33675
33676        // minX, minY and invSize are later used to transform coords into integers for z-order calculation
33677        invSize = Math.max(maxX - minX, maxY - minY);
33678        invSize = invSize !== 0 ? 32767 / invSize : 0;
33679    }
33680
33681    earcutLinked(outerNode, triangles, dim, minX, minY, invSize, 0);
33682
33683    return triangles;
33684}
33685
33686// create a circular doubly linked list from polygon points in the specified winding order
33687function linkedList(data, start, end, dim, clockwise) {
33688    let last;
33689
33690    if (clockwise === (signedArea(data, start, end, dim) > 0)) {
33691        for (let i = start; i < end; i += dim) last = insertNode(i / dim | 0, data[i], data[i + 1], last);
33692    } else {
33693        for (let i = end - dim; i >= start; i -= dim) last = insertNode(i / dim | 0, data[i], data[i + 1], last);
33694    }
33695
33696    if (last && equals(last, last.next)) {
33697        removeNode(last);
33698        last = last.next;
33699    }
33700
33701    return last;
33702}
33703
33704// eliminate colinear or duplicate points
33705function filterPoints(start, end) {
33706    if (!start) return start;
33707    if (!end) end = start;
33708
33709    let p = start,
33710        again;
33711    do {
33712        again = false;
33713
33714        if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) {
33715            removeNode(p);
33716            p = end = p.prev;
33717            if (p === p.next) break;
33718            again = true;
33719
33720        } else {
33721            p = p.next;
33722        }
33723    } while (again || p !== end);
33724
33725    return end;
33726}
33727
33728// main ear slicing loop which triangulates a polygon (given as a linked list)
33729function earcutLinked(ear, triangles, dim, minX, minY, invSize, pass) {
33730    if (!ear) return;
33731
33732    // interlink polygon nodes in z-order
33733    if (!pass && invSize) indexCurve(ear, minX, minY, invSize);
33734
33735    let stop = ear;
33736
33737    // iterate through ears, slicing them one by one
33738    while (ear.prev !== ear.next) {
33739        const prev = ear.prev;
33740        const next = ear.next;
33741
33742        if (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear)) {
33743            triangles.push(prev.i, ear.i, next.i); // cut off the triangle
33744
33745            removeNode(ear);
33746
33747            // skipping the next vertex leads to less sliver triangles
33748            ear = next.next;
33749            stop = next.next;
33750
33751            continue;
33752        }
33753
33754        ear = next;
33755
33756        // if we looped through the whole remaining polygon and can't find any more ears
33757        if (ear === stop) {
33758            // try filtering points and slicing again
33759            if (!pass) {
33760                earcutLinked(filterPoints(ear), triangles, dim, minX, minY, invSize, 1);
33761
33762            // if this didn't work, try curing all small self-intersections locally
33763            } else if (pass === 1) {
33764                ear = cureLocalIntersections(filterPoints(ear), triangles);
33765                earcutLinked(ear, triangles, dim, minX, minY, invSize, 2);
33766
33767            // as a last resort, try splitting the remaining polygon into two
33768            } else if (pass === 2) {
33769                splitEarcut(ear, triangles, dim, minX, minY, invSize);
33770            }
33771
33772            break;
33773        }
33774    }
33775}
33776
33777// check whether a polygon node forms a valid ear with adjacent nodes
33778function isEar(ear) {
33779    const a = ear.prev,
33780        b = ear,
33781        c = ear.next;
33782
33783    if (area(a, b, c) >= 0) return false; // reflex, can't be an ear
33784
33785    // now make sure we don't have other points inside the potential ear
33786    const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y;
33787
33788    // triangle bbox
33789    const x0 = Math.min(ax, bx, cx),
33790        y0 = Math.min(ay, by, cy),
33791        x1 = Math.max(ax, bx, cx),
33792        y1 = Math.max(ay, by, cy);
33793
33794    let p = c.next;
33795    while (p !== a) {
33796        if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 &&
33797            pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, p.x, p.y) &&
33798            area(p.prev, p, p.next) >= 0) return false;
33799        p = p.next;
33800    }
33801
33802    return true;
33803}
33804
33805function isEarHashed(ear, minX, minY, invSize) {
33806    const a = ear.prev,
33807        b = ear,
33808        c = ear.next;
33809
33810    if (area(a, b, c) >= 0) return false; // reflex, can't be an ear
33811
33812    const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y;
33813
33814    // triangle bbox
33815    const x0 = Math.min(ax, bx, cx),
33816        y0 = Math.min(ay, by, cy),
33817        x1 = Math.max(ax, bx, cx),
33818        y1 = Math.max(ay, by, cy);
33819
33820    // z-order range for the current triangle bbox;
33821    const minZ = zOrder(x0, y0, minX, minY, invSize),
33822        maxZ = zOrder(x1, y1, minX, minY, invSize);
33823
33824    let p = ear.prevZ,
33825        n = ear.nextZ;
33826
33827    // look for points inside the triangle in both directions
33828    while (p && p.z >= minZ && n && n.z <= maxZ) {
33829        if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c &&
33830            pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;
33831        p = p.prevZ;
33832
33833        if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c &&
33834            pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false;
33835        n = n.nextZ;
33836    }
33837
33838    // look for remaining points in decreasing z-order
33839    while (p && p.z >= minZ) {
33840        if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c &&
33841            pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;
33842        p = p.prevZ;
33843    }
33844
33845    // look for remaining points in increasing z-order
33846    while (n && n.z <= maxZ) {
33847        if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c &&
33848            pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false;
33849        n = n.nextZ;
33850    }
33851
33852    return true;
33853}
33854
33855// go through all polygon nodes and cure small local self-intersections
33856function cureLocalIntersections(start, triangles) {
33857    let p = start;
33858    do {
33859        const a = p.prev,
33860            b = p.next.next;
33861
33862        if (!equals(a, b) && intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) {
33863
33864            triangles.push(a.i, p.i, b.i);
33865
33866            // remove two nodes involved
33867            removeNode(p);
33868            removeNode(p.next);
33869
33870            p = start = b;
33871        }
33872        p = p.next;
33873    } while (p !== start);
33874
33875    return filterPoints(p);
33876}
33877
33878// try splitting polygon into two and triangulate them independently
33879function splitEarcut(start, triangles, dim, minX, minY, invSize) {
33880    // look for a valid diagonal that divides the polygon into two
33881    let a = start;
33882    do {
33883        let b = a.next.next;
33884        while (b !== a.prev) {
33885            if (a.i !== b.i && isValidDiagonal(a, b)) {
33886                // split the polygon in two by the diagonal
33887                let c = splitPolygon(a, b);
33888
33889                // filter colinear points around the cuts
33890                a = filterPoints(a, a.next);
33891                c = filterPoints(c, c.next);
33892
33893                // run earcut on each half
33894                earcutLinked(a, triangles, dim, minX, minY, invSize, 0);
33895                earcutLinked(c, triangles, dim, minX, minY, invSize, 0);
33896                return;
33897            }
33898            b = b.next;
33899        }
33900        a = a.next;
33901    } while (a !== start);
33902}
33903
33904// link every hole into the outer loop, producing a single-ring polygon without holes
33905function eliminateHoles(data, holeIndices, outerNode, dim) {
33906    const queue = [];
33907
33908    for (let i = 0, len = holeIndices.length; i < len; i++) {
33909        const start = holeIndices[i] * dim;
33910        const end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
33911        const list = linkedList(data, start, end, dim, false);
33912        if (list === list.next) list.steiner = true;
33913        queue.push(getLeftmost(list));
33914    }
33915
33916    queue.sort(compareXYSlope);
33917
33918    // process holes from left to right
33919    for (let i = 0; i < queue.length; i++) {
33920        outerNode = eliminateHole(queue[i], outerNode);
33921    }
33922
33923    return outerNode;
33924}
33925
33926function compareXYSlope(a, b) {
33927    let result = a.x - b.x;
33928    // when the left-most point of 2 holes meet at a vertex, sort the holes counterclockwise so that when we find
33929    // the bridge to the outer shell is always the point that they meet at.
33930    if (result === 0) {
33931        result = a.y - b.y;
33932        if (result === 0) {
33933            const aSlope = (a.next.y - a.y) / (a.next.x - a.x);
33934            const bSlope = (b.next.y - b.y) / (b.next.x - b.x);
33935            result = aSlope - bSlope;
33936        }
33937    }
33938    return result;
33939}
33940
33941// find a bridge between vertices that connects hole with an outer ring and link it
33942function eliminateHole(hole, outerNode) {
33943    const bridge = findHoleBridge(hole, outerNode);
33944    if (!bridge) {
33945        return outerNode;
33946    }
33947
33948    const bridgeReverse = splitPolygon(bridge, hole);
33949
33950    // filter collinear points around the cuts
33951    filterPoints(bridgeReverse, bridgeReverse.next);
33952    return filterPoints(bridge, bridge.next);
33953}
33954
33955// David Eberly's algorithm for finding a bridge between hole and outer polygon
33956function findHoleBridge(hole, outerNode) {
33957    let p = outerNode;
33958    const hx = hole.x;
33959    const hy = hole.y;
33960    let qx = -Infinity;
33961    let m;
33962
33963    // find a segment intersected by a ray from the hole's leftmost point to the left;
33964    // segment's endpoint with lesser x will be potential connection point
33965    // unless they intersect at a vertex, then choose the vertex
33966    if (equals(hole, p)) return p;
33967    do {
33968        if (equals(hole, p.next)) return p.next;
33969        else if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) {
33970            const x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y);
33971            if (x <= hx && x > qx) {
33972                qx = x;
33973                m = p.x < p.next.x ? p : p.next;
33974                if (x === hx) return m; // hole touches outer segment; pick leftmost endpoint
33975            }
33976        }
33977        p = p.next;
33978    } while (p !== outerNode);
33979
33980    if (!m) return null;
33981
33982    // look for points inside the triangle of hole point, segment intersection and endpoint;
33983    // if there are no points found, we have a valid connection;
33984    // otherwise choose the point of the minimum angle with the ray as connection point
33985
33986    const stop = m;
33987    const mx = m.x;
33988    const my = m.y;
33989    let tanMin = Infinity;
33990
33991    p = m;
33992
33993    do {
33994        if (hx >= p.x && p.x >= mx && hx !== p.x &&
33995                pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y)) {
33996
33997            const tan = Math.abs(hy - p.y) / (hx - p.x); // tangential
33998
33999            if (locallyInside(p, hole) &&
34000                (tan < tanMin || (tan === tanMin && (p.x > m.x || (p.x === m.x && sectorContainsSector(m, p)))))) {
34001                m = p;
34002                tanMin = tan;
34003            }
34004        }
34005
34006        p = p.next;
34007    } while (p !== stop);
34008
34009    return m;
34010}
34011
34012// whether sector in vertex m contains sector in vertex p in the same coordinates
34013function sectorContainsSector(m, p) {
34014    return area(m.prev, m, p.prev) < 0 && area(p.next, m, m.next) < 0;
34015}
34016
34017// interlink polygon nodes in z-order
34018function indexCurve(start, minX, minY, invSize) {
34019    let p = start;
34020    do {
34021        if (p.z === 0) p.z = zOrder(p.x, p.y, minX, minY, invSize);
34022        p.prevZ = p.prev;
34023        p.nextZ = p.next;
34024        p = p.next;
34025    } while (p !== start);
34026
34027    p.prevZ.nextZ = null;
34028    p.prevZ = null;
34029
34030    sortLinked(p);
34031}
34032
34033// Simon Tatham's linked list merge sort algorithm
34034// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
34035function sortLinked(list) {
34036    let numMerges;
34037    let inSize = 1;
34038
34039    do {
34040        let p = list;
34041        let e;
34042        list = null;
34043        let tail = null;
34044        numMerges = 0;
34045
34046        while (p) {
34047            numMerges++;
34048            let q = p;
34049            let pSize = 0;
34050            for (let i = 0; i < inSize; i++) {
34051                pSize++;
34052                q = q.nextZ;
34053                if (!q) break;
34054            }
34055            let qSize = inSize;
34056
34057            while (pSize > 0 || (qSize > 0 && q)) {
34058
34059                if (pSize !== 0 && (qSize === 0 || !q || p.z <= q.z)) {
34060                    e = p;
34061                    p = p.nextZ;
34062                    pSize--;
34063                } else {
34064                    e = q;
34065                    q = q.nextZ;
34066                    qSize--;
34067                }
34068
34069                if (tail) tail.nextZ = e;
34070                else list = e;
34071
34072                e.prevZ = tail;
34073                tail = e;
34074            }
34075
34076            p = q;
34077        }
34078
34079        tail.nextZ = null;
34080        inSize *= 2;
34081
34082    } while (numMerges > 1);
34083
34084    return list;
34085}
34086
34087// z-order of a point given coords and inverse of the longer side of data bbox
34088function zOrder(x, y, minX, minY, invSize) {
34089    // coords are transformed into non-negative 15-bit integer range
34090    x = (x - minX) * invSize | 0;
34091    y = (y - minY) * invSize | 0;
34092
34093    x = (x | (x << 8)) & 0x00FF00FF;
34094    x = (x | (x << 4)) & 0x0F0F0F0F;
34095    x = (x | (x << 2)) & 0x33333333;
34096    x = (x | (x << 1)) & 0x55555555;
34097
34098    y = (y | (y << 8)) & 0x00FF00FF;
34099    y = (y | (y << 4)) & 0x0F0F0F0F;
34100    y = (y | (y << 2)) & 0x33333333;
34101    y = (y | (y << 1)) & 0x55555555;
34102
34103    return x | (y << 1);
34104}
34105
34106// find the leftmost node of a polygon ring
34107function getLeftmost(start) {
34108    let p = start,
34109        leftmost = start;
34110    do {
34111        if (p.x < leftmost.x || (p.x === leftmost.x && p.y < leftmost.y)) leftmost = p;
34112        p = p.next;
34113    } while (p !== start);
34114
34115    return leftmost;
34116}
34117
34118// check if a point lies within a convex triangle
34119function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {
34120    return (cx - px) * (ay - py) >= (ax - px) * (cy - py) &&
34121           (ax - px) * (by - py) >= (bx - px) * (ay - py) &&
34122           (bx - px) * (cy - py) >= (cx - px) * (by - py);
34123}
34124
34125// check if a point lies within a convex triangle but false if its equal to the first point of the triangle
34126function pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, px, py) {
34127    return !(ax === px && ay === py) && pointInTriangle(ax, ay, bx, by, cx, cy, px, py);
34128}
34129
34130// check if a diagonal between two polygon nodes is valid (lies in polygon interior)
34131function isValidDiagonal(a, b) {
34132    return a.next.i !== b.i && a.prev.i !== b.i && !intersectsPolygon(a, b) && // doesn't intersect other edges
34133           (locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b) && // locally visible
34134            (area(a.prev, a, b.prev) || area(a, b.prev, b)) || // does not create opposite-facing sectors
34135            equals(a, b) && area(a.prev, a, a.next) > 0 && area(b.prev, b, b.next) > 0); // special zero-length case
34136}
34137
34138// signed area of a triangle
34139function area(p, q, r) {
34140    return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
34141}
34142
34143// check if two points are equal
34144function equals(p1, p2) {
34145    return p1.x === p2.x && p1.y === p2.y;
34146}
34147
34148// check if two segments intersect
34149function intersects(p1, q1, p2, q2) {
34150    const o1 = sign(area(p1, q1, p2));
34151    const o2 = sign(area(p1, q1, q2));
34152    const o3 = sign(area(p2, q2, p1));
34153    const o4 = sign(area(p2, q2, q1));
34154
34155    if (o1 !== o2 && o3 !== o4) return true; // general case
34156
34157    if (o1 === 0 && onSegment(p1, p2, q1)) return true; // p1, q1 and p2 are collinear and p2 lies on p1q1
34158    if (o2 === 0 && onSegment(p1, q2, q1)) return true; // p1, q1 and q2 are collinear and q2 lies on p1q1
34159    if (o3 === 0 && onSegment(p2, p1, q2)) return true; // p2, q2 and p1 are collinear and p1 lies on p2q2
34160    if (o4 === 0 && onSegment(p2, q1, q2)) return true; // p2, q2 and q1 are collinear and q1 lies on p2q2
34161
34162    return false;
34163}
34164
34165// for collinear points p, q, r, check if point q lies on segment pr
34166function onSegment(p, q, r) {
34167    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);
34168}
34169
34170function sign(num) {
34171    return num > 0 ? 1 : num < 0 ? -1 : 0;
34172}
34173
34174// check if a polygon diagonal intersects any polygon segments
34175function intersectsPolygon(a, b) {
34176    let p = a;
34177    do {
34178        if (p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i &&
34179                intersects(p, p.next, a, b)) return true;
34180        p = p.next;
34181    } while (p !== a);
34182
34183    return false;
34184}
34185
34186// check if a polygon diagonal is locally inside the polygon
34187function locallyInside(a, b) {
34188    return area(a.prev, a, a.next) < 0 ?
34189        area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0 :
34190        area(a, b, a.prev) < 0 || area(a, a.next, b) < 0;
34191}
34192
34193// check if the middle point of a polygon diagonal is inside the polygon
34194function middleInside(a, b) {
34195    let p = a;
34196    let inside = false;
34197    const px = (a.x + b.x) / 2;
34198    const py = (a.y + b.y) / 2;
34199    do {
34200        if (((p.y > py) !== (p.next.y > py)) && p.next.y !== p.y &&
34201                (px < (p.next.x - p.x) * (py - p.y) / (p.next.y - p.y) + p.x))
34202            inside = !inside;
34203        p = p.next;
34204    } while (p !== a);
34205
34206    return inside;
34207}
34208
34209// link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two;
34210// if one belongs to the outer ring and another to a hole, it merges it into a single ring
34211function splitPolygon(a, b) {
34212    const a2 = createNode(a.i, a.x, a.y),
34213        b2 = createNode(b.i, b.x, b.y),
34214        an = a.next,
34215        bp = b.prev;
34216
34217    a.next = b;
34218    b.prev = a;
34219
34220    a2.next = an;
34221    an.prev = a2;
34222
34223    b2.next = a2;
34224    a2.prev = b2;
34225
34226    bp.next = b2;
34227    b2.prev = bp;
34228
34229    return b2;
34230}
34231
34232// create a node and optionally link it with previous one (in a circular doubly linked list)
34233function insertNode(i, x, y, last) {
34234    const p = createNode(i, x, y);
34235
34236    if (!last) {
34237        p.prev = p;
34238        p.next = p;
34239
34240    } else {
34241        p.next = last.next;
34242        p.prev = last;
34243        last.next.prev = p;
34244        last.next = p;
34245    }
34246    return p;
34247}
34248
34249function removeNode(p) {
34250    p.next.prev = p.prev;
34251    p.prev.next = p.next;
34252
34253    if (p.prevZ) p.prevZ.nextZ = p.nextZ;
34254    if (p.nextZ) p.nextZ.prevZ = p.prevZ;
34255}
34256
34257function createNode(i, x, y) {
34258    return {
34259        i, // vertex index in coordinates array
34260        x, y, // vertex coordinates
34261        prev: null, // previous and next vertex nodes in a polygon ring
34262        next: null,
34263        z: 0, // z-order curve value
34264        prevZ: null, // previous and next nodes in z-order
34265        nextZ: null,
34266        steiner: false // indicates whether this is a steiner point
34267    };
34268}
34269
34270function signedArea(data, start, end, dim) {
34271    let sum = 0;
34272    for (let i = start, j = end - dim; i < end; i += dim) {
34273        sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]);
34274        j = i;
34275    }
34276    return sum;
34277}
34278
34279/**
34280 * An implementation of the earcut polygon triangulation algorithm.
34281 * The code is a port of [mapbox/earcut](https://github.com/mapbox/earcut).
34282 *
34283 * @see https://github.com/mapbox/earcut
34284 */
34285class Earcut {
34286
34287	/**
34288	 * Triangulates the given shape definition by returning an array of triangles.
34289	 *
34290	 * @param {Array<number>} data - An array with 2D points.
34291	 * @param {Array<number>} holeIndices - An array with indices defining holes.
34292	 * @param {number} [dim=2] - The number of coordinates per vertex in the input array.
34293	 * @return {Array<number>} An array representing the triangulated faces. Each face is defined by three consecutive numbers
34294	 * representing vertex indices.
34295	 */
34296	static triangulate( data, holeIndices, dim = 2 ) {
34297
34298		return earcut( data, holeIndices, dim );
34299
34300	}
34301
34302}
34303
34304/**
34305 * A class containing utility functions for shapes.
34306 *
34307 * @hideconstructor
34308 */
34309class ShapeUtils {
34310
34311	/**
34312	 * Calculate area of a ( 2D ) contour polygon.
34313	 *
34314	 * @param {Array<Vector2>} contour - An array of 2D points.
34315	 * @return {number} The area.
34316	 */
34317	static area( contour ) {
34318
34319		const n = contour.length;
34320		let a = 0.0;
34321
34322		for ( let p = n - 1, q = 0; q < n; p = q ++ ) {
34323
34324			a += contour[ p ].x * contour[ q ].y - contour[ q ].x * contour[ p ].y;
34325
34326		}
34327
34328		return a * 0.5;
34329
34330	}
34331
34332	/**
34333	 * Returns `true` if the given contour uses a clockwise winding order.
34334	 *
34335	 * @param {Array<Vector2>} pts - An array of 2D points defining a polygon.
34336	 * @return {boolean} Whether the given contour uses a clockwise winding order or not.
34337	 */
34338	static isClockWise( pts ) {
34339
34340		return ShapeUtils.area( pts ) < 0;
34341
34342	}
34343
34344	/**
34345	 * Triangulates the given shape definition.
34346	 *
34347	 * @param {Array<Vector2>} contour - An array of 2D points defining the contour.
34348	 * @param {Array<Array<Vector2>>} holes - An array that holds arrays of 2D points defining the holes.
34349	 * @return {Array<Array<number>>} An array that holds for each face definition an array with three indices.
34350	 */
34351	static triangulateShape( contour, holes ) {
34352
34353		const vertices = []; // flat array of vertices like [ x0,y0, x1,y1, x2,y2, ... ]
34354		const holeIndices = []; // array of hole indices
34355		const faces = []; // final array of vertex indices like [ [ a,b,d ], [ b,c,d ] ]
34356
34357		removeDupEndPts( contour );
34358		addContour( vertices, contour );
34359
34360		//
34361
34362		let holeIndex = contour.length;
34363
34364		holes.forEach( removeDupEndPts );
34365
34366		for ( let i = 0; i < holes.length; i ++ ) {
34367
34368			holeIndices.push( holeIndex );
34369			holeIndex += holes[ i ].length;
34370			addContour( vertices, holes[ i ] );
34371
34372		}
34373
34374		//
34375
34376		const triangles = Earcut.triangulate( vertices, holeIndices );
34377
34378		//
34379
34380		for ( let i = 0; i < triangles.length; i += 3 ) {
34381
34382			faces.push( triangles.slice( i, i + 3 ) );
34383
34384		}
34385
34386		return faces;
34387
34388	}
34389
34390}
34391
34392function removeDupEndPts( points ) {
34393
34394	const l = points.length;
34395
34396	if ( l > 2 && points[ l - 1 ].equals( points[ 0 ] ) ) {
34397
34398		points.pop();
34399
34400	}
34401
34402}
34403
34404function addContour( vertices, contour ) {
34405
34406	for ( let i = 0; i < contour.length; i ++ ) {
34407
34408		vertices.push( contour[ i ].x );
34409		vertices.push( contour[ i ].y );
34410
34411	}
34412
34413}
34414
34415/**
34416 * Creates extruded geometry from a path shape.
34417 *
34418 * ```js
34419 * const length = 12, width = 8;
34420 *
34421 * const shape = new THREE.Shape();
34422 * shape.moveTo( 0,0 );
34423 * shape.lineTo( 0, width );
34424 * shape.lineTo( length, width );
34425 * shape.lineTo( length, 0 );
34426 * shape.lineTo( 0, 0 );
34427 *
34428 * const geometry = new THREE.ExtrudeGeometry( shape );
34429 * const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
34430 * const mesh = new THREE.Mesh( geometry, material ) ;
34431 * scene.add( mesh );
34432 * ```
34433 *
34434 * @augments BufferGeometry
34435 * @demo scenes/geometry-browser.html#ExtrudeGeometry
34436 */
34437class ExtrudeGeometry extends BufferGeometry {
34438
34439	/**
34440	 * Constructs a new extrude geometry.
34441	 *
34442	 * @param {Shape|Array<Shape>} [shapes] - A shape or an array of shapes.
34443	 * @param {ExtrudeGeometry~Options} [options] - The extrude settings.
34444	 */
34445	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 = {} ) {
34446
34447		super();
34448
34449		this.type = 'ExtrudeGeometry';
34450
34451		/**
34452		 * Holds the constructor parameters that have been
34453		 * used to generate the geometry. Any modification
34454		 * after instantiation does not change the geometry.
34455		 *
34456		 * @type {Object}
34457		 */
34458		this.parameters = {
34459			shapes: shapes,
34460			options: options
34461		};
34462
34463		shapes = Array.isArray( shapes ) ? shapes : [ shapes ];
34464
34465		const scope = this;
34466
34467		const verticesArray = [];
34468		const uvArray = [];
34469
34470		for ( let i = 0, l = shapes.length; i < l; i ++ ) {
34471
34472			const shape = shapes[ i ];
34473			addShape( shape );
34474
34475		}
34476
34477		// build geometry
34478
34479		this.setAttribute( 'position', new Float32BufferAttribute( verticesArray, 3 ) );
34480		this.setAttribute( 'uv', new Float32BufferAttribute( uvArray, 2 ) );
34481
34482		this.computeVertexNormals();
34483
34484		// functions
34485
34486		function addShape( shape ) {
34487
34488			const placeholder = [];
34489
34490			// options
34491
34492			const curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12;
34493			const steps = options.steps !== undefined ? options.steps : 1;
34494			const depth = options.depth !== undefined ? options.depth : 1;
34495
34496			let bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true;
34497			let bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 0.2;
34498			let bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 0.1;
34499			let bevelOffset = options.bevelOffset !== undefined ? options.bevelOffset : 0;
34500			let bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3;
34501
34502			const extrudePath = options.extrudePath;
34503
34504			const uvgen = options.UVGenerator !== undefined ? options.UVGenerator : WorldUVGenerator;
34505
34506			//
34507
34508			let extrudePts, extrudeByPath = false;
34509			let splineTube, binormal, normal, position2;
34510
34511			if ( extrudePath ) {
34512
34513				extrudePts = extrudePath.getSpacedPoints( steps );
34514
34515				extrudeByPath = true;
34516				bevelEnabled = false; // bevels not supported for path extrusion
34517
34518				// SETUP TNB variables
34519
34520				const isClosed = extrudePath.isCatmullRomCurve3 ? extrudePath.closed : false;
34521
34522				splineTube = extrudePath.computeFrenetFrames( steps, isClosed );
34523
34524				// log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length);
34525
34526				binormal = new Vector3();
34527				normal = new Vector3();
34528				position2 = new Vector3();
34529
34530			}
34531
34532			// Safeguards if bevels are not enabled
34533
34534			if ( ! bevelEnabled ) {
34535
34536				bevelSegments = 0;
34537				bevelThickness = 0;
34538				bevelSize = 0;
34539				bevelOffset = 0;
34540
34541			}
34542
34543			// Variables initialization
34544
34545			const shapePoints = shape.extractPoints( curveSegments );
34546
34547			let vertices = shapePoints.shape;
34548			const holes = shapePoints.holes;
34549
34550			const reverse = ! ShapeUtils.isClockWise( vertices );
34551
34552			if ( reverse ) {
34553
34554				vertices = vertices.reverse();
34555
34556				// Maybe we should also check if holes are in the opposite direction, just to be safe ...
34557
34558				for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
34559
34560					const ahole = holes[ h ];
34561
34562					if ( ShapeUtils.isClockWise( ahole ) ) {
34563
34564						holes[ h ] = ahole.reverse();
34565
34566					}
34567
34568				}
34569
34570			}
34571
34572			/**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.
34573			 * @param {Array<Vector2>} points
34574			*/
34575			function mergeOverlappingPoints( points ) {
34576
34577				const THRESHOLD = 1e-10;
34578				const THRESHOLD_SQ = THRESHOLD * THRESHOLD;
34579				let prevPos = points[ 0 ];
34580				for ( let i = 1; i <= points.length; i ++ ) {
34581
34582					const currentIndex = i % points.length;
34583					const currentPos = points[ currentIndex ];
34584					const dx = currentPos.x - prevPos.x;
34585					const dy = currentPos.y - prevPos.y;
34586					const distSq = dx * dx + dy * dy;
34587
34588					const scalingFactorSqrt = Math.max(
34589						Math.abs( currentPos.x ),
34590						Math.abs( currentPos.y ),
34591						Math.abs( prevPos.x ),
34592						Math.abs( prevPos.y )
34593					);
34594					const thresholdSqScaled = THRESHOLD_SQ * scalingFactorSqrt * scalingFactorSqrt;
34595					if ( distSq <= thresholdSqScaled ) {
34596
34597						points.splice( currentIndex, 1 );
34598						i --;
34599						continue;
34600
34601					}
34602
34603					prevPos = currentPos;
34604
34605				}
34606
34607			}
34608
34609			mergeOverlappingPoints( vertices );
34610			holes.forEach( mergeOverlappingPoints );
34611
34612			const numHoles = holes.length;
34613
34614			/* Vertices */
34615
34616			const contour = vertices; // vertices has all points but contour has only points of circumference
34617
34618			for ( let h = 0; h < numHoles; h ++ ) {
34619
34620				const ahole = holes[ h ];
34621
34622				vertices = vertices.concat( ahole );
34623
34624			}
34625
34626
34627			function scalePt2( pt, vec, size ) {
34628
34629				if ( ! vec ) error( 'ExtrudeGeometry: vec does not exist' );
34630
34631				return pt.clone().addScaledVector( vec, size );
34632
34633			}
34634
34635			const vlen = vertices.length;
34636
34637
34638			// Find directions for point movement
34639
34640
34641			function getBevelVec( inPt, inPrev, inNext ) {
34642
34643				// computes for inPt the corresponding point inPt' on a new contour
34644				//   shifted by 1 unit (length of normalized vector) to the left
34645				// if we walk along contour clockwise, this new contour is outside the old one
34646				//
34647				// inPt' is the intersection of the two lines parallel to the two
34648				//  adjacent edges of inPt at a distance of 1 unit on the left side.
34649
34650				let v_trans_x, v_trans_y, shrink_by; // resulting translation vector for inPt
34651
34652				// good reading for geometry algorithms (here: line-line intersection)
34653				// http://geomalgorithms.com/a05-_intersect-1.html
34654
34655				const v_prev_x = inPt.x - inPrev.x,
34656					v_prev_y = inPt.y - inPrev.y;
34657				const v_next_x = inNext.x - inPt.x,
34658					v_next_y = inNext.y - inPt.y;
34659
34660				const v_prev_lensq = ( v_prev_x * v_prev_x + v_prev_y * v_prev_y );
34661
34662				// check for collinear edges
34663				const collinear0 = ( v_prev_x * v_next_y - v_prev_y * v_next_x );
34664
34665				if ( Math.abs( collinear0 ) > Number.EPSILON ) {
34666
34667					// not collinear
34668
34669					// length of vectors for normalizing
34670
34671					const v_prev_len = Math.sqrt( v_prev_lensq );
34672					const v_next_len = Math.sqrt( v_next_x * v_next_x + v_next_y * v_next_y );
34673
34674					// shift adjacent points by unit vectors to the left
34675
34676					const ptPrevShift_x = ( inPrev.x - v_prev_y / v_prev_len );
34677					const ptPrevShift_y = ( inPrev.y + v_prev_x / v_prev_len );
34678
34679					const ptNextShift_x = ( inNext.x - v_next_y / v_next_len );
34680					const ptNextShift_y = ( inNext.y + v_next_x / v_next_len );
34681
34682					// scaling factor for v_prev to intersection point
34683
34684					const sf = ( ( ptNextShift_x - ptPrevShift_x ) * v_next_y -
34685							( ptNextShift_y - ptPrevShift_y ) * v_next_x ) /
34686						( v_prev_x * v_next_y - v_prev_y * v_next_x );
34687
34688					// vector from inPt to intersection point
34689
34690					v_trans_x = ( ptPrevShift_x + v_prev_x * sf - inPt.x );
34691					v_trans_y = ( ptPrevShift_y + v_prev_y * sf - inPt.y );
34692
34693					// Don't normalize!, otherwise sharp corners become ugly
34694					//  but prevent crazy spikes
34695					const v_trans_lensq = ( v_trans_x * v_trans_x + v_trans_y * v_trans_y );
34696					if ( v_trans_lensq <= 2 ) {
34697
34698						return new Vector2( v_trans_x, v_trans_y );
34699
34700					} else {
34701
34702						shrink_by = Math.sqrt( v_trans_lensq / 2 );
34703
34704					}
34705
34706				} else {
34707
34708					// handle special case of collinear edges
34709
34710					let direction_eq = false; // assumes: opposite
34711
34712					if ( v_prev_x > Number.EPSILON ) {
34713
34714						if ( v_next_x > Number.EPSILON ) {
34715
34716							direction_eq = true;
34717
34718						}
34719
34720					} else {
34721
34722						if ( v_prev_x < - Number.EPSILON ) {
34723
34724							if ( v_next_x < - Number.EPSILON ) {
34725
34726								direction_eq = true;
34727
34728							}
34729
34730						} else {
34731
34732							if ( Math.sign( v_prev_y ) === Math.sign( v_next_y ) ) {
34733
34734								direction_eq = true;
34735
34736							}
34737
34738						}
34739
34740					}
34741
34742					if ( direction_eq ) {
34743
34744						// log("Warning: lines are a straight sequence");
34745						v_trans_x = - v_prev_y;
34746						v_trans_y = v_prev_x;
34747						shrink_by = Math.sqrt( v_prev_lensq );
34748
34749					} else {
34750
34751						// log("Warning: lines are a straight spike");
34752						v_trans_x = v_prev_x;
34753						v_trans_y = v_prev_y;
34754						shrink_by = Math.sqrt( v_prev_lensq / 2 );
34755
34756					}
34757
34758				}
34759
34760				return new Vector2( v_trans_x / shrink_by, v_trans_y / shrink_by );
34761
34762			}
34763
34764
34765			const contourMovements = [];
34766
34767			for ( let i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
34768
34769				if ( j === il ) j = 0;
34770				if ( k === il ) k = 0;
34771
34772				//  (j)---(i)---(k)
34773				// log('i,j,k', i, j , k)
34774
34775				contourMovements[ i ] = getBevelVec( contour[ i ], contour[ j ], contour[ k ] );
34776
34777			}
34778
34779			const holesMovements = [];
34780			let oneHoleMovements, verticesMovements = contourMovements.concat();
34781
34782			for ( let h = 0, hl = numHoles; h < hl; h ++ ) {
34783
34784				const ahole = holes[ h ];
34785
34786				oneHoleMovements = [];
34787
34788				for ( let i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
34789
34790					if ( j === il ) j = 0;
34791					if ( k === il ) k = 0;
34792
34793					//  (j)---(i)---(k)
34794					oneHoleMovements[ i ] = getBevelVec( ahole[ i ], ahole[ j ], ahole[ k ] );
34795
34796				}
34797
34798				holesMovements.push( oneHoleMovements );
34799				verticesMovements = verticesMovements.concat( oneHoleMovements );
34800
34801			}
34802
34803			let faces;
34804
34805			if ( bevelSegments === 0 ) {
34806
34807				faces = ShapeUtils.triangulateShape( contour, holes );
34808
34809			} else {
34810
34811				const contractedContourVertices = [];
34812				const expandedHoleVertices = [];
34813
34814				// Loop bevelSegments, 1 for the front, 1 for the back
34815
34816				for ( let b = 0; b < bevelSegments; b ++ ) {
34817
34818					//for ( b = bevelSegments; b > 0; b -- ) {
34819
34820					const t = b / bevelSegments;
34821					const z = bevelThickness * Math.cos( t * Math.PI / 2 );
34822					const bs = bevelSize * Math.sin( t * Math.PI / 2 ) + bevelOffset;
34823
34824					// contract shape
34825
34826					for ( let i = 0, il = contour.length; i < il; i ++ ) {
34827
34828						const vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
34829
34830						v( vert.x, vert.y, - z );
34831						if ( t === 0 ) contractedContourVertices.push( vert );
34832
34833					}
34834
34835					// expand holes
34836
34837					for ( let h = 0, hl = numHoles; h < hl; h ++ ) {
34838
34839						const ahole = holes[ h ];
34840						oneHoleMovements = holesMovements[ h ];
34841						const oneHoleVertices = [];
34842						for ( let i = 0, il = ahole.length; i < il; i ++ ) {
34843
34844							const vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
34845
34846							v( vert.x, vert.y, - z );
34847							if ( t === 0 ) oneHoleVertices.push( vert );
34848
34849						}
34850
34851						if ( t === 0 ) expandedHoleVertices.push( oneHoleVertices );
34852
34853					}
34854
34855				}
34856
34857				faces = ShapeUtils.triangulateShape( contractedContourVertices, expandedHoleVertices );
34858
34859			}
34860
34861			const flen = faces.length;
34862
34863			const bs = bevelSize + bevelOffset;
34864
34865			// Back facing vertices
34866
34867			for ( let i = 0; i < vlen; i ++ ) {
34868
34869				const vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
34870
34871				if ( ! extrudeByPath ) {
34872
34873					v( vert.x, vert.y, 0 );
34874
34875				} else {
34876
34877					// v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x );
34878
34879					normal.copy( splineTube.normals[ 0 ] ).multiplyScalar( vert.x );
34880					binormal.copy( splineTube.binormals[ 0 ] ).multiplyScalar( vert.y );
34881
34882					position2.copy( extrudePts[ 0 ] ).add( normal ).add( binormal );
34883
34884					v( position2.x, position2.y, position2.z );
34885
34886				}
34887
34888			}
34889
34890			// Add stepped vertices...
34891			// Including front facing vertices
34892
34893			for ( let s = 1; s <= steps; s ++ ) {
34894
34895				for ( let i = 0; i < vlen; i ++ ) {
34896
34897					const vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
34898
34899					if ( ! extrudeByPath ) {
34900
34901						v( vert.x, vert.y, depth / steps * s );
34902
34903					} else {
34904
34905						// v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x );
34906
34907						normal.copy( splineTube.normals[ s ] ).multiplyScalar( vert.x );
34908						binormal.copy( splineTube.binormals[ s ] ).multiplyScalar( vert.y );
34909
34910						position2.copy( extrudePts[ s ] ).add( normal ).add( binormal );
34911
34912						v( position2.x, position2.y, position2.z );
34913
34914					}
34915
34916				}
34917
34918			}
34919
34920
34921			// Add bevel segments planes
34922
34923			//for ( b = 1; b <= bevelSegments; b ++ ) {
34924			for ( let b = bevelSegments - 1; b >= 0; b -- ) {
34925
34926				const t = b / bevelSegments;
34927				const z = bevelThickness * Math.cos( t * Math.PI / 2 );
34928				const bs = bevelSize * Math.sin( t * Math.PI / 2 ) + bevelOffset;
34929
34930				// contract shape
34931
34932				for ( let i = 0, il = contour.length; i < il; i ++ ) {
34933
34934					const vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
34935					v( vert.x, vert.y, depth + z );
34936
34937				}
34938
34939				// expand holes
34940
34941				for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
34942
34943					const ahole = holes[ h ];
34944					oneHoleMovements = holesMovements[ h ];
34945
34946					for ( let i = 0, il = ahole.length; i < il; i ++ ) {
34947
34948						const vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
34949
34950						if ( ! extrudeByPath ) {
34951
34952							v( vert.x, vert.y, depth + z );
34953
34954						} else {
34955
34956							v( vert.x, vert.y + extrudePts[ steps - 1 ].y, extrudePts[ steps - 1 ].x + z );
34957
34958						}
34959
34960					}
34961
34962				}
34963
34964			}
34965
34966			/* Faces */
34967
34968			// Top and bottom faces
34969
34970			buildLidFaces();
34971
34972			// Sides faces
34973
34974			buildSideFaces();
34975
34976
34977			/////  Internal functions
34978
34979			function buildLidFaces() {
34980
34981				const start = verticesArray.length / 3;
34982
34983				if ( bevelEnabled ) {
34984
34985					let layer = 0; // steps + 1
34986					let offset = vlen * layer;
34987
34988					// Bottom faces
34989
34990					for ( let i = 0; i < flen; i ++ ) {
34991
34992						const face = faces[ i ];
34993						f3( face[ 2 ] + offset, face[ 1 ] + offset, face[ 0 ] + offset );
34994
34995					}
34996
34997					layer = steps + bevelSegments * 2;
34998					offset = vlen * layer;
34999
35000					// Top faces
35001
35002					for ( let i = 0; i < flen; i ++ ) {
35003
35004						const face = faces[ i ];
35005						f3( face[ 0 ] + offset, face[ 1 ] + offset, face[ 2 ] + offset );
35006
35007					}
35008
35009				} else {
35010
35011					// Bottom faces
35012
35013					for ( let i = 0; i < flen; i ++ ) {
35014
35015						const face = faces[ i ];
35016						f3( face[ 2 ], face[ 1 ], face[ 0 ] );
35017
35018					}
35019
35020					// Top faces
35021
35022					for ( let i = 0; i < flen; i ++ ) {
35023
35024						const face = faces[ i ];
35025						f3( face[ 0 ] + vlen * steps, face[ 1 ] + vlen * steps, face[ 2 ] + vlen * steps );
35026
35027					}
35028
35029				}
35030
35031				scope.addGroup( start, verticesArray.length / 3 - start, 0 );
35032
35033			}
35034
35035			// Create faces for the z-sides of the shape
35036
35037			function buildSideFaces() {
35038
35039				const start = verticesArray.length / 3;
35040				let layeroffset = 0;
35041				sidewalls( contour, layeroffset );
35042				layeroffset += contour.length;
35043
35044				for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
35045
35046					const ahole = holes[ h ];
35047					sidewalls( ahole, layeroffset );
35048
35049					//, true
35050					layeroffset += ahole.length;
35051
35052				}
35053
35054
35055				scope.addGroup( start, verticesArray.length / 3 - start, 1 );
35056
35057
35058			}
35059
35060			function sidewalls( contour, layeroffset ) {
35061
35062				let i = contour.length;
35063
35064				while ( -- i >= 0 ) {
35065
35066					const j = i;
35067					let k = i - 1;
35068					if ( k < 0 ) k = contour.length - 1;
35069
35070					//log('b', i,j, i-1, k,vertices.length);
35071
35072					for ( let s = 0, sl = ( steps + bevelSegments * 2 ); s < sl; s ++ ) {
35073
35074						const slen1 = vlen * s;
35075						const slen2 = vlen * ( s + 1 );
35076
35077						const a = layeroffset + j + slen1,
35078							b = layeroffset + k + slen1,
35079							c = layeroffset + k + slen2,
35080							d = layeroffset + j + slen2;
35081
35082						f4( a, b, c, d );
35083
35084					}
35085
35086				}
35087
35088			}
35089
35090			function v( x, y, z ) {
35091
35092				placeholder.push( x );
35093				placeholder.push( y );
35094				placeholder.push( z );
35095
35096			}
35097
35098
35099			function f3( a, b, c ) {
35100
35101				addVertex( a );
35102				addVertex( b );
35103				addVertex( c );
35104
35105				const nextIndex = verticesArray.length / 3;
35106				const uvs = uvgen.generateTopUV( scope, verticesArray, nextIndex - 3, nextIndex - 2, nextIndex - 1 );
35107
35108				addUV( uvs[ 0 ] );
35109				addUV( uvs[ 1 ] );
35110				addUV( uvs[ 2 ] );
35111
35112			}
35113
35114			function f4( a, b, c, d ) {
35115
35116				addVertex( a );
35117				addVertex( b );
35118				addVertex( d );
35119
35120				addVertex( b );
35121				addVertex( c );
35122				addVertex( d );
35123
35124
35125				const nextIndex = verticesArray.length / 3;
35126				const uvs = uvgen.generateSideWallUV( scope, verticesArray, nextIndex - 6, nextIndex - 3, nextIndex - 2, nextIndex - 1 );
35127
35128				addUV( uvs[ 0 ] );
35129				addUV( uvs[ 1 ] );
35130				addUV( uvs[ 3 ] );
35131
35132				addUV( uvs[ 1 ] );
35133				addUV( uvs[ 2 ] );
35134				addUV( uvs[ 3 ] );
35135
35136			}
35137
35138			function addVertex( index ) {
35139
35140				verticesArray.push( placeholder[ index * 3 + 0 ] );
35141				verticesArray.push( placeholder[ index * 3 + 1 ] );
35142				verticesArray.push( placeholder[ index * 3 + 2 ] );
35143
35144			}
35145
35146
35147			function addUV( vector2 ) {
35148
35149				uvArray.push( vector2.x );
35150				uvArray.push( vector2.y );
35151
35152			}
35153
35154		}
35155
35156	}
35157
35158	copy( source ) {
35159
35160		super.copy( source );
35161
35162		this.parameters = Object.assign( {}, source.parameters );
35163
35164		return this;
35165
35166	}
35167
35168	toJSON() {
35169
35170		const data = super.toJSON();
35171
35172		const shapes = this.parameters.shapes;
35173		const options = this.parameters.options;
35174
35175		return toJSON$1( shapes, options, data );
35176
35177	}
35178
35179	/**
35180	 * Factory method for creating an instance of this class from the given
35181	 * JSON object.
35182	 *
35183	 * @param {Object} data - A JSON object representing the serialized geometry.
35184	 * @param {Array<Shape>} shapes - An array of shapes.
35185	 * @return {ExtrudeGeometry} A new instance.
35186	 */
35187	static fromJSON( data, shapes ) {
35188
35189		const geometryShapes = [];
35190
35191		for ( let j = 0, jl = data.shapes.length; j < jl; j ++ ) {
35192
35193			const shape = shapes[ data.shapes[ j ] ];
35194
35195			geometryShapes.push( shape );
35196
35197		}
35198
35199		const extrudePath = data.options.extrudePath;
35200
35201		if ( extrudePath !== undefined ) {
35202
35203			data.options.extrudePath = new Curves[ extrudePath.type ]().fromJSON( extrudePath );
35204
35205		}
35206
35207		return new ExtrudeGeometry( geometryShapes, data.options );
35208
35209	}
35210
35211}
35212
35213const WorldUVGenerator = {
35214
35215	generateTopUV: function ( geometry, vertices, indexA, indexB, indexC ) {
35216
35217		const a_x = vertices[ indexA * 3 ];
35218		const a_y = vertices[ indexA * 3 + 1 ];
35219		const b_x = vertices[ indexB * 3 ];
35220		const b_y = vertices[ indexB * 3 + 1 ];
35221		const c_x = vertices[ indexC * 3 ];
35222		const c_y = vertices[ indexC * 3 + 1 ];
35223
35224		return [
35225			new Vector2( a_x, a_y ),
35226			new Vector2( b_x, b_y ),
35227			new Vector2( c_x, c_y )
35228		];
35229
35230	},
35231
35232	generateSideWallUV: function ( geometry, vertices, indexA, indexB, indexC, indexD ) {
35233
35234		const a_x = vertices[ indexA * 3 ];
35235		const a_y = vertices[ indexA * 3 + 1 ];
35236		const a_z = vertices[ indexA * 3 + 2 ];
35237		const b_x = vertices[ indexB * 3 ];
35238		const b_y = vertices[ indexB * 3 + 1 ];
35239		const b_z = vertices[ indexB * 3 + 2 ];
35240		const c_x = vertices[ indexC * 3 ];
35241		const c_y = vertices[ indexC * 3 + 1 ];
35242		const c_z = vertices[ indexC * 3 + 2 ];
35243		const d_x = vertices[ indexD * 3 ];
35244		const d_y = vertices[ indexD * 3 + 1 ];
35245		const d_z = vertices[ indexD * 3 + 2 ];
35246
35247		if ( Math.abs( a_y - b_y ) < Math.abs( a_x - b_x ) ) {
35248
35249			return [
35250				new Vector2( a_x, 1 - a_z ),
35251				new Vector2( b_x, 1 - b_z ),
35252				new Vector2( c_x, 1 - c_z ),
35253				new Vector2( d_x, 1 - d_z )
35254			];
35255
35256		} else {
35257
35258			return [
35259				new Vector2( a_y, 1 - a_z ),
35260				new Vector2( b_y, 1 - b_z ),
35261				new Vector2( c_y, 1 - c_z ),
35262				new Vector2( d_y, 1 - d_z )
35263			];
35264
35265		}
35266
35267	}
35268
35269};
35270
35271function toJSON$1( shapes, options, data ) {
35272
35273	data.shapes = [];
35274
35275	if ( Array.isArray( shapes ) ) {
35276
35277		for ( let i = 0, l = shapes.length; i < l; i ++ ) {
35278
35279			const shape = shapes[ i ];
35280
35281			data.shapes.push( shape.uuid );
35282
35283		}
35284
35285	} else {
35286
35287		data.shapes.push( shapes.uuid );
35288
35289	}
35290
35291	data.options = Object.assign( {}, options );
35292
35293	if ( options.extrudePath !== undefined ) data.options.extrudePath = options.extrudePath.toJSON();
35294
35295	return data;
35296
35297}
35298
35299/**
35300 * A geometry class for representing an icosahedron.
35301 *
35302 * ```js
35303 * const geometry = new THREE.IcosahedronGeometry();
35304 * const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
35305 * const icosahedron = new THREE.Mesh( geometry, material );
35306 * scene.add( icosahedron );
35307 * ```
35308 *
35309 * @augments PolyhedronGeometry
35310 * @demo scenes/geometry-browser.html#IcosahedronGeometry
35311 */
35312class IcosahedronGeometry extends PolyhedronGeometry {
35313
35314	/**
35315	 * Constructs a new icosahedron geometry.
35316	 *
35317	 * @param {number} [radius=1] - Radius of the icosahedron.
35318	 * @param {number} [detail=0] - Setting this to a value greater than `0` adds vertices making it no longer a icosahedron.
35319	 */
35320	constructor( radius = 1, detail = 0 ) {
35321
35322		const t = ( 1 + Math.sqrt( 5 ) ) / 2;
35323
35324		const vertices = [
35325			-1, t, 0, 	1, t, 0, 	-1, - t, 0, 	1, - t, 0,
35326			0, -1, t, 	0, 1, t,	0, -1, - t, 	0, 1, - t,
35327			t, 0, -1, 	t, 0, 1, 	- t, 0, -1, 	- t, 0, 1
35328		];
35329
35330		const indices = [
35331			0, 11, 5, 	0, 5, 1, 	0, 1, 7, 	0, 7, 10, 	0, 10, 11,
35332			1, 5, 9, 	5, 11, 4,	11, 10, 2,	10, 7, 6,	7, 1, 8,
35333			3, 9, 4, 	3, 4, 2,	3, 2, 6,	3, 6, 8,	3, 8, 9,
35334			4, 9, 5, 	2, 4, 11,	6, 2, 10,	8, 6, 7,	9, 8, 1
35335		];
35336
35337		super( vertices, indices, radius, detail );
35338
35339		this.type = 'IcosahedronGeometry';
35340
35341		/**
35342		 * Holds the constructor parameters that have been
35343		 * used to generate the geometry. Any modification
35344		 * after instantiation does not change the geometry.
35345		 *
35346		 * @type {Object}
35347		 */
35348		this.parameters = {
35349			radius: radius,
35350			detail: detail
35351		};
35352
35353	}
35354
35355	/**
35356	 * Factory method for creating an instance of this class from the given
35357	 * JSON object.
35358	 *
35359	 * @param {Object} data - A JSON object representing the serialized geometry.
35360	 * @return {IcosahedronGeometry} A new instance.
35361	 */
35362	static fromJSON( data ) {
35363
35364		return new IcosahedronGeometry( data.radius, data.detail );
35365
35366	}
35367
35368}
35369
35370/**
35371 * Creates meshes with axial symmetry like vases. The lathe rotates around the Y axis.
35372 *
35373 * ```js
35374 * const points = [];
35375 * for ( let i = 0; i < 10; i ++ ) {
35376 * 	points.push( new THREE.Vector2( Math.sin( i * 0.2 ) * 10 + 5, ( i - 5 ) * 2 ) );
35377 * }
35378 * const geometry = new THREE.LatheGeometry( points );
35379 * const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
35380 * const lathe = new THREE.Mesh( geometry, material );
35381 * scene.add( lathe );
35382 * ```
35383 *
35384 * @augments BufferGeometry
35385 * @demo scenes/geometry-browser.html#LatheGeometry
35386 */
35387class LatheGeometry extends BufferGeometry {
35388
35389	/**
35390	 * Constructs a new lathe geometry.
35391	 *
35392	 * @param {Array<Vector2|Vector3>} [points] - An array of points in 2D space. The x-coordinate of each point
35393	 * must be greater than zero.
35394	 * @param {number} [segments=12] - The number of circumference segments to generate.
35395	 * @param {number} [phiStart=0] - The starting angle in radians.
35396	 * @param {number} [phiLength=Math.PI*2] - The radian (0 to 2PI) range of the lathed section 2PI is a
35397	 * closed lathe, less than 2PI is a portion.
35398	 */
35399	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 ) {
35400
35401		super();
35402
35403		this.type = 'LatheGeometry';
35404
35405		/**
35406		 * Holds the constructor parameters that have been
35407		 * used to generate the geometry. Any modification
35408		 * after instantiation does not change the geometry.
35409		 *
35410		 * @type {Object}
35411		 */
35412		this.parameters = {
35413			points: points,
35414			segments: segments,
35415			phiStart: phiStart,
35416			phiLength: phiLength
35417		};
35418
35419		segments = Math.floor( segments );
35420
35421		// clamp phiLength so it's in range of [ 0, 2PI ]
35422
35423		phiLength = clamp( phiLength, 0, Math.PI * 2 );
35424
35425		// buffers
35426
35427		const indices = [];
35428		const vertices = [];
35429		const uvs = [];
35430		const initNormals = [];
35431		const normals = [];
35432
35433		// helper variables
35434
35435		const inverseSegments = 1.0 / segments;
35436		const vertex = new Vector3();
35437		const uv = new Vector2();
35438		const normal = new Vector3();
35439		const curNormal = new Vector3();
35440		const prevNormal = new Vector3();
35441		let dx = 0;
35442		let dy = 0;
35443
35444		// pre-compute normals for initial "meridian"
35445
35446		for ( let j = 0; j <= ( points.length - 1 ); j ++ ) {
35447
35448			switch ( j ) {
35449
35450				case 0:				// special handling for 1st vertex on path
35451
35452					dx = points[ j + 1 ].x - points[ j ].x;
35453					dy = points[ j + 1 ].y - points[ j ].y;
35454
35455					normal.x = dy * 1.0;
35456					normal.y = - dx;
35457					normal.z = dy * 0.0;
35458
35459					prevNormal.copy( normal );
35460
35461					normal.normalize();
35462
35463					initNormals.push( normal.x, normal.y, normal.z );
35464
35465					break;
35466
35467				case ( points.length - 1 ):	// special handling for last Vertex on path
35468
35469					initNormals.push( prevNormal.x, prevNormal.y, prevNormal.z );
35470
35471					break;
35472
35473				default:			// default handling for all vertices in between
35474
35475					dx = points[ j + 1 ].x - points[ j ].x;
35476					dy = points[ j + 1 ].y - points[ j ].y;
35477
35478					normal.x = dy * 1.0;
35479					normal.y = - dx;
35480					normal.z = dy * 0.0;
35481
35482					curNormal.copy( normal );
35483
35484					normal.x += prevNormal.x;
35485					normal.y += prevNormal.y;
35486					normal.z += prevNormal.z;
35487
35488					normal.normalize();
35489
35490					initNormals.push( normal.x, normal.y, normal.z );
35491
35492					prevNormal.copy( curNormal );
35493
35494			}
35495
35496		}
35497
35498		// generate vertices, uvs and normals
35499
35500		for ( let i = 0; i <= segments; i ++ ) {
35501
35502			const phi = phiStart + i * inverseSegments * phiLength;
35503
35504			const sin = Math.sin( phi );
35505			const cos = Math.cos( phi );
35506
35507			for ( let j = 0; j <= ( points.length - 1 ); j ++ ) {
35508
35509				// vertex
35510
35511				vertex.x = points[ j ].x * sin;
35512				vertex.y = points[ j ].y;
35513				vertex.z = points[ j ].x * cos;
35514
35515				vertices.push( vertex.x, vertex.y, vertex.z );
35516
35517				// uv
35518
35519				uv.x = i / segments;
35520				uv.y = j / ( points.length - 1 );
35521
35522				uvs.push( uv.x, uv.y );
35523
35524				// normal
35525
35526				const x = initNormals[ 3 * j + 0 ] * sin;
35527				const y = initNormals[ 3 * j + 1 ];
35528				const z = initNormals[ 3 * j + 0 ] * cos;
35529
35530				normals.push( x, y, z );
35531
35532			}
35533
35534		}
35535
35536		// indices
35537
35538		for ( let i = 0; i < segments; i ++ ) {
35539
35540			for ( let j = 0; j < ( points.length - 1 ); j ++ ) {
35541
35542				const base = j + i * points.length;
35543
35544				const a = base;
35545				const b = base + points.length;
35546				const c = base + points.length + 1;
35547				const d = base + 1;
35548
35549				// faces
35550
35551				indices.push( a, b, d );
35552				indices.push( c, d, b );
35553
35554			}
35555
35556		}
35557
35558		// build geometry
35559
35560		this.setIndex( indices );
35561		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
35562		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
35563		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
35564
35565	}
35566
35567	copy( source ) {
35568
35569		super.copy( source );
35570
35571		this.parameters = Object.assign( {}, source.parameters );
35572
35573		return this;
35574
35575	}
35576
35577	/**
35578	 * Factory method for creating an instance of this class from the given
35579	 * JSON object.
35580	 *
35581	 * @param {Object} data - A JSON object representing the serialized geometry.
35582	 * @return {LatheGeometry} A new instance.
35583	 */
35584	static fromJSON( data ) {
35585
35586		return new LatheGeometry( data.points, data.segments, data.phiStart, data.phiLength );
35587
35588	}
35589
35590}
35591
35592/**
35593 * A geometry class for representing an octahedron.
35594 *
35595 * ```js
35596 * const geometry = new THREE.OctahedronGeometry();
35597 * const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
35598 * const octahedron = new THREE.Mesh( geometry, material );
35599 * scene.add( octahedron );
35600 * ```
35601 *
35602 * @augments PolyhedronGeometry
35603 * @demo scenes/geometry-browser.html#OctahedronGeometry
35604 */
35605class OctahedronGeometry extends PolyhedronGeometry {
35606
35607	/**
35608	 * Constructs a new octahedron geometry.
35609	 *
35610	 * @param {number} [radius=1] - Radius of the octahedron.
35611	 * @param {number} [detail=0] - Setting this to a value greater than `0` adds vertices making it no longer a octahedron.
35612	 */
35613	constructor( radius = 1, detail = 0 ) {
35614
35615		const vertices = [
35616			1, 0, 0, 	-1, 0, 0,	0, 1, 0,
35617			0, -1, 0, 	0, 0, 1,	0, 0, -1
35618		];
35619
35620		const indices = [
35621			0, 2, 4,	0, 4, 3,	0, 3, 5,
35622			0, 5, 2,	1, 2, 5,	1, 5, 3,
35623			1, 3, 4,	1, 4, 2
35624		];
35625
35626		super( vertices, indices, radius, detail );
35627
35628		this.type = 'OctahedronGeometry';
35629
35630		/**
35631		 * Holds the constructor parameters that have been
35632		 * used to generate the geometry. Any modification
35633		 * after instantiation does not change the geometry.
35634		 *
35635		 * @type {Object}
35636		 */
35637		this.parameters = {
35638			radius: radius,
35639			detail: detail
35640		};
35641
35642	}
35643
35644	/**
35645	 * Factory method for creating an instance of this class from the given
35646	 * JSON object.
35647	 *
35648	 * @param {Object} data - A JSON object representing the serialized geometry.
35649	 * @return {OctahedronGeometry} A new instance.
35650	 */
35651	static fromJSON( data ) {
35652
35653		return new OctahedronGeometry( data.radius, data.detail );
35654
35655	}
35656
35657}
35658
35659/**
35660 * A geometry class for representing a plane.
35661 *
35662 * ```js
35663 * const geometry = new THREE.PlaneGeometry( 1, 1 );
35664 * const material = new THREE.MeshBasicMaterial( { color: 0xffff00, side: THREE.DoubleSide } );
35665 * const plane = new THREE.Mesh( geometry, material );
35666 * scene.add( plane );
35667 * ```
35668 *
35669 * @augments BufferGeometry
35670 * @demo scenes/geometry-browser.html#PlaneGeometry
35671 */
35672class PlaneGeometry extends BufferGeometry {
35673
35674	/**
35675	 * Constructs a new plane geometry.
35676	 *
35677	 * @param {number} [width=1] - The width along the X axis.
35678	 * @param {number} [height=1] - The height along the Y axis
35679	 * @param {number} [widthSegments=1] - The number of segments along the X axis.
35680	 * @param {number} [heightSegments=1] - The number of segments along the Y axis.
35681	 */
35682	constructor( width = 1, height = 1, widthSegments = 1, heightSegments = 1 ) {
35683
35684		super();
35685
35686		this.type = 'PlaneGeometry';
35687
35688		/**
35689		 * Holds the constructor parameters that have been
35690		 * used to generate the geometry. Any modification
35691		 * after instantiation does not change the geometry.
35692		 *
35693		 * @type {Object}
35694		 */
35695		this.parameters = {
35696			width: width,
35697			height: height,
35698			widthSegments: widthSegments,
35699			heightSegments: heightSegments
35700		};
35701
35702		const width_half = width / 2;
35703		const height_half = height / 2;
35704
35705		const gridX = Math.floor( widthSegments );
35706		const gridY = Math.floor( heightSegments );
35707
35708		const gridX1 = gridX + 1;
35709		const gridY1 = gridY + 1;
35710
35711		const segment_width = width / gridX;
35712		const segment_height = height / gridY;
35713
35714		//
35715
35716		const indices = [];
35717		const vertices = [];
35718		const normals = [];
35719		const uvs = [];
35720
35721		for ( let iy = 0; iy < gridY1; iy ++ ) {
35722
35723			const y = iy * segment_height - height_half;
35724
35725			for ( let ix = 0; ix < gridX1; ix ++ ) {
35726
35727				const x = ix * segment_width - width_half;
35728
35729				vertices.push( x, - y, 0 );
35730
35731				normals.push( 0, 0, 1 );
35732
35733				uvs.push( ix / gridX );
35734				uvs.push( 1 - ( iy / gridY ) );
35735
35736			}
35737
35738		}
35739
35740		for ( let iy = 0; iy < gridY; iy ++ ) {
35741
35742			for ( let ix = 0; ix < gridX; ix ++ ) {
35743
35744				const a = ix + gridX1 * iy;
35745				const b = ix + gridX1 * ( iy + 1 );
35746				const c = ( ix + 1 ) + gridX1 * ( iy + 1 );
35747				const d = ( ix + 1 ) + gridX1 * iy;
35748
35749				indices.push( a, b, d );
35750				indices.push( b, c, d );
35751
35752			}
35753
35754		}
35755
35756		this.setIndex( indices );
35757		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
35758		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
35759		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
35760
35761	}
35762
35763	copy( source ) {
35764
35765		super.copy( source );
35766
35767		this.parameters = Object.assign( {}, source.parameters );
35768
35769		return this;
35770
35771	}
35772
35773	/**
35774	 * Factory method for creating an instance of this class from the given
35775	 * JSON object.
35776	 *
35777	 * @param {Object} data - A JSON object representing the serialized geometry.
35778	 * @return {PlaneGeometry} A new instance.
35779	 */
35780	static fromJSON( data ) {
35781
35782		return new PlaneGeometry( data.width, data.height, data.widthSegments, data.heightSegments );
35783
35784	}
35785
35786}
35787
35788/**
35789 * A class for generating a two-dimensional ring geometry.
35790 *
35791 * ```js
35792 * const geometry = new THREE.RingGeometry( 1, 5, 32 );
35793 * const material = new THREE.MeshBasicMaterial( { color: 0xffff00, side: THREE.DoubleSide } );
35794 * const mesh = new THREE.Mesh( geometry, material );
35795 * scene.add( mesh );
35796 * ```
35797 *
35798 * @augments BufferGeometry
35799 * @demo scenes/geometry-browser.html#RingGeometry
35800 */
35801class RingGeometry extends BufferGeometry {
35802
35803	/**
35804	 * Constructs a new ring geometry.
35805	 *
35806	 * @param {number} [innerRadius=0.5] - The inner radius of the ring.
35807	 * @param {number} [outerRadius=1] - The outer radius of the ring.
35808	 * @param {number} [thetaSegments=32] - Number of segments. A higher number means the ring will be more round. Minimum is `3`.
35809	 * @param {number} [phiSegments=1] - Number of segments per ring segment. Minimum is `1`.
35810	 * @param {number} [thetaStart=0] - Starting angle in radians.
35811	 * @param {number} [thetaLength=Math.PI*2] - Central angle in radians.
35812	 */
35813	constructor( innerRadius = 0.5, outerRadius = 1, thetaSegments = 32, phiSegments = 1, thetaStart = 0, thetaLength = Math.PI * 2 ) {
35814
35815		super();
35816
35817		this.type = 'RingGeometry';
35818
35819		/**
35820		 * Holds the constructor parameters that have been
35821		 * used to generate the geometry. Any modification
35822		 * after instantiation does not change the geometry.
35823		 *
35824		 * @type {Object}
35825		 */
35826		this.parameters = {
35827			innerRadius: innerRadius,
35828			outerRadius: outerRadius,
35829			thetaSegments: thetaSegments,
35830			phiSegments: phiSegments,
35831			thetaStart: thetaStart,
35832			thetaLength: thetaLength
35833		};
35834
35835		thetaSegments = Math.max( 3, thetaSegments );
35836		phiSegments = Math.max( 1, phiSegments );
35837
35838		// buffers
35839
35840		const indices = [];
35841		const vertices = [];
35842		const normals = [];
35843		const uvs = [];
35844
35845		// some helper variables
35846
35847		let radius = innerRadius;
35848		const radiusStep = ( ( outerRadius - innerRadius ) / phiSegments );
35849		const vertex = new Vector3();
35850		const uv = new Vector2();
35851
35852		// generate vertices, normals and uvs
35853
35854		for ( let j = 0; j <= phiSegments; j ++ ) {
35855
35856			for ( let i = 0; i <= thetaSegments; i ++ ) {
35857
35858				// values are generate from the inside of the ring to the outside
35859
35860				const segment = thetaStart + i / thetaSegments * thetaLength;
35861
35862				// vertex
35863
35864				vertex.x = radius * Math.cos( segment );
35865				vertex.y = radius * Math.sin( segment );
35866
35867				vertices.push( vertex.x, vertex.y, vertex.z );
35868
35869				// normal
35870
35871				normals.push( 0, 0, 1 );
35872
35873				// uv
35874
35875				uv.x = ( vertex.x / outerRadius + 1 ) / 2;
35876				uv.y = ( vertex.y / outerRadius + 1 ) / 2;
35877
35878				uvs.push( uv.x, uv.y );
35879
35880			}
35881
35882			// increase the radius for next row of vertices
35883
35884			radius += radiusStep;
35885
35886		}
35887
35888		// indices
35889
35890		for ( let j = 0; j < phiSegments; j ++ ) {
35891
35892			const thetaSegmentLevel = j * ( thetaSegments + 1 );
35893
35894			for ( let i = 0; i < thetaSegments; i ++ ) {
35895
35896				const segment = i + thetaSegmentLevel;
35897
35898				const a = segment;
35899				const b = segment + thetaSegments + 1;
35900				const c = segment + thetaSegments + 2;
35901				const d = segment + 1;
35902
35903				// faces
35904
35905				indices.push( a, b, d );
35906				indices.push( b, c, d );
35907
35908			}
35909
35910		}
35911
35912		// build geometry
35913
35914		this.setIndex( indices );
35915		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
35916		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
35917		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
35918
35919	}
35920
35921	copy( source ) {
35922
35923		super.copy( source );
35924
35925		this.parameters = Object.assign( {}, source.parameters );
35926
35927		return this;
35928
35929	}
35930
35931	/**
35932	 * Factory method for creating an instance of this class from the given
35933	 * JSON object.
35934	 *
35935	 * @param {Object} data - A JSON object representing the serialized geometry.
35936	 * @return {RingGeometry} A new instance.
35937	 */
35938	static fromJSON( data ) {
35939
35940		return new RingGeometry( data.innerRadius, data.outerRadius, data.thetaSegments, data.phiSegments, data.thetaStart, data.thetaLength );
35941
35942	}
35943
35944}
35945
35946/**
35947 * Creates an one-sided polygonal geometry from one or more path shapes.
35948 *
35949 * ```js
35950 * const arcShape = new THREE.Shape()
35951 *	.moveTo( 5, 1 )
35952 *	.absarc( 1, 1, 4, 0, Math.PI * 2, false );
35953 *
35954 * const geometry = new THREE.ShapeGeometry( arcShape );
35955 * const material = new THREE.MeshBasicMaterial( { color: 0x00ff00, side: THREE.DoubleSide } );
35956 * const mesh = new THREE.Mesh( geometry, material ) ;
35957 * scene.add( mesh );
35958 * ```
35959 *
35960 * @augments BufferGeometry
35961 * @demo scenes/geometry-browser.html#ShapeGeometry
35962 */
35963class ShapeGeometry extends BufferGeometry {
35964
35965	/**
35966	 * Constructs a new shape geometry.
35967	 *
35968	 * @param {Shape|Array<Shape>} [shapes] - A shape or an array of shapes.
35969	 * @param {number} [curveSegments=12] - Number of segments per shape.
35970	 */
35971	constructor( shapes = new Shape( [ new Vector2( 0, 0.5 ), new Vector2( -0.5, -0.5 ), new Vector2( 0.5, -0.5 ) ] ), curveSegments = 12 ) {
35972
35973		super();
35974
35975		this.type = 'ShapeGeometry';
35976
35977		/**
35978		 * Holds the constructor parameters that have been
35979		 * used to generate the geometry. Any modification
35980		 * after instantiation does not change the geometry.
35981		 *
35982		 * @type {Object}
35983		 */
35984		this.parameters = {
35985			shapes: shapes,
35986			curveSegments: curveSegments
35987		};
35988
35989		// buffers
35990
35991		const indices = [];
35992		const vertices = [];
35993		const normals = [];
35994		const uvs = [];
35995
35996		// helper variables
35997
35998		let groupStart = 0;
35999		let groupCount = 0;
36000
36001		// allow single and array values for "shapes" parameter
36002
36003		if ( Array.isArray( shapes ) === false ) {
36004
36005			addShape( shapes );
36006
36007		} else {
36008
36009			for ( let i = 0; i < shapes.length; i ++ ) {
36010
36011				addShape( shapes[ i ] );
36012
36013				this.addGroup( groupStart, groupCount, i ); // enables MultiMaterial support
36014
36015				groupStart += groupCount;
36016				groupCount = 0;
36017
36018			}
36019
36020		}
36021
36022		// build geometry
36023
36024		this.setIndex( indices );
36025		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
36026		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
36027		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
36028
36029
36030		// helper functions
36031
36032		function addShape( shape ) {
36033
36034			const indexOffset = vertices.length / 3;
36035			const points = shape.extractPoints( curveSegments );
36036
36037			let shapeVertices = points.shape;
36038			const shapeHoles = points.holes;
36039
36040			// check direction of vertices
36041
36042			if ( ShapeUtils.isClockWise( shapeVertices ) === false ) {
36043
36044				shapeVertices = shapeVertices.reverse();
36045
36046			}
36047
36048			for ( let i = 0, l = shapeHoles.length; i < l; i ++ ) {
36049
36050				const shapeHole = shapeHoles[ i ];
36051
36052				if ( ShapeUtils.isClockWise( shapeHole ) === true ) {
36053
36054					shapeHoles[ i ] = shapeHole.reverse();
36055
36056				}
36057
36058			}
36059
36060			const faces = ShapeUtils.triangulateShape( shapeVertices, shapeHoles );
36061
36062			// join vertices of inner and outer paths to a single array
36063
36064			for ( let i = 0, l = shapeHoles.length; i < l; i ++ ) {
36065
36066				const shapeHole = shapeHoles[ i ];
36067				shapeVertices = shapeVertices.concat( shapeHole );
36068
36069			}
36070
36071			// vertices, normals, uvs
36072
36073			for ( let i = 0, l = shapeVertices.length; i < l; i ++ ) {
36074
36075				const vertex = shapeVertices[ i ];
36076
36077				vertices.push( vertex.x, vertex.y, 0 );
36078				normals.push( 0, 0, 1 );
36079				uvs.push( vertex.x, vertex.y ); // world uvs
36080
36081			}
36082
36083			// indices
36084
36085			for ( let i = 0, l = faces.length; i < l; i ++ ) {
36086
36087				const face = faces[ i ];
36088
36089				const a = face[ 0 ] + indexOffset;
36090				const b = face[ 1 ] + indexOffset;
36091				const c = face[ 2 ] + indexOffset;
36092
36093				indices.push( a, b, c );
36094				groupCount += 3;
36095
36096			}
36097
36098		}
36099
36100	}
36101
36102	copy( source ) {
36103
36104		super.copy( source );
36105
36106		this.parameters = Object.assign( {}, source.parameters );
36107
36108		return this;
36109
36110	}
36111
36112	toJSON() {
36113
36114		const data = super.toJSON();
36115
36116		const shapes = this.parameters.shapes;
36117
36118		return toJSON( shapes, data );
36119
36120	}
36121
36122	/**
36123	 * Factory method for creating an instance of this class from the given
36124	 * JSON object.
36125	 *
36126	 * @param {Object} data - A JSON object representing the serialized geometry.
36127	 * @param {Array<Shape>} shapes - An array of shapes.
36128	 * @return {ShapeGeometry} A new instance.
36129	 */
36130	static fromJSON( data, shapes ) {
36131
36132		const geometryShapes = [];
36133
36134		for ( let j = 0, jl = data.shapes.length; j < jl; j ++ ) {
36135
36136			const shape = shapes[ data.shapes[ j ] ];
36137
36138			geometryShapes.push( shape );
36139
36140		}
36141
36142		return new ShapeGeometry( geometryShapes, data.curveSegments );
36143
36144	}
36145
36146}
36147
36148function toJSON( shapes, data ) {
36149
36150	data.shapes = [];
36151
36152	if ( Array.isArray( shapes ) ) {
36153
36154		for ( let i = 0, l = shapes.length; i < l; i ++ ) {
36155
36156			const shape = shapes[ i ];
36157
36158			data.shapes.push( shape.uuid );
36159
36160		}
36161
36162	} else {
36163
36164		data.shapes.push( shapes.uuid );
36165
36166	}
36167
36168	return data;
36169
36170}
36171
36172/**
36173 * A class for generating a sphere geometry.
36174 *
36175 * ```js
36176 * const geometry = new THREE.SphereGeometry( 15, 32, 16 );
36177 * const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
36178 * const sphere = new THREE.Mesh( geometry, material );
36179 * scene.add( sphere );
36180 * ```
36181 *
36182 * @augments BufferGeometry
36183 * @demo scenes/geometry-browser.html#SphereGeometry
36184 */
36185class SphereGeometry extends BufferGeometry {
36186
36187	/**
36188	 * Constructs a new sphere geometry.
36189	 *
36190	 * @param {number} [radius=1] - The sphere radius.
36191	 * @param {number} [widthSegments=32] - The number of horizontal segments. Minimum value is `3`.
36192	 * @param {number} [heightSegments=16] - The number of vertical segments. Minimum value is `2`.
36193	 * @param {number} [phiStart=0] - The horizontal starting angle in radians.
36194	 * @param {number} [phiLength=Math.PI*2] - The horizontal sweep angle size.
36195	 * @param {number} [thetaStart=0] - The vertical starting angle in radians.
36196	 * @param {number} [thetaLength=Math.PI] - The vertical sweep angle size.
36197	 */
36198	constructor( radius = 1, widthSegments = 32, heightSegments = 16, phiStart = 0, phiLength = Math.PI * 2, thetaStart = 0, thetaLength = Math.PI ) {
36199
36200		super();
36201
36202		this.type = 'SphereGeometry';
36203
36204		/**
36205		 * Holds the constructor parameters that have been
36206		 * used to generate the geometry. Any modification
36207		 * after instantiation does not change the geometry.
36208		 *
36209		 * @type {Object}
36210		 */
36211		this.parameters = {
36212			radius: radius,
36213			widthSegments: widthSegments,
36214			heightSegments: heightSegments,
36215			phiStart: phiStart,
36216			phiLength: phiLength,
36217			thetaStart: thetaStart,
36218			thetaLength: thetaLength
36219		};
36220
36221		widthSegments = Math.max( 3, Math.floor( widthSegments ) );
36222		heightSegments = Math.max( 2, Math.floor( heightSegments ) );
36223
36224		const thetaEnd = Math.min( thetaStart + thetaLength, Math.PI );
36225
36226		let index = 0;
36227		const grid = [];
36228
36229		const vertex = new Vector3();
36230		const normal = new Vector3();
36231
36232		// buffers
36233
36234		const indices = [];
36235		const vertices = [];
36236		const normals = [];
36237		const uvs = [];
36238
36239		// generate vertices, normals and uvs
36240
36241		for ( let iy = 0; iy <= heightSegments; iy ++ ) {
36242
36243			const verticesRow = [];
36244
36245			const v = iy / heightSegments;
36246
36247			// special case for the poles
36248
36249			let uOffset = 0;
36250
36251			if ( iy === 0 && thetaStart === 0 ) {
36252
36253				uOffset = 0.5 / widthSegments;
36254
36255			} else if ( iy === heightSegments && thetaEnd === Math.PI ) {
36256
36257				uOffset = -0.5 / widthSegments;
36258
36259			}
36260
36261			for ( let ix = 0; ix <= widthSegments; ix ++ ) {
36262
36263				const u = ix / widthSegments;
36264
36265				// vertex
36266
36267				vertex.x = - radius * Math.cos( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
36268				vertex.y = radius * Math.cos( thetaStart + v * thetaLength );
36269				vertex.z = radius * Math.sin( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength
vendor: 34,031 bytes, lines 36269-37694
36269 );
36270
36271				vertices.push( vertex.x, vertex.y, vertex.z );
36272
36273				// normal
36274
36275				normal.copy( vertex ).normalize();
36276				normals.push( normal.x, normal.y, normal.z );
36277
36278				// uv
36279
36280				uvs.push( u + uOffset, 1 - v );
36281
36282				verticesRow.push( index ++ );
36283
36284			}
36285
36286			grid.push( verticesRow );
36287
36288		}
36289
36290		// indices
36291
36292		for ( let iy = 0; iy < heightSegments; iy ++ ) {
36293
36294			for ( let ix = 0; ix < widthSegments; ix ++ ) {
36295
36296				const a = grid[ iy ][ ix + 1 ];
36297				const b = grid[ iy ][ ix ];
36298				const c = grid[ iy + 1 ][ ix ];
36299				const d = grid[ iy + 1 ][ ix + 1 ];
36300
36301				if ( iy !== 0 || thetaStart > 0 ) indices.push( a, b, d );
36302				if ( iy !== heightSegments - 1 || thetaEnd < Math.PI ) indices.push( b, c, d );
36303
36304			}
36305
36306		}
36307
36308		// build geometry
36309
36310		this.setIndex( indices );
36311		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
36312		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
36313		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
36314
36315	}
36316
36317	copy( source ) {
36318
36319		super.copy( source );
36320
36321		this.parameters = Object.assign( {}, source.parameters );
36322
36323		return this;
36324
36325	}
36326
36327	/**
36328	 * Factory method for creating an instance of this class from the given
36329	 * JSON object.
36330	 *
36331	 * @param {Object} data - A JSON object representing the serialized geometry.
36332	 * @return {SphereGeometry} A new instance.
36333	 */
36334	static fromJSON( data ) {
36335
36336		return new SphereGeometry( data.radius, data.widthSegments, data.heightSegments, data.phiStart, data.phiLength, data.thetaStart, data.thetaLength );
36337
36338	}
36339
36340}
36341
36342/**
36343 * A geometry class for representing an tetrahedron.
36344 *
36345 * ```js
36346 * const geometry = new THREE.TetrahedronGeometry();
36347 * const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
36348 * const tetrahedron = new THREE.Mesh( geometry, material );
36349 * scene.add( tetrahedron );
36350 * ```
36351 *
36352 * @augments PolyhedronGeometry
36353 * @demo scenes/geometry-browser.html#TetrahedronGeometry
36354 */
36355class TetrahedronGeometry extends PolyhedronGeometry {
36356
36357	/**
36358	 * Constructs a new tetrahedron geometry.
36359	 *
36360	 * @param {number} [radius=1] - Radius of the tetrahedron.
36361	 * @param {number} [detail=0] - Setting this to a value greater than `0` adds vertices making it no longer a tetrahedron.
36362	 */
36363	constructor( radius = 1, detail = 0 ) {
36364
36365		const vertices = [
36366			1, 1, 1, 	-1, -1, 1, 	-1, 1, -1, 	1, -1, -1
36367		];
36368
36369		const indices = [
36370			2, 1, 0, 	0, 3, 2,	1, 3, 0,	2, 3, 1
36371		];
36372
36373		super( vertices, indices, radius, detail );
36374
36375		this.type = 'TetrahedronGeometry';
36376
36377		/**
36378		 * Holds the constructor parameters that have been
36379		 * used to generate the geometry. Any modification
36380		 * after instantiation does not change the geometry.
36381		 *
36382		 * @type {Object}
36383		 */
36384		this.parameters = {
36385			radius: radius,
36386			detail: detail
36387		};
36388
36389	}
36390
36391	/**
36392	 * Factory method for creating an instance of this class from the given
36393	 * JSON object.
36394	 *
36395	 * @param {Object} data - A JSON object representing the serialized geometry.
36396	 * @return {TetrahedronGeometry} A new instance.
36397	 */
36398	static fromJSON( data ) {
36399
36400		return new TetrahedronGeometry( data.radius, data.detail );
36401
36402	}
36403
36404}
36405
36406/**
36407 * A geometry class for representing an torus.
36408 *
36409 * ```js
36410 * const geometry = new THREE.TorusGeometry( 10, 3, 16, 100 );
36411 * const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
36412 * const torus = new THREE.Mesh( geometry, material );
36413 * scene.add( torus );
36414 * ```
36415 *
36416 * @augments BufferGeometry
36417 * @demo scenes/geometry-browser.html#TorusGeometry
36418 */
36419class TorusGeometry extends BufferGeometry {
36420
36421	/**
36422	 * Constructs a new torus geometry.
36423	 *
36424	 * @param {number} [radius=1] - Radius of the torus, from the center of the torus to the center of the tube.
36425	 * @param {number} [tube=0.4] - Radius of the tube. Must be smaller than `radius`.
36426	 * @param {number} [radialSegments=12] - The number of radial segments.
36427	 * @param {number} [tubularSegments=48] - The number of tubular segments.
36428	 * @param {number} [arc=Math.PI*2] - Central angle in radians.
36429	 * @param {number} [thetaStart=0] - Start of the tubular sweep in radians.
36430	 * @param {number} [thetaLength=Math.PI*2] - Length of the tubular sweep in radians.
36431	 */
36432	constructor( radius = 1, tube = 0.4, radialSegments = 12, tubularSegments = 48, arc = Math.PI * 2, thetaStart = 0, thetaLength = Math.PI * 2 ) {
36433
36434		super();
36435
36436		this.type = 'TorusGeometry';
36437
36438		/**
36439		 * Holds the constructor parameters that have been
36440		 * used to generate the geometry. Any modification
36441		 * after instantiation does not change the geometry.
36442		 *
36443		 * @type {Object}
36444		 */
36445		this.parameters = {
36446			radius: radius,
36447			tube: tube,
36448			radialSegments: radialSegments,
36449			tubularSegments: tubularSegments,
36450			arc: arc,
36451			thetaStart: thetaStart,
36452			thetaLength: thetaLength,
36453		};
36454
36455		radialSegments = Math.floor( radialSegments );
36456		tubularSegments = Math.floor( tubularSegments );
36457
36458		// buffers
36459
36460		const indices = [];
36461		const vertices = [];
36462		const normals = [];
36463		const uvs = [];
36464
36465		// helper variables
36466
36467		const center = new Vector3();
36468		const vertex = new Vector3();
36469		const normal = new Vector3();
36470
36471		// generate vertices, normals and uvs
36472
36473		for ( let j = 0; j <= radialSegments; j ++ ) {
36474
36475			const v = thetaStart + ( j / radialSegments ) * thetaLength;
36476
36477			for ( let i = 0; i <= tubularSegments; i ++ ) {
36478
36479				const u = i / tubularSegments * arc;
36480
36481				// vertex
36482
36483				vertex.x = ( radius + tube * Math.cos( v ) ) * Math.cos( u );
36484				vertex.y = ( radius + tube * Math.cos( v ) ) * Math.sin( u );
36485				vertex.z = tube * Math.sin( v );
36486
36487				vertices.push( vertex.x, vertex.y, vertex.z );
36488
36489				// normal
36490
36491				center.x = radius * Math.cos( u );
36492				center.y = radius * Math.sin( u );
36493				normal.subVectors( vertex, center ).normalize();
36494
36495				normals.push( normal.x, normal.y, normal.z );
36496
36497				// uv
36498
36499				uvs.push( i / tubularSegments );
36500				uvs.push( j / radialSegments );
36501
36502			}
36503
36504		}
36505
36506		// generate indices
36507
36508		for ( let j = 1; j <= radialSegments; j ++ ) {
36509
36510			for ( let i = 1; i <= tubularSegments; i ++ ) {
36511
36512				// indices
36513
36514				const a = ( tubularSegments + 1 ) * j + i - 1;
36515				const b = ( tubularSegments + 1 ) * ( j - 1 ) + i - 1;
36516				const c = ( tubularSegments + 1 ) * ( j - 1 ) + i;
36517				const d = ( tubularSegments + 1 ) * j + i;
36518
36519				// faces
36520
36521				indices.push( a, b, d );
36522				indices.push( b, c, d );
36523
36524			}
36525
36526		}
36527
36528		// build geometry
36529
36530		this.setIndex( indices );
36531		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
36532		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
36533		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
36534
36535	}
36536
36537	copy( source ) {
36538
36539		super.copy( source );
36540
36541		this.parameters = Object.assign( {}, source.parameters );
36542
36543		return this;
36544
36545	}
36546
36547	/**
36548	 * Factory method for creating an instance of this class from the given
36549	 * JSON object.
36550	 *
36551	 * @param {Object} data - A JSON object representing the serialized geometry.
36552	 * @return {TorusGeometry} A new instance.
36553	 */
36554	static fromJSON( data ) {
36555
36556		return new TorusGeometry( data.radius, data.tube, data.radialSegments, data.tubularSegments, data.arc );
36557
36558	}
36559
36560}
36561
36562/**
36563 * Creates a torus knot, the particular shape of which is defined by a pair
36564 * of coprime integers, p and q. If p and q are not coprime, the result will
36565 * be a torus link.
36566 *
36567 * ```js
36568 * const geometry = new THREE.TorusKnotGeometry( 10, 3, 100, 16 );
36569 * const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
36570 * const torusKnot = new THREE.Mesh( geometry, material );
36571 * scene.add( torusKnot );
36572 * ```
36573 *
36574 * @augments BufferGeometry
36575 * @demo scenes/geometry-browser.html#TorusKnotGeometry
36576 */
36577class TorusKnotGeometry extends BufferGeometry {
36578
36579	/**
36580	 * Constructs a new torus knot geometry.
36581	 *
36582	 * @param {number} [radius=1] - Radius of the torus knot.
36583	 * @param {number} [tube=0.4] - Radius of the tube.
36584	 * @param {number} [tubularSegments=64] - The number of tubular segments.
36585	 * @param {number} [radialSegments=8] - The number of radial segments.
36586	 * @param {number} [p=2] - This value determines, how many times the geometry winds around its axis of rotational symmetry.
36587	 * @param {number} [q=3] - This value determines, how many times the geometry winds around a circle in the interior of the torus.
36588	 */
36589	constructor( radius = 1, tube = 0.4, tubularSegments = 64, radialSegments = 8, p = 2, q = 3 ) {
36590
36591		super();
36592
36593		this.type = 'TorusKnotGeometry';
36594
36595		/**
36596		 * Holds the constructor parameters that have been
36597		 * used to generate the geometry. Any modification
36598		 * after instantiation does not change the geometry.
36599		 *
36600		 * @type {Object}
36601		 */
36602		this.parameters = {
36603			radius: radius,
36604			tube: tube,
36605			tubularSegments: tubularSegments,
36606			radialSegments: radialSegments,
36607			p: p,
36608			q: q
36609		};
36610
36611		tubularSegments = Math.floor( tubularSegments );
36612		radialSegments = Math.floor( radialSegments );
36613
36614		// buffers
36615
36616		const indices = [];
36617		const vertices = [];
36618		const normals = [];
36619		const uvs = [];
36620
36621		// helper variables
36622
36623		const vertex = new Vector3();
36624		const normal = new Vector3();
36625
36626		const P1 = new Vector3();
36627		const P2 = new Vector3();
36628
36629		const B = new Vector3();
36630		const T = new Vector3();
36631		const N = new Vector3();
36632
36633		// generate vertices, normals and uvs
36634
36635		for ( let i = 0; i <= tubularSegments; ++ i ) {
36636
36637			// the radian "u" is used to calculate the position on the torus curve of the current tubular segment
36638
36639			const u = i / tubularSegments * p * Math.PI * 2;
36640
36641			// now we calculate two points. P1 is our current position on the curve, P2 is a little farther ahead.
36642			// these points are used to create a special "coordinate space", which is necessary to calculate the correct vertex positions
36643
36644			calculatePositionOnCurve( u, p, q, radius, P1 );
36645			calculatePositionOnCurve( u + 0.01, p, q, radius, P2 );
36646
36647			// calculate orthonormal basis
36648
36649			T.subVectors( P2, P1 );
36650			N.addVectors( P2, P1 );
36651			B.crossVectors( T, N );
36652			N.crossVectors( B, T );
36653
36654			// normalize B, N. T can be ignored, we don't use it
36655
36656			B.normalize();
36657			N.normalize();
36658
36659			for ( let j = 0; j <= radialSegments; ++ j ) {
36660
36661				// now calculate the vertices. they are nothing more than an extrusion of the torus curve.
36662				// because we extrude a shape in the xy-plane, there is no need to calculate a z-value.
36663
36664				const v = j / radialSegments * Math.PI * 2;
36665				const cx = - tube * Math.cos( v );
36666				const cy = tube * Math.sin( v );
36667
36668				// now calculate the final vertex position.
36669				// first we orient the extrusion with our basis vectors, then we add it to the current position on the curve
36670
36671				vertex.x = P1.x + ( cx * N.x + cy * B.x );
36672				vertex.y = P1.y + ( cx * N.y + cy * B.y );
36673				vertex.z = P1.z + ( cx * N.z + cy * B.z );
36674
36675				vertices.push( vertex.x, vertex.y, vertex.z );
36676
36677				// normal (P1 is always the center/origin of the extrusion, thus we can use it to calculate the normal)
36678
36679				normal.subVectors( vertex, P1 ).normalize();
36680
36681				normals.push( normal.x, normal.y, normal.z );
36682
36683				// uv
36684
36685				uvs.push( i / tubularSegments );
36686				uvs.push( j / radialSegments );
36687
36688			}
36689
36690		}
36691
36692		// generate indices
36693
36694		for ( let j = 1; j <= tubularSegments; j ++ ) {
36695
36696			for ( let i = 1; i <= radialSegments; i ++ ) {
36697
36698				// indices
36699
36700				const a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 );
36701				const b = ( radialSegments + 1 ) * j + ( i - 1 );
36702				const c = ( radialSegments + 1 ) * j + i;
36703				const d = ( radialSegments + 1 ) * ( j - 1 ) + i;
36704
36705				// faces
36706
36707				indices.push( a, b, d );
36708				indices.push( b, c, d );
36709
36710			}
36711
36712		}
36713
36714		// build geometry
36715
36716		this.setIndex( indices );
36717		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
36718		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
36719		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
36720
36721		// this function calculates the current position on the torus curve
36722
36723		function calculatePositionOnCurve( u, p, q, radius, position ) {
36724
36725			const cu = Math.cos( u );
36726			const su = Math.sin( u );
36727			const quOverP = q / p * u;
36728			const cs = Math.cos( quOverP );
36729
36730			position.x = radius * ( 2 + cs ) * 0.5 * cu;
36731			position.y = radius * ( 2 + cs ) * su * 0.5;
36732			position.z = radius * Math.sin( quOverP ) * 0.5;
36733
36734		}
36735
36736	}
36737
36738	copy( source ) {
36739
36740		super.copy( source );
36741
36742		this.parameters = Object.assign( {}, source.parameters );
36743
36744		return this;
36745
36746	}
36747
36748	/**
36749	 * Factory method for creating an instance of this class from the given
36750	 * JSON object.
36751	 *
36752	 * @param {Object} data - A JSON object representing the serialized geometry.
36753	 * @return {TorusKnotGeometry} A new instance.
36754	 */
36755	static fromJSON( data ) {
36756
36757		return new TorusKnotGeometry( data.radius, data.tube, data.tubularSegments, data.radialSegments, data.p, data.q );
36758
36759	}
36760
36761}
36762
36763/**
36764 * Creates a tube that extrudes along a 3D curve.
36765 *
36766 * ```js
36767 * class CustomSinCurve extends THREE.Curve {
36768 *
36769 * 	getPoint( t, optionalTarget = new THREE.Vector3() ) {
36770 *
36771 * 		const tx = t * 3 - 1.5;
36772 * 		const ty = Math.sin( 2 * Math.PI * t );
36773 * 		const tz = 0;
36774 *
36775 * 		return optionalTarget.set( tx, ty, tz );
36776 * 	}
36777 *
36778 * }
36779 *
36780 * const path = new CustomSinCurve( 10 );
36781 * const geometry = new THREE.TubeGeometry( path, 20, 2, 8, false );
36782 * const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
36783 * const mesh = new THREE.Mesh( geometry, material );
36784 * scene.add( mesh );
36785 * ```
36786 *
36787 * @augments BufferGeometry
36788 * @demo scenes/geometry-browser.html#TubeGeometry
36789 */
36790class TubeGeometry extends BufferGeometry {
36791
36792	/**
36793	 * Constructs a new tube geometry.
36794	 *
36795	 * @param {Curve} [path=QuadraticBezierCurve3] - A 3D curve defining the path of the tube.
36796	 * @param {number} [tubularSegments=64] - The number of segments that make up the tube.
36797	 * @param {number} [radius=1] -The radius of the tube.
36798	 * @param {number} [radialSegments=8] - The number of segments that make up the cross-section.
36799	 * @param {boolean} [closed=false] - Whether the tube is closed or not.
36800	 */
36801	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 ) {
36802
36803		super();
36804
36805		this.type = 'TubeGeometry';
36806
36807		/**
36808		 * Holds the constructor parameters that have been
36809		 * used to generate the geometry. Any modification
36810		 * after instantiation does not change the geometry.
36811		 *
36812		 * @type {Object}
36813		 */
36814		this.parameters = {
36815			path: path,
36816			tubularSegments: tubularSegments,
36817			radius: radius,
36818			radialSegments: radialSegments,
36819			closed: closed
36820		};
36821
36822		const frames = path.computeFrenetFrames( tubularSegments, closed );
36823
36824		// expose internals
36825
36826		this.tangents = frames.tangents;
36827		this.normals = frames.normals;
36828		this.binormals = frames.binormals;
36829
36830		// helper variables
36831
36832		const vertex = new Vector3();
36833		const normal = new Vector3();
36834		const uv = new Vector2();
36835		let P = new Vector3();
36836
36837		// buffer
36838
36839		const vertices = [];
36840		const normals = [];
36841		const uvs = [];
36842		const indices = [];
36843
36844		// create buffer data
36845
36846		generateBufferData();
36847
36848		// build geometry
36849
36850		this.setIndex( indices );
36851		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
36852		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
36853		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
36854
36855		// functions
36856
36857		function generateBufferData() {
36858
36859			for ( let i = 0; i < tubularSegments; i ++ ) {
36860
36861				generateSegment( i );
36862
36863			}
36864
36865			// if the geometry is not closed, generate the last row of vertices and normals
36866			// at the regular position on the given path
36867			//
36868			// if the geometry is closed, duplicate the first row of vertices and normals (uvs will differ)
36869
36870			generateSegment( ( closed === false ) ? tubularSegments : 0 );
36871
36872			// uvs are generated in a separate function.
36873			// this makes it easy compute correct values for closed geometries
36874
36875			generateUVs();
36876
36877			// finally create faces
36878
36879			generateIndices();
36880
36881		}
36882
36883		function generateSegment( i ) {
36884
36885			// we use getPointAt to sample evenly distributed points from the given path
36886
36887			P = path.getPointAt( i / tubularSegments, P );
36888
36889			// retrieve corresponding normal and binormal
36890
36891			const N = frames.normals[ i ];
36892			const B = frames.binormals[ i ];
36893
36894			// generate normals and vertices for the current segment
36895
36896			for ( let j = 0; j <= radialSegments; j ++ ) {
36897
36898				const v = j / radialSegments * Math.PI * 2;
36899
36900				const sin = Math.sin( v );
36901				const cos = - Math.cos( v );
36902
36903				// normal
36904
36905				normal.x = ( cos * N.x + sin * B.x );
36906				normal.y = ( cos * N.y + sin * B.y );
36907				normal.z = ( cos * N.z + sin * B.z );
36908				normal.normalize();
36909
36910				normals.push( normal.x, normal.y, normal.z );
36911
36912				// vertex
36913
36914				vertex.x = P.x + radius * normal.x;
36915				vertex.y = P.y + radius * normal.y;
36916				vertex.z = P.z + radius * normal.z;
36917
36918				vertices.push( vertex.x, vertex.y, vertex.z );
36919
36920			}
36921
36922		}
36923
36924		function generateIndices() {
36925
36926			for ( let j = 1; j <= tubularSegments; j ++ ) {
36927
36928				for ( let i = 1; i <= radialSegments; i ++ ) {
36929
36930					const a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 );
36931					const b = ( radialSegments + 1 ) * j + ( i - 1 );
36932					const c = ( radialSegments + 1 ) * j + i;
36933					const d = ( radialSegments + 1 ) * ( j - 1 ) + i;
36934
36935					// faces
36936
36937					indices.push( a, b, d );
36938					indices.push( b, c, d );
36939
36940				}
36941
36942			}
36943
36944		}
36945
36946		function generateUVs() {
36947
36948			for ( let i = 0; i <= tubularSegments; i ++ ) {
36949
36950				for ( let j = 0; j <= radialSegments; j ++ ) {
36951
36952					uv.x = i / tubularSegments;
36953					uv.y = j / radialSegments;
36954
36955					uvs.push( uv.x, uv.y );
36956
36957				}
36958
36959			}
36960
36961		}
36962
36963	}
36964
36965	copy( source ) {
36966
36967		super.copy( source );
36968
36969		this.parameters = Object.assign( {}, source.parameters );
36970
36971		return this;
36972
36973	}
36974
36975	toJSON() {
36976
36977		const data = super.toJSON();
36978
36979		data.path = this.parameters.path.toJSON();
36980
36981		return data;
36982
36983	}
36984
36985	/**
36986	 * Factory method for creating an instance of this class from the given
36987	 * JSON object.
36988	 *
36989	 * @param {Object} data - A JSON object representing the serialized geometry.
36990	 * @return {TubeGeometry} A new instance.
36991	 */
36992	static fromJSON( data ) {
36993
36994		// This only works for built-in curves (e.g. CatmullRomCurve3).
36995		// User defined curves or instances of CurvePath will not be deserialized.
36996		return new TubeGeometry(
36997			new Curves[ data.path.type ]().fromJSON( data.path ),
36998			data.tubularSegments,
36999			data.radius,
37000			data.radialSegments,
37001			data.closed
37002		);
37003
37004	}
37005
37006}
37007
37008/**
37009 * Can be used as a helper object to visualize a geometry as a wireframe.
37010 *
37011 * ```js
37012 * const geometry = new THREE.SphereGeometry();
37013 *
37014 * const wireframe = new THREE.WireframeGeometry( geometry );
37015 *
37016 * const line = new THREE.LineSegments( wireframe );
37017 * line.material.depthWrite = false;
37018 * line.material.opacity = 0.25;
37019 * line.material.transparent = true;
37020 *
37021 * scene.add( line );
37022 * ```
37023 *
37024 * Note: It is not yet possible to serialize/deserialize instances of this class.
37025 *
37026 * @augments BufferGeometry
37027 */
37028class WireframeGeometry extends BufferGeometry {
37029
37030	/**
37031	 * Constructs a new wireframe geometry.
37032	 *
37033	 * @param {?BufferGeometry} [geometry=null] - The geometry.
37034	 */
37035	constructor( geometry = null ) {
37036
37037		super();
37038
37039		this.type = 'WireframeGeometry';
37040
37041		/**
37042		 * Holds the constructor parameters that have been
37043		 * used to generate the geometry. Any modification
37044		 * after instantiation does not change the geometry.
37045		 *
37046		 * @type {Object}
37047		 */
37048		this.parameters = {
37049			geometry: geometry
37050		};
37051
37052		if ( geometry !== null ) {
37053
37054			// buffer
37055
37056			const vertices = [];
37057			const edges = new Set();
37058
37059			// helper variables
37060
37061			const start = new Vector3();
37062			const end = new Vector3();
37063
37064			if ( geometry.index !== null ) {
37065
37066				// indexed BufferGeometry
37067
37068				const position = geometry.attributes.position;
37069				const indices = geometry.index;
37070				let groups = geometry.groups;
37071
37072				if ( groups.length === 0 ) {
37073
37074					groups = [ { start: 0, count: indices.count, materialIndex: 0 } ];
37075
37076				}
37077
37078				// create a data structure that contains all edges without duplicates
37079
37080				for ( let o = 0, ol = groups.length; o < ol; ++ o ) {
37081
37082					const group = groups[ o ];
37083
37084					const groupStart = group.start;
37085					const groupCount = group.count;
37086
37087					for ( let i = groupStart, l = ( groupStart + groupCount ); i < l; i += 3 ) {
37088
37089						for ( let j = 0; j < 3; j ++ ) {
37090
37091							const index1 = indices.getX( i + j );
37092							const index2 = indices.getX( i + ( j + 1 ) % 3 );
37093
37094							start.fromBufferAttribute( position, index1 );
37095							end.fromBufferAttribute( position, index2 );
37096
37097							if ( isUniqueEdge( start, end, edges ) === true ) {
37098
37099								vertices.push( start.x, start.y, start.z );
37100								vertices.push( end.x, end.y, end.z );
37101
37102							}
37103
37104						}
37105
37106					}
37107
37108				}
37109
37110			} else {
37111
37112				// non-indexed BufferGeometry
37113
37114				const position = geometry.attributes.position;
37115
37116				for ( let i = 0, l = ( position.count / 3 ); i < l; i ++ ) {
37117
37118					for ( let j = 0; j < 3; j ++ ) {
37119
37120						// three edges per triangle, an edge is represented as (index1, index2)
37121						// e.g. the first triangle has the following edges: (0,1),(1,2),(2,0)
37122
37123						const index1 = 3 * i + j;
37124						const index2 = 3 * i + ( ( j + 1 ) % 3 );
37125
37126						start.fromBufferAttribute( position, index1 );
37127						end.fromBufferAttribute( position, index2 );
37128
37129						if ( isUniqueEdge( start, end, edges ) === true ) {
37130
37131							vertices.push( start.x, start.y, start.z );
37132							vertices.push( end.x, end.y, end.z );
37133
37134						}
37135
37136					}
37137
37138				}
37139
37140			}
37141
37142			// build geometry
37143
37144			this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
37145
37146		}
37147
37148	}
37149
37150	copy( source ) {
37151
37152		super.copy( source );
37153
37154		this.parameters = Object.assign( {}, source.parameters );
37155
37156		return this;
37157
37158	}
37159
37160}
37161
37162function isUniqueEdge( start, end, edges ) {
37163
37164	const hash1 = `${start.x},${start.y},${start.z}-${end.x},${end.y},${end.z}`;
37165	const hash2 = `${end.x},${end.y},${end.z}-${start.x},${start.y},${start.z}`; // coincident edge
37166
37167	if ( edges.has( hash1 ) === true || edges.has( hash2 ) === true ) {
37168
37169		return false;
37170
37171	} else {
37172
37173		edges.add( hash1 );
37174		edges.add( hash2 );
37175		return true;
37176
37177	}
37178
37179}
37180
37181var Geometries = /*#__PURE__*/Object.freeze({
37182	__proto__: null,
37183	BoxGeometry: BoxGeometry,
37184	CapsuleGeometry: CapsuleGeometry,
37185	CircleGeometry: CircleGeometry,
37186	ConeGeometry: ConeGeometry,
37187	CylinderGeometry: CylinderGeometry,
37188	DodecahedronGeometry: DodecahedronGeometry,
37189	EdgesGeometry: EdgesGeometry,
37190	ExtrudeGeometry: ExtrudeGeometry,
37191	IcosahedronGeometry: IcosahedronGeometry,
37192	LatheGeometry: LatheGeometry,
37193	OctahedronGeometry: OctahedronGeometry,
37194	PlaneGeometry: PlaneGeometry,
37195	PolyhedronGeometry: PolyhedronGeometry,
37196	RingGeometry: RingGeometry,
37197	ShapeGeometry: ShapeGeometry,
37198	SphereGeometry: SphereGeometry,
37199	TetrahedronGeometry: TetrahedronGeometry,
37200	TorusGeometry: TorusGeometry,
37201	TorusKnotGeometry: TorusKnotGeometry,
37202	TubeGeometry: TubeGeometry,
37203	WireframeGeometry: WireframeGeometry
37204});
37205
37206/**
37207 * This material can receive shadows, but otherwise is completely transparent.
37208 *
37209 * ```js
37210 * const geometry = new THREE.PlaneGeometry( 2000, 2000 );
37211 * geometry.rotateX( - Math.PI / 2 );
37212 *
37213 * const material = new THREE.ShadowMaterial();
37214 * material.opacity = 0.2;
37215 *
37216 * const plane = new THREE.Mesh( geometry, material );
37217 * plane.position.y = -200;
37218 * plane.receiveShadow = true;
37219 * scene.add( plane );
37220 * ```
37221 *
37222 * @augments Material
37223 */
37224class ShadowMaterial extends Material {
37225
37226	/**
37227	 * Constructs a new shadow material.
37228	 *
37229	 * @param {Object} [parameters] - An object with one or more properties
37230	 * defining the material's appearance. Any property of the material
37231	 * (including any property from inherited materials) can be passed
37232	 * in here. Color values can be passed any type of value accepted
37233	 * by {@link Color#set}.
37234	 */
37235	constructor( parameters ) {
37236
37237		super();
37238
37239		/**
37240		 * This flag can be used for type testing.
37241		 *
37242		 * @type {boolean}
37243		 * @readonly
37244		 * @default true
37245		 */
37246		this.isShadowMaterial = true;
37247
37248		this.type = 'ShadowMaterial';
37249
37250		/**
37251		 * Color of the material.
37252		 *
37253		 * @type {Color}
37254		 * @default (0,0,0)
37255		 */
37256		this.color = new Color( 0x000000 );
37257
37258		/**
37259		 * Overwritten since shadow materials are transparent
37260		 * by default.
37261		 *
37262		 * @type {boolean}
37263		 * @default true
37264		 */
37265		this.transparent = true;
37266
37267		/**
37268		 * Whether the material is affected by fog or not.
37269		 *
37270		 * @type {boolean}
37271		 * @default true
37272		 */
37273		this.fog = true;
37274
37275		this.setValues( parameters );
37276
37277	}
37278
37279	copy( source ) {
37280
37281		super.copy( source );
37282
37283		this.color.copy( source.color );
37284
37285		this.fog = source.fog;
37286
37287		return this;
37288
37289	}
37290
37291}
37292
37293/**
37294 * Provides utility functions for managing uniforms.
37295 *
37296 * @module UniformsUtils
37297 */
37298
37299/**
37300 * Clones the given uniform definitions by performing a deep-copy. That means
37301 * if the value of a uniform refers to an object like a Vector3 or Texture,
37302 * the cloned uniform will refer to a new object reference.
37303 *
37304 * @param {Object} src - An object representing uniform definitions.
37305 * @return {Object} The cloned uniforms.
37306 */
37307function cloneUniforms( src ) {
37308
37309	const dst = {};
37310
37311	for ( const u in src ) {
37312
37313		dst[ u ] = {};
37314
37315		for ( const p in src[ u ] ) {
37316
37317			const property = src[ u ][ p ];
37318
37319			if ( isThreeObject( property ) ) {
37320
37321				if ( property.isRenderTargetTexture ) {
37322
37323					warn( 'UniformsUtils: Textures of render targets cannot be cloned via cloneUniforms() or mergeUniforms().' );
37324					dst[ u ][ p ] = null;
37325
37326				} else {
37327
37328					dst[ u ][ p ] = property.clone();
37329
37330				}
37331
37332			} else if ( Array.isArray( property ) ) {
37333
37334				if ( isThreeObject( property[ 0 ] ) ) {
37335
37336					const clonedProperty = [];
37337
37338					for ( let i = 0, l = property.length; i < l; i ++ ) {
37339
37340						clonedProperty[ i ] = property[ i ].clone();
37341
37342					}
37343
37344					dst[ u ][ p ] = clonedProperty;
37345
37346				} else {
37347
37348					dst[ u ][ p ] = property.slice();
37349
37350				}
37351
37352			} else {
37353
37354				dst[ u ][ p ] = property;
37355
37356			}
37357
37358		}
37359
37360	}
37361
37362	return dst;
37363
37364}
37365
37366/**
37367 * Merges the given uniform definitions into a single object. Since the
37368 * method internally uses cloneUniforms(), it performs a deep-copy when
37369 * producing the merged uniform definitions.
37370 *
37371 * @param {Array} uniforms - An array of objects containing uniform definitions.
37372 * @return {Object} The merged uniforms.
37373 */
37374function mergeUniforms( uniforms ) {
37375
37376	const merged = {};
37377
37378	for ( let u = 0; u < uniforms.length; u ++ ) {
37379
37380		const tmp = cloneUniforms( uniforms[ u ] );
37381
37382		for ( const p in tmp ) {
37383
37384			merged[ p ] = tmp[ p ];
37385
37386		}
37387
37388	}
37389
37390	return merged;
37391
37392}
37393
37394function isThreeObject( property ) {
37395
37396	return ( property && ( property.isColor ||
37397		property.isMatrix3 || property.isMatrix4 ||
37398		property.isVector2 || property.isVector3 || property.isVector4 ||
37399		property.isTexture || property.isQuaternion ) );
37400
37401}
37402
37403function cloneUniformsGroups( src ) {
37404
37405	const dst = [];
37406
37407	for ( let u = 0; u < src.length; u ++ ) {
37408
37409		dst.push( src[ u ].clone() );
37410
37411	}
37412
37413	return dst;
37414
37415}
37416
37417function getUnlitUniformColorSpace( renderer ) {
37418
37419	const currentRenderTarget = renderer.getRenderTarget();
37420
37421	if ( currentRenderTarget === null ) {
37422
37423		// https://github.com/mrdoob/three.js/pull/23937#issuecomment-1111067398
37424		return renderer.outputColorSpace;
37425
37426	}
37427
37428	// https://github.com/mrdoob/three.js/issues/27868
37429	if ( currentRenderTarget.isXRRenderTarget === true ) {
37430
37431		return currentRenderTarget.texture.colorSpace;
37432
37433	}
37434
37435	return ColorManagement.workingColorSpace;
37436
37437}
37438
37439// Legacy
37440
37441const UniformsUtils = { clone: cloneUniforms, merge: mergeUniforms };
37442
37443var default_vertex = "void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}";
37444
37445var default_fragment = "void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}";
37446
37447/**
37448 * A material rendered with custom shaders. A shader is a small program written in GLSL.
37449 * that runs on the GPU. You may want to use a custom shader if you need to implement an
37450 * effect not included with any of the built-in materials.
37451 *
37452 * There are the following notes to bear in mind when using a `ShaderMaterial`:
37453 *
37454 * - `ShaderMaterial` can only be used with {@link WebGLRenderer}.
37455 * - Built in attributes and uniforms are passed to the shaders along with your code. If
37456 * you don't want that, use {@link RawShaderMaterial} instead.
37457 * - You can use the directive `#pragma unroll_loop_start` and `#pragma unroll_loop_end`
37458 * in order to unroll a `for` loop in GLSL by the shader preprocessor. The directive has
37459 * to be placed right above the loop. The loop formatting has to correspond to a defined standard.
37460 *   - The loop has to be [normalized](https://en.wikipedia.org/wiki/Normalized_loop).
37461 *   - The loop variable has to be *i*.
37462 *   - The value `UNROLLED_LOOP_INDEX` will be replaced with the explicitly
37463 * value of *i* for the given iteration and can be used in preprocessor
37464 * statements.
37465 *
37466 * ```js
37467 * const material = new THREE.ShaderMaterial( {
37468 * 	uniforms: {
37469 * 		time: { value: 1.0 },
37470 * 		resolution: { value: new THREE.Vector2() }
37471 * 	},
37472 * 	vertexShader: document.getElementById( 'vertexShader' ).textContent,
37473 * 	fragmentShader: document.getElementById( 'fragmentShader' ).textContent
37474 * } );
37475 * ```
37476 *
37477 * @augments Material
37478 */
37479class ShaderMaterial extends Material {
37480
37481	/**
37482	 * Constructs a new shader material.
37483	 *
37484	 * @param {Object} [parameters] - An object with one or more properties
37485	 * defining the material's appearance. Any property of the material
37486	 * (including any property from inherited materials) can be passed
37487	 * in here. Color values can be passed any type of value accepted
37488	 * by {@link Color#set}.
37489	 */
37490	constructor( parameters ) {
37491
37492		super();
37493
37494		/**
37495		 * This flag can be used for type testing.
37496		 *
37497		 * @type {boolean}
37498		 * @readonly
37499		 * @default true
37500		 */
37501		this.isShaderMaterial = true;
37502
37503		this.type = 'ShaderMaterial';
37504
37505		/**
37506		 * Defines custom constants using `#define` directives within the GLSL code
37507		 * for both the vertex shader and the fragment shader; each key/value pair
37508		 * yields another directive.
37509		 * ```js
37510		 * defines: {
37511		 * 	FOO: 15,
37512		 * 	BAR: true
37513		 * }
37514		 * ```
37515		 * Yields the lines:
37516		 * ```
37517		 * #define FOO 15
37518		 * #define BAR true
37519		 * ```
37520		 *
37521		 * @type {Object}
37522		 */
37523		this.defines = {};
37524
37525		/**
37526		 * An object of the form:
37527		 * ```js
37528		 * {
37529		 * 	"uniform1": { value: 1.0 },
37530		 * 	"uniform2": { value: 2 }
37531		 * }
37532		 * ```
37533		 * specifying the uniforms to be passed to the shader code; keys are uniform
37534		 * names, values are definitions of the form
37535		 * ```
37536		 * {
37537		 * 	value: 1.0
37538		 * }
37539		 * ```
37540		 * where `value` is the value of the uniform. Names must match the name of
37541		 * the uniform, as defined in the GLSL code. Note that uniforms are refreshed
37542		 * on every frame, so updating the value of the uniform will immediately
37543		 * update the value available to the GLSL code.
37544		 *
37545		 * @type {Object}
37546		 */
37547		this.uniforms = {};
37548
37549		/**
37550		 * An array holding uniforms groups for configuring UBOs.
37551		 *
37552		 * @type {Array<UniformsGroup>}
37553		 */
37554		this.uniformsGroups = [];
37555
37556		/**
37557		 * Vertex shader GLSL code. This is the actual code for the shader.
37558		 *
37559		 * @type {string}
37560		 */
37561		this.vertexShader = default_vertex;
37562
37563		/**
37564		 * Fragment shader GLSL code. This is the actual code for the shader.
37565		 *
37566		 * @type {string}
37567		 */
37568		this.fragmentShader = default_fragment;
37569
37570		/**
37571		 * Controls line thickness or lines.
37572		 *
37573		 * WebGL and WebGPU ignore this setting and always render line primitives with a
37574		 * width of one pixel.
37575		 *
37576		 * @type {number}
37577		 * @default 1
37578		 */
37579		this.linewidth = 1;
37580
37581		/**
37582		 * Renders the geometry as a wireframe.
37583		 *
37584		 * @type {boolean}
37585		 * @default false
37586		 */
37587		this.wireframe = false;
37588
37589		/**
37590		 * Controls the thickness of the wireframe.
37591		 *
37592		 * WebGL and WebGPU ignore this property and always render
37593		 * 1 pixel wide lines.
37594		 *
37595		 * @type {number}
37596		 * @default 1
37597		 */
37598		this.wireframeLinewidth = 1;
37599
37600		/**
37601		 * Defines whether the material color is affected by global fog settings; `true`
37602		 * to pass fog uniforms to the shader.
37603		 *
37604		 * Setting this property to `true` requires the definition of fog uniforms. It is
37605		 * recommended to use `UniformsUtils.merge()` to combine the custom shader uniforms
37606		 * with predefined fog uniforms.
37607		 *
37608		 * ```js
37609		 * const material = new ShaderMaterial( {
37610		 *     uniforms: UniformsUtils.merge( [ UniformsLib[ 'fog' ], shaderUniforms ] );
37611		 *     vertexShader: vertexShader,
37612		 *     fragmentShader: fragmentShader,
37613		 *     fog: true
37614		 * } );
37615		 * ```
37616		 *
37617		 * @type {boolean}
37618		 * @default false
37619		 */
37620		this.fog = false;
37621
37622		/**
37623		 * Defines whether this material uses lighting; `true` to pass uniform data
37624		 * related to lighting to this shader.
37625		 *
37626		 * @type {boolean}
37627		 * @default false
37628		 */
37629		this.lights = false;
37630
37631		/**
37632		 * Defines whether this material supports clipping; `true` to let the renderer
37633		 * pass the clippingPlanes uniform.
37634		 *
37635		 * @type {boolean}
37636		 * @default false
37637		 */
37638		this.clipping = false;
37639
37640		/**
37641		 * Overwritten and set to `true` by default.
37642		 *
37643		 * @type {boolean}
37644		 * @default true
37645		 */
37646		this.forceSinglePass = true;
37647
37648		/**
37649		 * This object allows to enable certain WebGL 2 extensions.
37650		 *
37651		 * - clipCullDistance: set to `true` to use vertex shader clipping
37652		 * - multiDraw: set to `true` to use vertex shader multi_draw / enable gl_DrawID
37653		 *
37654		 * @type {{clipCullDistance:false,multiDraw:false}}
37655		 */
37656		this.extensions = {
37657			clipCullDistance: false, // set to use vertex shader clipping
37658			multiDraw: false // set to use vertex shader multi_draw / enable gl_DrawID
37659		};
37660
37661		/**
37662		 * When the rendered geometry doesn't include these attributes but the
37663		 * material does, these default values will be passed to the shaders. This
37664		 * avoids errors when buffer data is missing.
37665		 *
37666		 * - color: [ 1, 1, 1 ]
37667		 * - uv: [ 0, 0 ]
37668		 * - uv1: [ 0, 0 ]
37669		 *
37670		 * @type {Object}
37671		 */
37672		this.defaultAttributeValues = {
37673			'color': [ 1, 1, 1 ],
37674			'uv': [ 0, 0 ],
37675			'uv1': [ 0, 0 ]
37676		};
37677
37678		/**
37679		 * If set, this calls [gl.bindAttribLocation](https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bindAttribLocation)
37680		 * to bind a generic vertex index to an attribute variable.
37681		 *
37682		 * @type {string|undefined}
37683		 * @default undefined
37684		 */
37685		this.index0AttributeName = undefined;
37686
37687		/**
37688		 * Can be used to force a uniform update while changing uniforms in
37689		 * {@link Object3D#onBeforeRender}.
37690		 *
37691		 * @type {boolean}
37692		 * @default false
37693		 */
37694		this.uniformsNeedUpdate = false;
vendor: 28,443 bytes, lines 37695-38830
37695
37696		/**
37697		 * Defines the GLSL version of custom shader code.
37698		 *
37699		 * @type {?(GLSL1|GLSL3)}
37700		 * @default null
37701		 */
37702		this.glslVersion = null;
37703
37704		if ( parameters !== undefined ) {
37705
37706			this.setValues( parameters );
37707
37708		}
37709
37710	}
37711
37712	copy( source ) {
37713
37714		super.copy( source );
37715
37716		this.fragmentShader = source.fragmentShader;
37717		this.vertexShader = source.vertexShader;
37718
37719		this.uniforms = cloneUniforms( source.uniforms );
37720		this.uniformsGroups = cloneUniformsGroups( source.uniformsGroups );
37721
37722		this.defines = Object.assign( {}, source.defines );
37723
37724		this.wireframe = source.wireframe;
37725		this.wireframeLinewidth = source.wireframeLinewidth;
37726
37727		this.fog = source.fog;
37728		this.lights = source.lights;
37729		this.clipping = source.clipping;
37730
37731		this.extensions = Object.assign( {}, source.extensions );
37732
37733		this.glslVersion = source.glslVersion;
37734
37735		this.defaultAttributeValues = Object.assign( {}, source.defaultAttributeValues );
37736
37737		this.index0AttributeName = source.index0AttributeName;
37738
37739		this.uniformsNeedUpdate = source.uniformsNeedUpdate;
37740
37741		return this;
37742
37743	}
37744
37745	toJSON( meta ) {
37746
37747		const data = super.toJSON( meta );
37748
37749		data.glslVersion = this.glslVersion;
37750		data.uniforms = {};
37751
37752		for ( const name in this.uniforms ) {
37753
37754			const uniform = this.uniforms[ name ];
37755			const value = uniform.value;
37756
37757			if ( value && value.isTexture ) {
37758
37759				data.uniforms[ name ] = {
37760					type: 't',
37761					value: value.toJSON( meta ).uuid
37762				};
37763
37764			} else if ( value && value.isColor ) {
37765
37766				data.uniforms[ name ] = {
37767					type: 'c',
37768					value: value.getHex()
37769				};
37770
37771			} else if ( value && value.isVector2 ) {
37772
37773				data.uniforms[ name ] = {
37774					type: 'v2',
37775					value: value.toArray()
37776				};
37777
37778			} else if ( value && value.isVector3 ) {
37779
37780				data.uniforms[ name ] = {
37781					type: 'v3',
37782					value: value.toArray()
37783				};
37784
37785			} else if ( value && value.isVector4 ) {
37786
37787				data.uniforms[ name ] = {
37788					type: 'v4',
37789					value: value.toArray()
37790				};
37791
37792			} else if ( value && value.isMatrix3 ) {
37793
37794				data.uniforms[ name ] = {
37795					type: 'm3',
37796					value: value.toArray()
37797				};
37798
37799			} else if ( value && value.isMatrix4 ) {
37800
37801				data.uniforms[ name ] = {
37802					type: 'm4',
37803					value: value.toArray()
37804				};
37805
37806			} else {
37807
37808				data.uniforms[ name ] = {
37809					value: value
37810				};
37811
37812				// note: the array variants v2v, v3v, v4v, m4v and tv are not supported so far
37813
37814			}
37815
37816		}
37817
37818		if ( Object.keys( this.defines ).length > 0 ) data.defines = this.defines;
37819
37820		data.vertexShader = this.vertexShader;
37821		data.fragmentShader = this.fragmentShader;
37822
37823		data.lights = this.lights;
37824		data.clipping = this.clipping;
37825
37826		const extensions = {};
37827
37828		for ( const key in this.extensions ) {
37829
37830			if ( this.extensions[ key ] === true ) extensions[ key ] = true;
37831
37832		}
37833
37834		if ( Object.keys( extensions ).length > 0 ) data.extensions = extensions;
37835
37836		return data;
37837
37838	}
37839
37840}
37841
37842/**
37843 * This class works just like {@link ShaderMaterial}, except that definitions
37844 * of built-in uniforms and attributes are not automatically prepended to the
37845 * GLSL shader code.
37846 *
37847 * `RawShaderMaterial` can only be used with {@link WebGLRenderer}.
37848 *
37849 * @augments ShaderMaterial
37850 */
37851class RawShaderMaterial extends ShaderMaterial {
37852
37853	/**
37854	 * Constructs a new raw shader material.
37855	 *
37856	 * @param {Object} [parameters] - An object with one or more properties
37857	 * defining the material's appearance. Any property of the material
37858	 * (including any property from inherited materials) can be passed
37859	 * in here. Color values can be passed any type of value accepted
37860	 * by {@link Color#set}.
37861	 */
37862	constructor( parameters ) {
37863
37864		super( parameters );
37865
37866		/**
37867		 * This flag can be used for type testing.
37868		 *
37869		 * @type {boolean}
37870		 * @readonly
37871		 * @default true
37872		 */
37873		this.isRawShaderMaterial = true;
37874
37875		this.type = 'RawShaderMaterial';
37876
37877	}
37878
37879}
37880
37881/**
37882 * A standard physically based material, using Metallic-Roughness workflow.
37883 *
37884 * Physically based rendering (PBR) has recently become the standard in many
37885 * 3D applications, such as [Unity](https://blogs.unity3d.com/2014/10/29/physically-based-shading-in-unity-5-a-primer/),
37886 * [Unreal](https://docs.unrealengine.com/latest/INT/Engine/Rendering/Materials/PhysicallyBased/) and
37887 * [3D Studio Max](http://area.autodesk.com/blogs/the-3ds-max-blog/what039s-new-for-rendering-in-3ds-max-2017).
37888 *
37889 * This approach differs from older approaches in that instead of using
37890 * approximations for the way in which light interacts with a surface, a
37891 * physically correct model is used. The idea is that, instead of tweaking
37892 * materials to look good under specific lighting, a material can be created
37893 * that will react 'correctly' under all lighting scenarios.
37894 *
37895 * In practice this gives a more accurate and realistic looking result than
37896 * the {@link MeshLambertMaterial} or {@link MeshPhongMaterial}, at the cost of
37897 * being somewhat more computationally expensive. `MeshStandardMaterial` uses per-fragment
37898 * shading.
37899 *
37900 * Note that for best results you should always specify an environment map when using this material.
37901 *
37902 * For a non-technical introduction to the concept of PBR and how to set up a
37903 * PBR material, check out these articles by the people at [marmoset](https://www.marmoset.co):
37904 *
37905 * - [Basic Theory of Physically Based Rendering](https://www.marmoset.co/posts/basic-theory-of-physically-based-rendering/)
37906 * - [Physically Based Rendering and You Can Too](https://www.marmoset.co/posts/physically-based-rendering-and-you-can-too/)
37907 *
37908 * Technical details of the approach used in three.js (and most other PBR systems) can be found is this
37909 * [paper from Disney](https://media.disneyanimation.com/uploads/production/publication_asset/48/asset/s2012_pbs_disney_brdf_notes_v3.pdf)
37910 * (pdf), by Brent Burley.
37911 *
37912 * @augments Material
37913 * @demo scenes/material-browser.html#MeshStandardMaterial
37914 */
37915class MeshStandardMaterial extends Material {
37916
37917	/**
37918	 * Constructs a new mesh standard material.
37919	 *
37920	 * @param {Object} [parameters] - An object with one or more properties
37921	 * defining the material's appearance. Any property of the material
37922	 * (including any property from inherited materials) can be passed
37923	 * in here. Color values can be passed any type of value accepted
37924	 * by {@link Color#set}.
37925	 */
37926	constructor( parameters ) {
37927
37928		super();
37929
37930		/**
37931		 * This flag can be used for type testing.
37932		 *
37933		 * @type {boolean}
37934		 * @readonly
37935		 * @default true
37936		 */
37937		this.isMeshStandardMaterial = true;
37938
37939		this.type = 'MeshStandardMaterial';
37940
37941		this.defines = { 'STANDARD': '' };
37942
37943		/**
37944		 * Color of the material.
37945		 *
37946		 * @type {Color}
37947		 * @default (1,1,1)
37948		 */
37949		this.color = new Color( 0xffffff ); // diffuse
37950
37951		/**
37952		 * How rough the material appears. `0.0` means a smooth mirror reflection, `1.0`
37953		 * means fully diffuse. If `roughnessMap` is also provided,
37954		 * both values are multiplied.
37955		 *
37956		 * @type {number}
37957		 * @default 1
37958		 */
37959		this.roughness = 1.0;
37960
37961		/**
37962		 * How much the material is like a metal. Non-metallic materials such as wood
37963		 * or stone use `0.0`, metallic use `1.0`, with nothing (usually) in between.
37964		 * A value between `0.0` and `1.0` could be used for a rusty metal look.
37965		 * If `metalnessMap` is also provided, both values are multiplied.
37966		 *
37967		 * @type {number}
37968		 * @default 0
37969		 */
37970		this.metalness = 0.0;
37971
37972		/**
37973		 * The color map. May optionally include an alpha channel, typically combined
37974		 * with {@link Material#transparent} or {@link Material#alphaTest}. The texture map
37975		 * color is modulated by the diffuse `color`.
37976		 *
37977		 * @type {?Texture}
37978		 * @default null
37979		 */
37980		this.map = null;
37981
37982		/**
37983		 * The light map. Requires a second set of UVs.
37984		 *
37985		 * @type {?Texture}
37986		 * @default null
37987		 */
37988		this.lightMap = null;
37989
37990		/**
37991		 * Intensity of the baked light.
37992		 *
37993		 * @type {number}
37994		 * @default 1
37995		 */
37996		this.lightMapIntensity = 1.0;
37997
37998		/**
37999		 * The red channel of this texture is used as the ambient occlusion map.
38000		 * Requires a second set of UVs.
38001		 *
38002		 * @type {?Texture}
38003		 * @default null
38004		 */
38005		this.aoMap = null;
38006
38007		/**
38008		 * Intensity of the ambient occlusion effect. Range is `[0,1]`, where `0`
38009		 * disables ambient occlusion. Where intensity is `1` and the AO map's
38010		 * red channel is also `1`, ambient light is fully occluded on a surface.
38011		 *
38012		 * @type {number}
38013		 * @default 1
38014		 */
38015		this.aoMapIntensity = 1.0;
38016
38017		/**
38018		 * Emissive (light) color of the material, essentially a solid color
38019		 * unaffected by other lighting.
38020		 *
38021		 * @type {Color}
38022		 * @default (0,0,0)
38023		 */
38024		this.emissive = new Color( 0x000000 );
38025
38026		/**
38027		 * Intensity of the emissive light. Modulates the emissive color.
38028		 *
38029		 * @type {number}
38030		 * @default 1
38031		 */
38032		this.emissiveIntensity = 1.0;
38033
38034		/**
38035		 * Set emissive (glow) map. The emissive map color is modulated by the
38036		 * emissive color and the emissive intensity. If you have an emissive map,
38037		 * be sure to set the emissive color to something other than black.
38038		 *
38039		 * @type {?Texture}
38040		 * @default null
38041		 */
38042		this.emissiveMap = null;
38043
38044		/**
38045		 * The texture to create a bump map. The black and white values map to the
38046		 * perceived depth in relation to the lights. Bump doesn't actually affect
38047		 * the geometry of the object, only the lighting. If a normal map is defined
38048		 * this will be ignored.
38049		 *
38050		 * @type {?Texture}
38051		 * @default null
38052		 */
38053		this.bumpMap = null;
38054
38055		/**
38056		 * How much the bump map affects the material. Typical range is `[0,1]`.
38057		 *
38058		 * @type {number}
38059		 * @default 1
38060		 */
38061		this.bumpScale = 1;
38062
38063		/**
38064		 * The texture to create a normal map. The RGB values affect the surface
38065		 * normal for each pixel fragment and change the way the color is lit. Normal
38066		 * maps do not change the actual shape of the surface, only the lighting. In
38067		 * case the material has a normal map authored using the left handed
38068		 * convention, the `y` component of `normalScale` should be negated to compensate
38069		 * for the different handedness.
38070		 *
38071		 * @type {?Texture}
38072		 * @default null
38073		 */
38074		this.normalMap = null;
38075
38076		/**
38077		 * The type of normal map.
38078		 *
38079		 * @type {(TangentSpaceNormalMap|ObjectSpaceNormalMap)}
38080		 * @default TangentSpaceNormalMap
38081		 */
38082		this.normalMapType = TangentSpaceNormalMap;
38083
38084		/**
38085		 * How much the normal map affects the material. Typical value range is `[0,1]`.
38086		 *
38087		 * @type {Vector2}
38088		 * @default (1,1)
38089		 */
38090		this.normalScale = new Vector2( 1, 1 );
38091
38092		/**
38093		 * The displacement map affects the position of the mesh's vertices. Unlike
38094		 * other maps which only affect the light and shade of the material the
38095		 * displaced vertices can cast shadows, block other objects, and otherwise
38096		 * act as real geometry. The displacement texture is an image where the value
38097		 * of each pixel (white being the highest) is mapped against, and
38098		 * repositions, the vertices of the mesh.
38099		 *
38100		 * @type {?Texture}
38101		 * @default null
38102		 */
38103		this.displacementMap = null;
38104
38105		/**
38106		 * How much the displacement map affects the mesh (where black is no
38107		 * displacement, and white is maximum displacement). Without a displacement
38108		 * map set, this value is not applied.
38109		 *
38110		 * @type {number}
38111		 * @default 0
38112		 */
38113		this.displacementScale = 1;
38114
38115		/**
38116		 * The offset of the displacement map's values on the mesh's vertices.
38117		 * The bias is added to the scaled sample of the displacement map.
38118		 * Without a displacement map set, this value is not applied.
38119		 *
38120		 * @type {number}
38121		 * @default 0
38122		 */
38123		this.displacementBias = 0;
38124
38125		/**
38126		 * The green channel of this texture is used to alter the roughness of the
38127		 * material.
38128		 *
38129		 * @type {?Texture}
38130		 * @default null
38131		 */
38132		this.roughnessMap = null;
38133
38134		/**
38135		 * The blue channel of this texture is used to alter the metalness of the
38136		 * material.
38137		 *
38138		 * @type {?Texture}
38139		 * @default null
38140		 */
38141		this.metalnessMap = null;
38142
38143		/**
38144		 * The alpha map is a grayscale texture that controls the opacity across the
38145		 * surface (black: fully transparent; white: fully opaque).
38146		 *
38147		 * Only the color of the texture is used, ignoring the alpha channel if one
38148		 * exists. For RGB and RGBA textures, the renderer will use the green channel
38149		 * when sampling this texture due to the extra bit of precision provided for
38150		 * green in DXT-compressed and uncompressed RGB 565 formats. Luminance-only and
38151		 * luminance/alpha textures will also still work as expected.
38152		 *
38153		 * @type {?Texture}
38154		 * @default null
38155		 */
38156		this.alphaMap = null;
38157
38158		/**
38159		 * The environment map. To ensure a physically correct rendering, environment maps
38160		 * are internally pre-processed with {@link PMREMGenerator}.
38161		 *
38162		 * @type {?Texture}
38163		 * @default null
38164		 */
38165		this.envMap = null;
38166
38167		/**
38168		 * The rotation of the environment map in radians.
38169		 *
38170		 * @type {Euler}
38171		 * @default (0,0,0)
38172		 */
38173		this.envMapRotation = new Euler();
38174
38175		/**
38176		 * Scales the effect of the environment map by multiplying its color.
38177		 *
38178		 * @type {number}
38179		 * @default 1
38180		 */
38181		this.envMapIntensity = 1.0;
38182
38183		/**
38184		 * Renders the geometry as a wireframe.
38185		 *
38186		 * @type {boolean}
38187		 * @default false
38188		 */
38189		this.wireframe = false;
38190
38191		/**
38192		 * Controls the thickness of the wireframe.
38193		 *
38194		 * Can only be used with {@link SVGRenderer}.
38195		 *
38196		 * @type {number}
38197		 * @default 1
38198		 */
38199		this.wireframeLinewidth = 1;
38200
38201		/**
38202		 * Defines appearance of wireframe ends.
38203		 *
38204		 * Can only be used with {@link SVGRenderer}.
38205		 *
38206		 * @type {('round'|'bevel'|'miter')}
38207		 * @default 'round'
38208		 */
38209		this.wireframeLinecap = 'round';
38210
38211		/**
38212		 * Defines appearance of wireframe joints.
38213		 *
38214		 * Can only be used with {@link SVGRenderer}.
38215		 *
38216		 * @type {('round'|'bevel'|'miter')}
38217		 * @default 'round'
38218		 */
38219		this.wireframeLinejoin = 'round';
38220
38221		/**
38222		 * Whether the material is rendered with flat shading or not.
38223		 *
38224		 * @type {boolean}
38225		 * @default false
38226		 */
38227		this.flatShading = false;
38228
38229		/**
38230		 * Whether the material is affected by fog or not.
38231		 *
38232		 * @type {boolean}
38233		 * @default true
38234		 */
38235		this.fog = true;
38236
38237		this.setValues( parameters );
38238
38239	}
38240
38241	copy( source ) {
38242
38243		super.copy( source );
38244
38245		this.defines = { 'STANDARD': '' };
38246
38247		this.color.copy( source.color );
38248		this.roughness = source.roughness;
38249		this.metalness = source.metalness;
38250
38251		this.map = source.map;
38252
38253		this.lightMap = source.lightMap;
38254		this.lightMapIntensity = source.lightMapIntensity;
38255
38256		this.aoMap = source.aoMap;
38257		this.aoMapIntensity = source.aoMapIntensity;
38258
38259		this.emissive.copy( source.emissive );
38260		this.emissiveMap = source.emissiveMap;
38261		this.emissiveIntensity = source.emissiveIntensity;
38262
38263		this.bumpMap = source.bumpMap;
38264		this.bumpScale = source.bumpScale;
38265
38266		this.normalMap = source.normalMap;
38267		this.normalMapType = source.normalMapType;
38268		this.normalScale.copy( source.normalScale );
38269
38270		this.displacementMap = source.displacementMap;
38271		this.displacementScale = source.displacementScale;
38272		this.displacementBias = source.displacementBias;
38273
38274		this.roughnessMap = source.roughnessMap;
38275
38276		this.metalnessMap = source.metalnessMap;
38277
38278		this.alphaMap = source.alphaMap;
38279
38280		this.envMap = source.envMap;
38281		this.envMapRotation.copy( source.envMapRotation );
38282		this.envMapIntensity = source.envMapIntensity;
38283
38284		this.wireframe = source.wireframe;
38285		this.wireframeLinewidth = source.wireframeLinewidth;
38286		this.wireframeLinecap = source.wireframeLinecap;
38287		this.wireframeLinejoin = source.wireframeLinejoin;
38288
38289		this.flatShading = source.flatShading;
38290
38291		this.fog = source.fog;
38292
38293		return this;
38294
38295	}
38296
38297}
38298
38299/**
38300 * An extension of the {@link MeshStandardMaterial}, providing more advanced
38301 * physically-based rendering properties:
38302 *
38303 * - Anisotropy: Ability to represent the anisotropic property of materials
38304 * as observable with brushed metals.
38305 * - Clearcoat: Some materials — like car paints, carbon fiber, and wet surfaces — require
38306 * a clear, reflective layer on top of another layer that may be irregular or rough.
38307 * Clearcoat approximates this effect, without the need for a separate transparent surface.
38308 * - Iridescence: Allows to render the effect where hue varies  depending on the viewing
38309 * angle and illumination angle. This can be seen on soap bubbles, oil films, or on the
38310 * wings of many insects.
38311 * - Physically-based transparency: One limitation of {@link Material#opacity} is that highly
38312 * transparent materials are less reflective. Physically-based transmission provides a more
38313 * realistic option for thin, transparent surfaces like glass.
38314 * - Advanced reflectivity: More flexible reflectivity for non-metallic materials.
38315 * - Sheen: Can be used for representing cloth and fabric materials.
38316 *
38317 * As a result of these complex shading features, `MeshPhysicalMaterial` has a
38318 * higher performance cost, per pixel, than other three.js materials. Most
38319 * effects are disabled by default, and add cost as they are enabled. For
38320 * best results, always specify an environment map when using this material.
38321 *
38322 * @augments MeshStandardMaterial
38323 * @demo scenes/material-browser.html#MeshPhysicalMaterial
38324 */
38325class MeshPhysicalMaterial extends MeshStandardMaterial {
38326
38327	/**
38328	 * Constructs a new mesh physical material.
38329	 *
38330	 * @param {Object} [parameters] - An object with one or more properties
38331	 * defining the material's appearance. Any property of the material
38332	 * (including any property from inherited materials) can be passed
38333	 * in here. Color values can be passed any type of value accepted
38334	 * by {@link Color#set}.
38335	 */
38336	constructor( parameters ) {
38337
38338		super();
38339
38340		/**
38341		 * This flag can be used for type testing.
38342		 *
38343		 * @type {boolean}
38344		 * @readonly
38345		 * @default true
38346		 */
38347		this.isMeshPhysicalMaterial = true;
38348
38349		this.defines = {
38350
38351			'STANDARD': '',
38352			'PHYSICAL': ''
38353
38354		};
38355
38356		this.type = 'MeshPhysicalMaterial';
38357
38358		/**
38359		 * The rotation of the anisotropy in tangent, bitangent space, measured in radians
38360		 * counter-clockwise from the tangent. When `anisotropyMap` is present, this
38361		 * property provides additional rotation to the vectors in the texture.
38362		 *
38363		 * @type {number}
38364		 * @default 1
38365		 */
38366		this.anisotropyRotation = 0;
38367
38368		/**
38369		 * Red and green channels represent the anisotropy direction in `[-1, 1]` tangent,
38370		 * bitangent space, to be rotated by `anisotropyRotation`. The blue channel
38371		 * contains strength as `[0, 1]` to be multiplied by `anisotropy`.
38372		 *
38373		 * @type {?Texture}
38374		 * @default null
38375		 */
38376		this.anisotropyMap = null;
38377
38378		/**
38379		 * The red channel of this texture is multiplied against `clearcoat`,
38380		 * for per-pixel control over a coating's intensity.
38381		 *
38382		 * @type {?Texture}
38383		 * @default null
38384		 */
38385		this.clearcoatMap = null;
38386
38387		/**
38388		 * Roughness of the clear coat layer, from `0.0` to `1.0`.
38389		 *
38390		 * @type {number}
38391		 * @default 0
38392		 */
38393		this.clearcoatRoughness = 0.0;
38394
38395		/**
38396		 * The green channel of this texture is multiplied against
38397		 * `clearcoatRoughness`, for per-pixel control over a coating's roughness.
38398		 *
38399		 * @type {?Texture}
38400		 * @default null
38401		 */
38402		this.clearcoatRoughnessMap = null;
38403
38404		/**
38405		 * How much `clearcoatNormalMap` affects the clear coat layer, from
38406		 * `(0,0)` to `(1,1)`.
38407		 *
38408		 * @type {Vector2}
38409		 * @default (1,1)
38410		 */
38411		this.clearcoatNormalScale = new Vector2( 1, 1 );
38412
38413		/**
38414		 * Can be used to enable independent normals for the clear coat layer.
38415		 *
38416		 * @type {?Texture}
38417		 * @default null
38418		 */
38419		this.clearcoatNormalMap = null;
38420
38421		/**
38422		 * Index-of-refraction for non-metallic materials, from `1.0` to `2.333`.
38423		 *
38424		 * @type {number}
38425		 * @default 1.5
38426		 */
38427		this.ior = 1.5;
38428
38429		/**
38430		 * Degree of reflectivity, from `0.0` to `1.0`. Default is `0.5`, which
38431		 * corresponds to an index-of-refraction of `1.5`.
38432		 *
38433		 * This models the reflectivity of non-metallic materials. It has no effect
38434		 * when `metalness` is `1.0`
38435		 *
38436		 * @name MeshPhysicalMaterial#reflectivity
38437		 * @type {number}
38438		 * @default 0.5
38439		 */
38440		Object.defineProperty( this, 'reflectivity', {
38441			get: function () {
38442
38443				return ( clamp( 2.5 * ( this.ior - 1 ) / ( this.ior + 1 ), 0, 1 ) );
38444
38445			},
38446			set: function ( reflectivity ) {
38447
38448				this.ior = ( 1 + 0.4 * reflectivity ) / ( 1 - 0.4 * reflectivity );
38449
38450			}
38451		} );
38452
38453		/**
38454		 * The red channel of this texture is multiplied against `iridescence`, for per-pixel
38455		 * control over iridescence.
38456		 *
38457		 * @type {?Texture}
38458		 * @default null
38459		 */
38460		this.iridescenceMap = null;
38461
38462		/**
38463		 * Strength of the iridescence RGB color shift effect, represented by an index-of-refraction.
38464		 * Between `1.0` to `2.333`.
38465		 *
38466		 * @type {number}
38467		 * @default 1.3
38468		 */
38469		this.iridescenceIOR = 1.3;
38470
38471		/**
38472		 *Array of exactly 2 elements, specifying minimum and maximum thickness of the iridescence layer.
38473		 Thickness of iridescence layer has an equivalent effect of the one `thickness` has on `ior`.
38474		 *
38475		 * @type {Array<number,number>}
38476		 * @default [100,400]
38477		 */
38478		this.iridescenceThicknessRange = [ 100, 400 ];
38479
38480		/**
38481		 * A texture that defines the thickness of the iridescence layer, stored in the green channel.
38482		 * Minimum and maximum values of thickness are defined by `iridescenceThicknessRange` array:
38483		 * - `0.0` in the green channel will result in thickness equal to first element of the array.
38484		 * - `1.0` in the green channel will result in thickness equal to second element of the array.
38485		 * - Values in-between will linearly interpolate between the elements of the array.
38486		 *
38487		 * @type {?Texture}
38488		 * @default null
38489		 */
38490		this.iridescenceThicknessMap = null;
38491
38492		/**
38493		 * The sheen tint.
38494		 *
38495		 * @type {Color}
38496		 * @default (0,0,0)
38497		 */
38498		this.sheenColor = new Color( 0x000000 );
38499
38500		/**
38501		 * The RGB channels of this texture are multiplied against  `sheenColor`, for per-pixel control
38502		 * over sheen tint.
38503		 *
38504		 * @type {?Texture}
38505		 * @default null
38506		 */
38507		this.sheenColorMap = null;
38508
38509		/**
38510		 * Roughness of the sheen layer, from `0.0` to `1.0`.
38511		 *
38512		 * @type {number}
38513		 * @default 1
38514		 */
38515		this.sheenRoughness = 1.0;
38516
38517		/**
38518		 * The alpha channel of this texture is multiplied against `sheenRoughness`, for per-pixel control
38519		 * over sheen roughness.
38520		 *
38521		 * @type {?Texture}
38522		 * @default null
38523		 */
38524		this.sheenRoughnessMap = null;
38525
38526		/**
38527		 * The red channel of this texture is multiplied against `transmission`, for per-pixel control over
38528		 * optical transparency.
38529		 *
38530		 * @type {?Texture}
38531		 * @default null
38532		 */
38533		this.transmissionMap = null;
38534
38535		/**
38536		 * The thickness of the volume beneath the surface. The value is given in the
38537		 * coordinate space of the mesh. If the value is `0` the material is
38538		 * thin-walled. Otherwise the material is a volume boundary.
38539		 *
38540		 * @type {number}
38541		 * @default 0
38542		 */
38543		this.thickness = 0;
38544
38545		/**
38546		 * A texture that defines the thickness, stored in the green channel. This will
38547		 * be multiplied by `thickness`.
38548		 *
38549		 * @type {?Texture}
38550		 * @default null
38551		 */
38552		this.thicknessMap = null;
38553
38554		/**
38555		 * Density of the medium given as the average distance that light travels in
38556		 * the medium before interacting with a particle. The value is given in world
38557		 * space units, and must be greater than zero.
38558		 *
38559		 * @type {number}
38560		 * @default Infinity
38561		 */
38562		this.attenuationDistance = Infinity;
38563
38564		/**
38565		 * The color that white light turns into due to absorption when reaching the
38566		 * attenuation distance.
38567		 *
38568		 * @type {Color}
38569		 * @default (1,1,1)
38570		 */
38571		this.attenuationColor = new Color( 1, 1, 1 );
38572
38573		/**
38574		 * A float that scales the amount of specular reflection for non-metals only.
38575		 * When set to zero, the model is effectively Lambertian. From `0.0` to `1.0`.
38576		 *
38577		 * @type {number}
38578		 * @default 1
38579		 */
38580		this.specularIntensity = 1.0;
38581
38582		/**
38583		 * The alpha channel of this texture is multiplied against `specularIntensity`,
38584		 * for per-pixel control over specular intensity.
38585		 *
38586		 * @type {?Texture}
38587		 * @default null
38588		 */
38589		this.specularIntensityMap = null;
38590
38591		/**
38592		 * Tints the specular reflection at normal incidence for non-metals only.
38593		 *
38594		 * @type {Color}
38595		 * @default (1,1,1)
38596		 */
38597		this.specularColor = new Color( 1, 1, 1 );
38598
38599		/**
38600		 * The RGB channels of this texture are multiplied against `specularColor`,
38601		 * for per-pixel control over specular color.
38602		 *
38603		 * @type {?Texture}
38604		 * @default null
38605		 */
38606		this.specularColorMap = null;
38607
38608		this._anisotropy = 0;
38609		this._clearcoat = 0;
38610		this._dispersion = 0;
38611		this._iridescence = 0;
38612		this._sheen = 0.0;
38613		this._transmission = 0;
38614
38615		this.setValues( parameters );
38616
38617	}
38618
38619	/**
38620	 * The anisotropy strength, from `0.0` to `1.0`.
38621	 *
38622	 * @type {number}
38623	 * @default 0
38624	 */
38625	get anisotropy() {
38626
38627		return this._anisotropy;
38628
38629	}
38630
38631	set anisotropy( value ) {
38632
38633		if ( this._anisotropy > 0 !== value > 0 ) {
38634
38635			this.version ++;
38636
38637		}
38638
38639		this._anisotropy = value;
38640
38641	}
38642
38643	/**
38644	 * Represents the intensity of the clear coat layer, from `0.0` to `1.0`. Use
38645	 * clear coat related properties to enable multilayer materials that have a
38646	 * thin translucent layer over the base layer.
38647	 *
38648	 * @type {number}
38649	 * @default 0
38650	 */
38651	get clearcoat() {
38652
38653		return this._clearcoat;
38654
38655	}
38656
38657	set clearcoat( value ) {
38658
38659		if ( this._clearcoat > 0 !== value > 0 ) {
38660
38661			this.version ++;
38662
38663		}
38664
38665		this._clearcoat = value;
38666
38667	}
38668	/**
38669	 * The intensity of the iridescence layer, simulating RGB color shift based on the angle between
38670	 * the surface and the viewer, from `0.0` to `1.0`.
38671	 *
38672	 * @type {number}
38673	 * @default 0
38674	 */
38675	get iridescence() {
38676
38677		return this._iridescence;
38678
38679	}
38680
38681	set iridescence( value ) {
38682
38683		if ( this._iridescence > 0 !== value > 0 ) {
38684
38685			this.version ++;
38686
38687		}
38688
38689		this._iridescence = value;
38690
38691	}
38692
38693	/**
38694	 * Defines the strength of the angular separation of colors (chromatic aberration) transmitting
38695	 * through a relatively clear volume. Any value zero or larger is valid, the typical range of
38696	 * realistic values is `[0, 1]`. This property can be only be used with transmissive objects.
38697	 *
38698	 * @type {number}
38699	 * @default 0
38700	 */
38701	get dispersion() {
38702
38703		return this._dispersion;
38704
38705	}
38706
38707	set dispersion( value ) {
38708
38709		if ( this._dispersion > 0 !== value > 0 ) {
38710
38711			this.version ++;
38712
38713		}
38714
38715		this._dispersion = value;
38716
38717	}
38718
38719	/**
38720	 * The intensity of the sheen layer, from `0.0` to `1.0`.
38721	 *
38722	 * @type {number}
38723	 * @default 0
38724	 */
38725	get sheen() {
38726
38727		return this._sheen;
38728
38729	}
38730
38731	set sheen( value ) {
38732
38733		if ( this._sheen > 0 !== value > 0 ) {
38734
38735			this.version ++;
38736
38737		}
38738
38739		this._sheen = value;
38740
38741	}
38742
38743	/**
38744	 * Degree of transmission (or optical transparency), from `0.0` to `1.0`.
38745	 *
38746	 * Thin, transparent or semitransparent, plastic or glass materials remain
38747	 * largely reflective even if they are fully transmissive. The transmission
38748	 * property can be used to model these materials.
38749	 *
38750	 * When transmission is non-zero, `opacity` should be  set to `1`.
38751	 *
38752	 * @type {number}
38753	 * @default 0
38754	 */
38755	get transmission() {
38756
38757		return this._transmission;
38758
38759	}
38760
38761	set transmission( value ) {
38762
38763		if ( this._transmission > 0 !== value > 0 ) {
38764
38765			this.version ++;
38766
38767		}
38768
38769		this._transmission = value;
38770
38771	}
38772
38773	copy( source ) {
38774
38775		super.copy( source );
38776
38777		this.defines = {
38778
38779			'STANDARD': '',
38780			'PHYSICAL': ''
38781
38782		};
38783
38784		this.anisotropy = source.anisotropy;
38785		this.anisotropyRotation = source.anisotropyRotation;
38786		this.anisotropyMap = source.anisotropyMap;
38787
38788		this.clearcoat = source.clearcoat;
38789		this.clearcoatMap = source.clearcoatMap;
38790		this.clearcoatRoughness = source.clearcoatRoughness;
38791		this.clearcoatRoughnessMap = source.clearcoatRoughnessMap;
38792		this.clearcoatNormalMap = source.clearcoatNormalMap;
38793		this.clearcoatNormalScale.copy( source.clearcoatNormalScale );
38794
38795		this.dispersion = source.dispersion;
38796		this.ior = source.ior;
38797
38798		this.iridescence = source.iridescence;
38799		this.iridescenceMap = source.iridescenceMap;
38800		this.iridescenceIOR = source.iridescenceIOR;
38801		this.iridescenceThicknessRange = [ ...source.iridescenceThicknessRange ];
38802		this.iridescenceThicknessMap = source.iridescenceThicknessMap;
38803
38804		this.sheen = source.sheen;
38805		this.sheenColor.copy( source.sheenColor );
38806		this.sheenColorMap = source.sheenColorMap;
38807		this.sheenRoughness = source.sheenRoughness;
38808		this.sheenRoughnessMap = source.sheenRoughnessMap;
38809
38810		this.transmission = source.transmission;
38811		this.transmissionMap = source.transmissionMap;
38812
38813		this.thickness = source.thickness;
38814		this.thicknessMap = source.thicknessMap;
38815		this.attenuationDistance = source.attenuationDistance;
38816		this.attenuationColor.copy( source.attenuationColor );
38817
38818		this.specularIntensity = source.specularIntensity;
38819		this.specularIntensityMap = source.specularIntensityMap;
38820		this.specularColor.copy( source.specularColor );
38821		this.specularColorMap = source.specularColorMap;
38822
38823		return this;
38824
38825	}
38826
38827}
38828
38829/**
38830 * A material for 
38830shiny surfaces with specular highlights.
38831 *
38832 * The material uses a non-physically based [Blinn-Phong](https://en.wikipedia.org/wiki/Blinn-Phong_shading_model)
38833 * model for calculating reflectance. Unlike the Lambertian model used in the
38834 * {@link MeshLambertMaterial} this can simulate shiny surfaces with specular
38835 * highlights (such as varnished wood). `MeshPhongMaterial` uses per-fragment shading.
38836 *
38837 * Performance will generally be greater when using this material over the
38838 * {@link MeshStandardMaterial} or {@link MeshPhysicalMaterial}, at the cost of
38839 * some graphical accuracy.
38840 *
38841 * @augments Material
38842 * @demo scenes/material-browser.html#MeshPhongMaterial
38843 */
38844class MeshPhongMaterial extends Material {
38845
38846	/**
38847	 * Constructs a new mesh phong material.
38848	 *
38849	 * @param {Object} [parameters] - An object with one or more properties
38850	 * defining the material's appearance. Any property of the material
38851	 * (including any property from inherited materials) can be passed
38852	 * in here. Color values can be passed any type of value accepted
38853	 * by {@link Color#set}.
38854	 */
38855	constructor( parameters ) {
38856
38857		super();
38858
38859		/**
38860		 * This flag can be used for type testing.
38861		 *
38862		 * @type {boolean}
38863		 * @readonly
38864		 * @default true
38865		 */
38866		this.isMeshPhongMaterial = true;
38867
38868		this.type = 'MeshPhongMaterial';
38869
38870		/**
38871		 * Color of the material.
38872		 *
38873		 * @type {Color}
38874		 * @default (1,1,1)
38875		 */
38876		this.color = new Color( 0xffffff ); // diffuse
38877
38878		/**
38879		 * Specular color of the material. The default color is set to `0x111111` (very dark grey)
38880		 *
38881		 * This defines how shiny the material is and the color of its shine.
38882		 *
38883		 * @type {Color}
38884		 */
38885		this.specular = new Color( 0x111111 );
38886
38887		/**
38888		 * How shiny the specular highlight is; a higher value gives a sharper highlight.
38889		 *
38890		 * @type {number}
38891		 * @default 30
38892		 */
38893		this.shininess = 30;
38894
38895		/**
38896		 * The color map. May optionally include an alpha channel, typically combined
38897		 * with {@link Material#transparent} or {@link Material#alphaTest}. The texture map
38898		 * color is modulated by the diffuse `color`.
38899		 *
38900		 * @type {?Texture}
38901		 * @default null
38902		 */
38903		this.map = null;
38904
38905		/**
38906		 * The light map. Requires a second set of UVs.
38907		 *
38908		 * @type {?Texture}
38909		 * @default null
38910		 */
38911		this.lightMap = null;
38912
38913		/**
38914		 * Intensity of the baked light.
38915		 *
38916		 * @type {number}
38917		 * @default 1
38918		 */
38919		this.lightMapIntensity = 1.0;
38920
38921		/**
38922		 * The red channel of this texture is used as the ambient occlusion map.
38923		 * Requires a second set of UVs.
38924		 *
38925		 * @type {?Texture}
38926		 * @default null
38927		 */
38928		this.aoMap = null;
38929
38930		/**
38931		 * Intensity of the ambient occlusion effect. Range is `[0,1]`, where `0`
38932		 * disables ambient occlusion. Where intensity is `1` and the AO map's
38933		 * red channel is also `1`, ambient light is fully occluded on a surface.
38934		 *
38935		 * @type {number}
38936		 * @default 1
38937		 */
38938		this.aoMapIntensity = 1.0;
38939
38940		/**
38941		 * Emissive (light) color of the material, essentially a solid color
38942		 * unaffected by other lighting.
38943		 *
38944		 * @type {Color}
38945		 * @default (0,0,0)
38946		 */
38947		this.emissive = new Color( 0x000000 );
38948
38949		/**
38950		 * Intensity of the emissive light. Modulates the emissive color.
38951		 *
38952		 * @type {number}
38953		 * @default 1
38954		 */
38955		this.emissiveIntensity = 1.0;
38956
38957		/**
38958		 * Set emissive (glow) map. The emissive map color is modulated by the
38959		 * emissive color and the emissive intensity. If you have an emissive map,
38960		 * be sure to set the emissive color to something other than black.
38961		 *
38962		 * @type {?Texture}
38963		 * @default null
38964		 */
38965		this.emissiveMap = null;
38966
38967		/**
38968		 * The texture to create a bump map. The black and white values map to the
38969		 * perceived depth in relation to the lights. Bump doesn't actually affect
38970		 * the geometry of the object, only the lighting. If a normal map is defined
38971		 * this will be ignored.
38972		 *
38973		 * @type {?Texture}
38974		 * @default null
38975		 */
38976		this.bumpMap = null;
38977
38978		/**
38979		 * How much the bump map affects the material. Typical range is `[0,1]`.
38980		 *
38981		 * @type {number}
38982		 * @default 1
38983		 */
38984		this.bumpScale = 1;
38985
38986		/**
38987		 * The texture to create a normal map. The RGB values affect the surface
38988		 * normal for each pixel fragment and change the way the color is lit. Normal
38989		 * maps do not change the actual shape of the surface, only the lighting. In
38990		 * case the material has a normal map authored using the left handed
38991		 * convention, the `y` component of `normalScale` should be negated to compensate
38992		 * for the different handedness.
38993		 *
38994		 * @type {?Texture}
38995		 * @default null
38996		 */
38997		this.normalMap = null;
38998
38999		/**
39000		 * The type of normal map.
39001		 *
39002		 * @type {(TangentSpaceNormalMap|ObjectSpaceNormalMap)}
39003		 * @default TangentSpaceNormalMap
39004		 */
39005		this.normalMapType = TangentSpaceNormalMap;
39006
39007		/**
39008		 * How much the normal map affects the material. Typical value range is `[0,1]`.
39009		 *
39010		 * @type {Vector2}
39011		 * @default (1,1)
39012		 */
39013		this.normalScale = new Vector2( 1, 1 );
39014
39015		/**
39016		 * The displacement map affects the position of the mesh's vertices. Unlike
39017		 * other maps which only affect the light and shade of the material the
39018		 * displaced vertices can cast shadows, block other objects, and otherwise
39019		 * act as real geometry. The displacement texture is an image where the value
39020		 * of each pixel (white being the highest) is mapped against, and
39021		 * repositions, the vertices of the mesh.
39022		 *
39023		 * @type {?Texture}
39024		 * @default null
39025		 */
39026		this.displacementMap = null;
39027
39028		/**
39029		 * How much the displacement map affects the mesh (where black is no
39030		 * displacement, and white is maximum displacement). Without a displacement
39031		 * map set, this value is not applied.
39032		 *
39033		 * @type {number}
39034		 * @default 0
39035		 */
39036		this.displacementScale = 1;
39037
39038		/**
39039		 * The offset of the displacement map's values on the mesh's vertices.
39040		 * The bias is added to the scaled sample of the displacement map.
39041		 * Without a displacement map set, this value is not applied.
39042		 *
39043		 * @type {number}
39044		 * @default 0
39045		 */
39046		this.displacementBias = 0;
39047
39048		/**
39049		 * The specular map value affects both how much the specular surface
39050		 * highlight contributes and how much of the environment map affects the
39051		 * surface.
39052		 *
39053		 * @type {?Texture}
39054		 * @default null
39055		 */
39056		this.specularMap = null;
39057
39058		/**
39059		 * The alpha map is a grayscale texture that controls the opacity across the
39060		 * surface (black: fully transparent; white: fully opaque).
39061		 *
39062		 * Only the color of the texture is used, ignoring the alpha channel if one
39063		 * exists. For RGB and RGBA textures, the renderer will use the green channel
39064		 * when sampling this texture due to the extra bit of precision provided for
39065		 * green in DXT-compressed and uncompressed RGB 565 formats. Luminance-only and
39066		 * luminance/alpha textures will also still work as expected.
39067		 *
39068		 * @type {?Texture}
39069		 * @default null
39070		 */
39071		this.alphaMap = null;
39072
39073		/**
39074		 * The environment map.
39075		 *
39076		 * @type {?Texture}
39077		 * @default null
39078		 */
39079		this.envMap = null;
39080
39081		/**
39082		 * The rotation of the environment map in radians.
39083		 *
39084		 * @type {Euler}
39085		 * @default (0,0,0)
39086		 */
39087		this.envMapRotation = new Euler();
39088
39089		/**
39090		 * How to combine the result of the surface's color with the environment map, if any.
39091		 *
39092		 * When set to `MixOperation`, the {@link MeshBasicMaterial#reflectivity} is used to
39093		 * blend between the two colors.
39094		 *
39095		 * @type {(MultiplyOperation|MixOperation|AddOperation)}
39096		 * @default MultiplyOperation
39097		 */
39098		this.combine = MultiplyOperation;
39099
39100		/**
39101		 * How much the environment map affects the surface.
39102		 * The valid range is between `0` (no reflections) and `1` (full reflections).
39103		 *
39104		 * @type {number}
39105		 * @default 1
39106		 */
39107		this.reflectivity = 1;
39108
39109		/**
39110		 * Scales the effect of the environment map by multiplying its color.
39111		 *
39112		 * @type {number}
39113		 * @default 1
39114		 */
39115		this.envMapIntensity = 1.0;
39116
39117		/**
39118		 * The index of refraction (IOR) of air (approximately 1) divided by the
39119		 * index of refraction of the material. It is used with environment mapping
39120		 * modes {@link CubeRefractionMapping} and {@link EquirectangularRefractionMapping}.
39121		 * The refraction ratio should not exceed `1`.
39122		 *
39123		 * @type {number}
39124		 * @default 0.98
39125		 */
39126		this.refractionRatio = 0.98;
39127
39128		/**
39129		 * Renders the geometry as a wireframe.
39130		 *
39131		 * @type {boolean}
39132		 * @default false
39133		 */
39134		this.wireframe = false;
39135
39136		/**
39137		 * Controls the thickness of the wireframe.
39138		 *
39139		 * Can only be used with {@link SVGRenderer}.
39140		 *
39141		 * @type {number}
39142		 * @default 1
39143		 */
39144		this.wireframeLinewidth = 1;
39145
39146		/**
39147		 * Defines appearance of wireframe ends.
39148		 *
39149		 * Can only be used with {@link SVGRenderer}.
39150		 *
39151		 * @type {('round'|'bevel'|'miter')}
39152		 * @default 'round'
39153		 */
39154		this.wireframeLinecap = 'round';
39155
39156		/**
39157		 * Defines appearance of wireframe joints.
39158		 *
39159		 * Can only be used with {@link SVGRenderer}.
39160		 *
39161		 * @type {('round'|'bevel'|'miter')}
39162		 * @default 'round'
39163		 */
39164		this.wireframeLinejoin = 'round';
39165
39166		/**
39167		 * Whether the material is rendered with flat shading or not.
39168		 *
39169		 * @type {boolean}
39170		 * @default false
39171		 */
39172		this.flatShading = false;
39173
39174		/**
39175		 * Whether the material is affected by fog or not.
39176		 *
39177		 * @type {boolean}
39178		 * @default true
39179		 */
39180		this.fog = true;
39181
39182		this.setValues( parameters );
39183
39184	}
39185
39186	copy( source ) {
39187
39188		super.copy( source );
39189
39190		this.color.copy( source.color );
39191		this.specular.copy( source.specular );
39192		this.shininess = source.shininess;
39193
39194		this.map = source.map;
39195
39196		this.lightMap = source.lightMap;
39197		this.lightMapIntensity = source.lightMapIntensity;
39198
39199		this.aoMap = source.aoMap;
39200		this.aoMapIntensity = source.aoMapIntensity;
39201
39202		this.emissive.copy( source.emissive );
39203		this.emissiveMap = source.emissiveMap;
39204		this.emissiveIntensity = source.emissiveIntensity;
39205
39206		this.bumpMap = source.bumpMap;
39207		this.bumpScale = source.bumpScale;
39208
39209		this.normalMap = source.normalMap;
39210		this.normalMapType = source.normalMapType;
39211		this.normalScale.copy( source.normalScale );
39212
39213		this.displacementMap = source.displacementMap;
39214		this.displacementScale = source.displacementScale;
39215		this.displacementBias = source.displacementBias;
39216
39217		this.specularMap = source.specularMap;
39218
39219		this.alphaMap = source.alphaMap;
39220
39221		this.envMap = source.envMap;
39222		this.envMapRotation.copy( source.envMapRotation );
39223		this.combine = source.combine;
39224		this.reflectivity = source.reflectivity;
39225		this.envMapIntensity = source.envMapIntensity;
39226		this.refractionRatio = source.refractionRatio;
39227
39228		this.wireframe = source.wireframe;
39229		this.wireframeLinewidth = source.wireframeLinewidth;
39230		this.wireframeLinecap = source.wireframeLinecap;
39231		this.wireframeLinejoin = source.wireframeLinejoin;
39232
39233		this.flatShading = source.flatShading;
39234
39235		this.fog = source.fog;
39236
39237		return this;
39238
39239	}
39240
39241}
39242
39243/**
39244 * A material implementing toon shading.
39245 *
39246 * @augments Material
39247 * @demo scenes/material-browser.html#MeshToonMaterial
39248 */
39249class MeshToonMaterial extends Material {
39250
39251	/**
39252	 * Constructs a new mesh toon material.
39253	 *
39254	 * @param {Object} [parameters] - An object with one or more properties
39255	 * defining the material's appearance. Any property of the material
39256	 * (including any property from inherited materials) can be passed
39257	 * in here. Color values can be passed any type of value accepted
39258	 * by {@link Color#set}.
39259	 */
39260	constructor( parameters ) {
39261
39262		super();
39263
39264		/**
39265		 * This flag can be used for type testing.
39266		 *
39267		 * @type {boolean}
39268		 * @readonly
39269		 * @default true
39270		 */
39271		this.isMeshToonMaterial = true;
39272
39273		this.defines = { 'TOON': '' };
39274
39275		this.type = 'MeshToonMaterial';
39276
39277		/**
39278		 * Color of the material.
39279		 *
39280		 * @type {Color}
39281		 * @default (1,1,1)
39282		 */
39283		this.color = new Color( 0xffffff );
39284
39285		/**
39286		 * The color map. May optionally include an alpha channel, typically combined
39287		 * with {@link Material#transparent} or {@link Material#alphaTest}. The texture map
39288		 * color is modulated by the diffuse `color`.
39289		 *
39290		 * @type {?Texture}
39291		 * @default null
39292		 */
39293		this.map = null;
39294
39295		/**
39296		 * Gradient map for toon shading. It's required to set
39297		 * {@link Texture#minFilter} and {@link Texture#magFilter} to {@link NearestFilter}
39298		 * when using this type of texture.
39299		 *
39300		 * @type {?Texture}
39301		 * @default null
39302		 */
39303		this.gradientMap = null;
39304
39305		/**
39306		 * The light map. Requires a second set of UVs.
39307		 *
39308		 * @type {?Texture}
39309		 * @default null
39310		 */
39311		this.lightMap = null;
39312
39313		/**
39314		 * Intensity of the baked light.
39315		 *
39316		 * @type {number}
39317		 * @default 1
39318		 */
39319		this.lightMapIntensity = 1.0;
39320
39321		/**
39322		 * The red channel of this texture is used as the ambient occlusion map.
39323		 * Requires a second set of UVs.
39324		 *
39325		 * @type {?Texture}
39326		 * @default null
39327		 */
39328		this.aoMap = null;
39329
39330		/**
39331		 * Intensity of the ambient occlusion effect. Range is `[0,1]`, where `0`
39332		 * disables ambient occlusion. Where intensity is `1` and the AO map's
39333		 * red channel is also `1`, ambient light is fully occluded on a surface.
39334		 *
39335		 * @type {number}
39336		 * @default 1
39337		 */
39338		this.aoMapIntensity = 1.0;
39339
39340		/**
39341		 * Emissive (light) color of the material, essentially a solid color
39342		 * unaffected by other lighting.
39343		 *
39344		 * @type {Color}
39345		 * @default (0,0,0)
39346		 */
39347		this.emissive = new Color( 0x000000 );
39348
39349		/**
39350		 * Intensity of the emissive light. Modulates the emissive color.
39351		 *
39352		 * @type {number}
39353		 * @default 1
39354		 */
39355		this.emissiveIntensity = 1.0;
39356
39357		/**
39358		 * Set emissive (glow) map. The emissive map color is modulated by the
39359		 * emissive color and the emissive intensity. If you have an emissive map,
39360		 * be sure to set the emissive color to something other than black.
39361		 *
39362		 * @type {?Texture}
39363		 * @default null
39364		 */
39365		this.emissiveMap = null;
39366
39367		/**
39368		 * The texture to create a bump map. The black and white values map to the
39369		 * perceived depth in relation to the lights. Bump doesn't actually affect
39370		 * the geometry of the object, only the lighting. If a normal map is defined
39371		 * this will be ignored.
39372		 *
39373		 * @type {?Texture}
39374		 * @default null
39375		 */
39376		this.bumpMap = null;
39377
39378		/**
39379		 * How much the bump map affects the material. Typical range is `[0,1]`.
39380		 *
39381		 * @type {number}
39382		 * @default 1
39383		 */
39384		this.bumpScale = 1;
39385
39386		/**
39387		 * The texture to create a normal map. The RGB values affect the surface
39388		 * normal for each pixel fragment and change the way the color is lit. Normal
39389		 * maps do not change the actual shape of the surface, only the lighting. In
39390		 * case the material has a normal map authored using the left handed
39391		 * convention, the `y` component of `normalScale` should be negated to compensate
39392		 * for the different handedness.
39393		 *
39394		 * @type {?Texture}
39395		 * @default null
39396		 */
39397		this.normalMap = null;
39398
39399		/**
39400		 * The type of normal map.
39401		 *
39402		 * @type {(TangentSpaceNormalMap|ObjectSpaceNormalMap)}
39403		 * @default TangentSpaceNormalMap
39404		 */
39405		this.normalMapType = TangentSpaceNormalMap;
39406
39407		/**
39408		 * How much the normal map affects the material. Typical value range is `[0,1]`.
39409		 *
39410		 * @type {Vector2}
39411		 * @default (1,1)
39412		 */
39413		this.normalScale = new Vector2( 1, 1 );
39414
39415		/**
39416		 * The displacement map affects the position of the mesh's vertices. Unlike
39417		 * other maps which only affect the light and shade of the material the
39418		 * displaced vertices can cast shadows, block other objects, and otherwise
39419		 * act as real geometry. The displacement texture is an image where the value
39420		 * of each pixel (white being the highest) is mapped against, and
39421		 * repositions, the vertices of the mesh.
39422		 *
39423		 * @type {?Texture}
39424		 * @default null
39425		 */
39426		this.displacementMap = null;
39427
39428		/**
39429		 * How much the displacement map affects the mesh (where black is no
39430		 * displacement, and white is maximum displacement). Without a displacement
39431		 * map set, this value is not applied.
39432		 *
39433		 * @type {number}
39434		 * @default 0
39435		 */
39436		this.displacementScale = 1;
39437
39438		/**
39439		 * The offset of the displacement map's values on the mesh's vertices.
39440		 * The bias is added to the scaled sample of the displacement map.
39441		 * Without a displacement map set, this value is not applied.
39442		 *
39443		 * @type {number}
39444		 * @default 0
39445		 */
39446		this.displacementBias = 0;
39447
39448		/**
39449		 * The alpha map is a grayscale texture that controls the opacity across the
39450		 * surface (black: fully transparent; white: fully opaque).
39451		 *
39452		 * Only the color of the texture is used, ignoring the alpha channel if one
39453		 * exists. For RGB and RGBA textures, the renderer will use the green channel
39454		 * when sampling this texture due to the extra bit of precision provided for
39455		 * green in DXT-compressed and uncompressed RGB 565 formats. Luminance-only and
39456		 * luminance/alpha textures will also still work as expected.
39457		 *
39458		 * @type {?Texture}
39459		 * @default null
39460		 */
39461		this.alphaMap = null;
39462
39463		/**
39464		 * Renders the geometry as a wireframe.
39465		 *
39466		 * @type {boolean}
39467		 * @default false
39468		 */
39469		this.wireframe = false;
39470
39471		/**
39472		 * Controls the thickness of the wireframe.
39473		 *
39474		 * Can only be used with {@link SVGRenderer}.
39475		 *
39476		 * @type {number}
39477		 * @default 1
39478		 */
39479		this.wireframeLinewidth = 1;
39480
39481		/**
39482		 * Defines appearance of wireframe ends.
39483		 *
39484		 * Can only be used with {@link SVGRenderer}.
39485		 *
39486		 * @type {('round'|'bevel'|'miter')}
39487		 * @default 'round'
39488		 */
39489		this.wireframeLinecap = 'round';
39490
39491		/**
39492		 * Defines appearance of wireframe joints.
39493		 *
39494		 * Can only be used with {@link SVGRenderer}.
39495		 *
39496		 * @type {('round'|'bevel'|'miter')}
39497		 * @default 'round'
39498		 */
39499		this.wireframeLinejoin = 'round';
39500
39501		/**
39502		 * Whether the material is affected by fog or not.
39503		 *
39504		 * @type {boolean}
39505		 * @default true
39506		 */
39507		this.fog = true;
39508
39509		this.setValues( parameters );
39510
39511	}
39512
39513	copy( source ) {
39514
39515		super.copy( source );
39516
39517		this.color.copy( source.color );
39518
39519		this.map = source.map;
39520		this.gradientMap = source.gradientMap;
39521
39522		this.lightMap = source.lightMap;
39523		this.lightMapIntensity = source.lightMapIntensity;
39524
39525		this.aoMap = source.aoMap;
39526		this.aoMapIntensity = source.aoMapIntensity;
39527
39528		this.emissive.copy( source.emissive );
39529		this.emissiveMap = source.emissiveMap;
39530		this.emissiveIntensity = source.emissiveIntensity;
39531
39532		this.bumpMap = source.bumpMap;
39533		this.bumpScale = source.bumpScale;
39534
39535		this.normalMap = source.normalMap;
39536		this.normalMapType = source.normalMapType;
39537		this.normalScale.copy( source.normalScale );
39538
39539		this.displacementMap = source.displacementMap;
39540		this.displacementScale = source.displacementScale;
39541		this.displacementBias = source.displacementBias;
39542
39543		this.alphaMap = source.alphaMap;
39544
39545		this.wireframe = source.wireframe;
39546		this.wireframeLinewidth = source.wireframeLinewidth;
39547		this.wireframeLinecap = source.wireframeLinecap;
39548		this.wireframeLinejoin = source.wireframeLinejoin;
39549
39550		this.fog = source.fog;
39551
39552		return this;
39553
39554	}
39555
39556}
39557
39558/**
39559 * A material that maps the normal vectors to RGB colors.
39560 *
39561 * @augments Material
39562 * @demo scenes/material-browser.html#MeshNormalMaterial
39563 */
39564class MeshNormalMaterial extends Material {
39565
39566	/**
39567	 * Constructs a new mesh normal material.
39568	 *
39569	 * @param {Object} [parameters] - An object with one or more properties
39570	 * defining the material's appearance. Any property of the material
39571	 * (including any property from inherited materials) can be passed
39572	 * in here. Color values can be passed any type of value accepted
39573	 * by {@link Color#set}.
39574	 */
39575	constructor( parameters ) {
39576
39577		super();
39578
39579		/**
39580		 * This flag can be used for type testing.
39581		 *
39582		 * @type {boolean}
39583		 * @readonly
39584		 * @default true
39585		 */
39586		this.isMeshNormalMaterial = true;
39587
39588		this.type = 'MeshNormalMaterial';
39589
39590		/**
39591		 * The texture to create a bump map. The black and white values map to the
39592		 * perceived depth in relation to the lights. Bump doesn't actually affect
39593		 * the geometry of the object, only the lighting. If a normal map is defined
39594		 * this will be ignored.
39595		 *
39596		 * @type {?Texture}
39597		 * @default null
39598		 */
39599		this.bumpMap = null;
39600
39601		/**
39602		 * How much the bump map affects the material. Typical range is `[0,1]`.
39603		 *
39604		 * @type {number}
39605		 * @default 1
39606		 */
39607		this.bumpScale = 1;
39608
39609		/**
39610		 * The texture to create a normal map. The RGB values affect the surface
39611		 * normal for each pixel fragment and change the way the color is lit. Normal
39612		 * maps do not change the actual shape of the surface, only the lighting. In
39613		 * case the material has a normal map authored using the left handed
39614		 * convention, the `y` component of `normalScale` should be negated to compensate
39615		 * for the different handedness.
39616		 *
39617		 * @type {?Texture}
39618		 * @default null
39619		 */
39620		this.normalMap = null;
39621
39622		/**
39623		 * The type of normal map.
39624		 *
39625		 * @type {(TangentSpaceNormalMap|ObjectSpaceNormalMap)}
39626		 * @default TangentSpaceNormalMap
39627		 */
39628		this.normalMapType = TangentSpaceNormalMap;
39629
39630		/**
39631		 * How much the normal map affects the material. Typical value range is `[0,1]`.
39632		 *
39633		 * @type {Vector2}
39634		 * @default (1,1)
39635		 */
39636		this.normalScale = new Vector2( 1, 1 );
39637
39638		/**
39639		 * The displacement map affects the position of the mesh's vertices. Unlike
39640		 * other maps which only affect the light and shade of the material the
39641		 * displaced vertices can cast shadows, block other objects, and otherwise
39642		 * act as real geometry. The displacement texture is an image where the value
39643		 * of each pixel (white being the highest) is mapped against, and
39644		 * repositions, the vertices of the mesh.
39645		 *
39646		 * @type {?Texture}
39647		 * @default null
39648		 */
39649		this.displacementMap = null;
39650
39651		/**
39652		 * How much the displacement map affects the mesh (where black is no
39653		 * displacement, and white is maximum displacement). Without a displacement
39654		 * map set, this value is not applied.
39655		 *
39656		 * @type {number}
39657		 * @default 0
39658		 */
39659		this.displacementScale = 1;
39660
39661		/**
39662		 * The offset of the displacement map's values on the mesh's vertices.
39663		 * The bias is added to the scaled sample of the displacement map.
39664		 * Without a displacement map set, this value is not applied.
39665		 *
39666		 * @type {number}
39667		 * @default 0
39668		 */
39669		this.displacementBias = 0;
39670
39671		/**
39672		 * Renders the geometry as a wireframe.
39673		 *
39674		 * @type {boolean}
39675		 * @default false
39676		 */
39677		this.wireframe = false;
39678
39679		/**
39680		 * Controls the thickness of the wireframe.
39681		 *
39682		 * WebGL and WebGPU ignore this property and always render
39683		 * 1 pixel wide lines.
39684		 *
39685		 * @type {number}
39686		 * @default 1
39687		 */
39688		this.wireframeLinewidth = 1;
39689
39690		/**
39691		 * Whether the material is rendered with flat shading or not.
39692		 *
39693		 * @type {boolean}
39694		 * @default false
39695		 */
39696		this.flatShading = false;
39697
39698		this.setValues( parameters );
39699
39700	}
39701
39702	copy( source ) {
39703
39704		super.copy( source );
39705
39706		this.bumpMap = source.bumpMap;
39707		this.bumpScale = source.bumpScale;
39708
39709		this.normalMap = source.normalMap;
39710		this.normalMapType = source.normalMapType;
39711		this.normalScale.copy( source.normalScale );
39712
39713		this.displacementMap = source.displacementMap;
39714		this.displacementScale = source.displacementScale;
39715		this.displacementBias = source.displacementBias;
39716
39717		this.wireframe = source.wireframe;
39718		this.wireframeLinewidth = source.wireframeLinewidth;
39719
39720		this.flatShading = source.flatShading;
39721
39722		return this;
39723
39724	}
39725
39726}
39727
39728/**
39729 * A material for non-shiny surfaces, without specular highlights.
39730 *
39731 * The material uses a non-physically based [Lambertian](https://en.wikipedia.org/wiki/Lambertian_reflectance)
39732 * model for calculating reflectance. This can simulate some surfaces (such
39733 * as untreated wood or stone) well, but cannot simulate shiny surfaces with
39734 * specular highlights (such as varnished wood). `MeshLambertMaterial` uses per-fragment
39735 * shading.
39736 *
39737 * Due to the simplicity of the reflectance and illumination models,
39738 * performance will be greater when using this material over the
39739 * {@link MeshPhongMaterial}, {@link MeshStandardMaterial} or
39740 * {@link MeshPhysicalMaterial}, at the cost of some graphical accuracy.
39741 *
39742 * @augments Material
39743 * @demo scenes/material-browser.html#MeshLambertMaterial
39744 */
39745class MeshLambertMaterial extends Material {
39746
39747	/**
39748	 * Constructs a new mesh lambert material.
39749	 *
39750	 * @param {Object} [parameters] - An object with one or more properties
39751	 * defining the material's appearance. Any property of the material
39752	 * (including any property from inherited materials) can be passed
39753	 * in here. Color values can be passed any type of value accepted
39754	 * by {@link Color#set}.
39755	 */
39756	constructor( parameters ) {
39757
39758		super();
39759
39760		/**
39761		 * This flag can be used for type testing.
39762		 *
39763		 * @type {boolean}
39764		 * @readonly
39765		 * @default true
39766		 */
39767		this.isMeshLambertMaterial = true;
39768
39769		this.type = 'MeshLambertMaterial';
39770
39771		/**
39772		 * Color of the material.
39773		 *
39774		 * @type {Color}
39775		 * @default (1,1,1)
39776		 */
39777		this.color = new Color( 0xffffff ); // diffuse
39778
39779		/**
39780		 * The color map. May optionally include an alpha channel, typically combined
39781		 * with {@link Material#transparent} or {@link Material#alphaTest}. The texture map
39782		 * color is modulated by the diffuse `color`.
39783		 *
39784		 * @type {?Texture}
39785		 * @default null
39786		 */
39787		this.map = null;
39788
39789		/**
39790		 * The light map. Requires a second set of UVs.
39791		 *
39792		 * @type {?Texture}
39793		 * @default null
39794		 */
39795		this.lightMap = null;
39796
39797		/**
39798		 * Intensity of the baked light.
39799		 *
39800		 * @type {number}
39801		 * @default 1
39802		 */
39803		this.lightMapIntensity = 1.0;
39804
39805		/**
39806		 * The red channel of this texture is used as the ambient occlusion map.
39807		 * Requires a second set of UVs.
39808		 *
39809		 * @type {?Texture}
39810		 * @default null
39811		 */
39812		this.aoMap = null;
39813
39814		/**
39815		 * Intensity of the ambient occlusion effect. Range is `[0,1]`, where `0`
39816		 * disables ambient occlusion. Where intensity is `1` and the AO map's
39817		 * red channel is also `1`, ambient light is fully occluded on a surface.
39818		 *
39819		 * @type {number}
39820		 * @default 1
39821		 */
39822		this.aoMapIntensity = 1.0;
39823
39824		/**
39825		 * Emissive (light) color of the material, essentially a solid color
39826		 * unaffected by other lighting.
39827		 *
39828		 * @type {Color}
39829		 * @default (0,0,0)
39830		 */
39831		this.emissive = new Color( 0x000000 );
39832
39833		/**
39834		 * Intensity of the emissive light. Modulates the emissive color.
39835		 *
39836		 * @type {number}
39837		 * @default 1
39838		 */
39839		this.emissiveIntensity = 1.0;
39840
39841		/**
39842		 * Set emissive (glow) map. The emissive map color is modulated by the
39843		 * emissive color and the emissive intensity. If you have an emissive map,
39844		 * be sure to set the emissive color to something other than black.
39845		 *
39846		 * @type {?Texture}
39847		 * @default null
39848		 */
39849		this.emissiveMap = null;
39850
39851		/**
39852		 * The texture to create a bump map. The black and white values map to the
39853		 * perceived depth in relation to the lights. Bump doesn't actually affect
39854		 * the geometry of the object, only the lighting. If a normal map is defined
39855		 * this will be ignored.
39856		 *
39857		 * @type {?Texture}
39858		 * @default null
39859		 */
39860		this.bumpMap = null;
39861
39862		/**
39863		 * How much the bump map affects the material. Typical range is `[0,1]`.
39864		 *
39865		 * @type {number}
39866		 * @default 1
39867		 */
39868		this.bumpScale = 1;
39869
39870		/**
39871		 * The texture to create a normal map. The RGB values affect the surface
39872		 * normal for each pixel fragment and change the way the color is lit. Normal
39873		 * maps do not change the actual shape of the surface, only the lighting. In
39874		 * case the material has a normal map authored using the left handed
39875		 * convention, the `y` component of `normalScale` should be negated to compensate
39876		 * for the different handedness.
39877		 *
39878		 * @type {?Texture}
39879		 * @default null
39880		 */
39881		this.normalMap = null;
39882
39883		/**
39884		 * The type of normal map.
39885		 *
39886		 * @type {(TangentSpaceNormalMap|ObjectSpaceNormalMap)}
39887		 * @default TangentSpaceNormalMap
39888		 */
39889		this.normalMapType = TangentSpaceNormalMap;
39890
39891		/**
39892		 * How much the normal map affects the material. Typical value range is `[0,1]`.
39893		 *
39894		 * @type {Vector2}
39895		 * @default (1,1)
39896		 */
39897		this.normalScale = new Vector2( 1, 1 );
39898
39899		/**
39900		 * The displacement map affects the position of the mesh's vertices. Unlike
39901		 * other maps which only affect the light and shade of the material the
39902		 * displaced vertices can cast shadows, block other objects, and otherwise
39903		 * act as real geometry. The displacement texture is an image where the value
39904		 * of each pixel (white being the highest) is mapped against, and
39905		 * repositions, the vertices of the mesh.
39906		 *
39907		 * @type {?Texture}
39908		 * @default null
39909		 */
39910		this.displacementMap = null;
39911
39912		/**
39913		 * How much the displacement map affects the mesh (where black is no
39914		 * displacement, and white is maximum displacement). Without a displacement
39915		 * map set, this value is not applied.
39916		 *
39917		 * @type {number}
39918		 * @default 0
39919		 */
39920		this.displacementScale = 1;
39921
39922		/**
39923		 * The offset of the displacement map's values on the mesh's vertices.
39924		 * The bias is added to the scaled sample of the displacement map.
39925		 * Without a displacement map set, this value is not applied.
39926		 *
39927		 * @type {number}
39928		 * @default 0
39929		 */
39930		this.displacementBias = 0;
39931
39932		/**
39933		 * Specular map used by the material.
39934		 *
39935		 * @type {?Texture}
39936		 * @default null
39937		 */
39938		this.specularMap = null;
39939
39940		/**
39941		 * The alpha map is a grayscale texture that controls the opacity across the
39942		 * surface (black: fully transparent; white: fully opaque).
39943		 *
39944		 * Only the color of the texture is used, ignoring the alpha channel if one
39945		 * exists. For RGB and RGBA textures, the renderer will use the green channel
39946		 * when sampling this texture due to the extra bit of precision provided for
39947		 * green in DXT-compressed and uncompressed RGB 565 formats. Luminance-only and
39948		 * luminance/alpha textures will also still work as expected.
39949		 *
39950		 * @type {?Texture}
39951		 * @default null
39952		 */
39953		this.alphaMap = null;
39954
39955		/**
39956		 * The environment map.
39957		 *
39958		 * @type {?Texture}
39959		 * @default null
39960		 */
39961		this.envMap = null;
39962
39963		/**
39964		 * The rotation of the environment map in radians.
39965		 *
39966		 * @type {Euler}
39967		 * @default (0,0,0)
39968		 */
39969		this.envMapRotation = new Euler();
39970
39971		/**
39972		 * How to combine the result of the surface's color with the environment map, if any.
39973		 *
39974		 * When set to `MixOperation`, the {@link MeshBasicMaterial#reflectivity} is used to
39975		 * blend between the two colors.
39976		 *
39977		 * @type {(MultiplyOperation|MixOperation|AddOperation)}
39978		 * @default MultiplyOperation
39979		 */
39980		this.combine = MultiplyOperation;
39981
39982		/**
39983		 * How much the environment map affects the surface.
39984		 * The valid range is between `0` (no reflections) and `1` (full reflections).
39985		 *
39986		 * @type {number}
39987		 * @default 1
39988		 */
39989		this.reflectivity = 1;
39990
39991		/**
39992		 * Scales the effect of the environment map by multiplying its color.
39993		 *
39994		 * @type {number}
39995		 * @default 1
39996		 */
39997		this.envMapIntensity = 1.0;
39998
39999		/**
40000		 * The index of refraction (IOR) of air (approximately 1) divided by the
40001		 * index of refraction of the material. It is used with environment mapping
40002		 * modes {@link CubeRefractionMapping} and {@link EquirectangularRefractionMapping}.
40003		 * The refraction ratio should not exceed `1`.
40004		 *
40005		 * @type {number}
40006		 * @default 0.98
40007		 */
40008		this.refractionRatio = 0.98;
40009
40010		/**
40011		 * Renders the geometry as a wireframe.
40012		 *
40013		 * @type {boolean}
40014		 * @default false
40015		 */
40016		this.wireframe = false;
40017
40018		/**
40019		 * Controls the thickness of the wireframe.
40020		 *
40021		 * Can only be used with {@link SVGRenderer}.
40022		 *
40023		 * @type {number}
40024		 * @default 1
40025		 */
40026		this.wireframeLinewidth = 1;
40027
40028		/**
40029		 * Defines appearance of wireframe ends.
40030		 *
40031		 * Can only be used with {@link SVGRenderer}.
40032		 *
40033		 * @type {('round'|'bevel'|'miter')}
40034		 * @default 'round'
40035		 */
40036		this.wireframeLinecap = 'round';
40037
40038		/**
40039		 * Defines appearance of wireframe joints.
40040		 *
40041		 * Can only be used with {@link SVGRenderer}.
40042		 *
40043		 * @type {('round'|'bevel'|'miter')}
40044		 * @default 'round'
40045		 */
40046		this.wireframeLinejoin = 'round';
40047
40048		/**
40049		 * Whether the material is rendered with flat shading or not.
40050		 *
40051		 * @type {boolean}
40052		 * @default false
40053		 */
40054		this.flatShading = false;
40055
40056		/**
40057		 * Whether the material is affected by fog or not.
40058		 *
40059		 * @type {boolean}
40060		 * @default true
40061		 */
40062		this.fog = true;
40063
40064		this.setValues( parameters );
40065
40066	}
40067
40068	copy( source ) {
40069
40070		super.copy( source );
40071
40072		this.color.copy( source.color );
40073
40074		this.map = source.map;
40075
40076		this.lightMap = source.lightMap;
40077		this.lightMapIntensity = source.lightMapIntensity;
40078
40079		this.aoMap = source.aoMap;
40080		this.aoMapIntensity = source.aoMapIntensity;
40081
40082		this.emissive.copy( source.emissive );
40083		this.emissiveMap = source.emissiveMap;
40084		this.emissiveIntensity = source.emissiveIntensity;
40085
40086		this.bumpMap = source.bumpMap;
40087		this.bumpScale = source.bumpScale;
40088
40089		this.normalMap = source.normalMap;
40090		this.normalMapType = source.normalMapType;
40091		this.normalScale.copy( source.normalScale );
40092
40093		this.displacementMap = source.displacementMap;
40094		this.displacementScale = source.displacementScale;
40095		this.displacementBias = source.displacementBias;
40096
40097		this.specularMap = source.specularMap;
40098
40099		this.alphaMap = source.alphaMap;
40100
40101		this.envMap = source.envMap;
40102		this.envMapRotation.copy( source.envMapRotation );
40103		this.combine = source.combine;
40104		this.reflectivity = source.reflectivity;
40105		this.envMapIntensity = source.envMapIntensity;
40106		this.refractionRatio = source.refractionRatio;
40107
40108		this.wireframe = source.wireframe;
40109		this.wireframeLinewidth = source.wireframeLinewidth;
40110		this.wireframeLinecap = source.wireframeLinecap;
40111		this.wireframeLinejoin = source.wireframeLinejoin;
40112
40113		this.flatShading = source.flatShading;
40114
40115		this.fog = source.fog;
40116
40117		return this;
40118
40119	}
40120
40121}
40122
40123/**
40124 * A material for drawing geometry by depth. Depth is based off of the camera
40125 * near and far plane. White is nearest, black is farthest.
40126 *
40127 * @augments Material
40128 * @demo scenes/material-browser.html#MeshDepthMaterial
40129 */
40130class MeshDepthMaterial extends Material {
40131
40132	/**
40133	 * Constructs a new mesh depth 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.isMeshDepthMaterial = true;
40153
40154		this.type = 'MeshDepthMaterial';
40155
40156		/**
40157		 * Type for depth packing.
40158		 *
40159		 * @type {(BasicDepthPacking|RGBADepthPacking|RGBDepthPacking|RGDepthPacking)}
40160		 * @default BasicDepthPacking
40161		 */
40162		this.depthPacking = BasicDepthPacking;
40163
40164		/**
40165		 * The color map. May optionally include an alpha channel, typically combined
40166		 * with {@link Material#transparent} or {@link Material#alphaTest}.
40167		 *
40168		 * @type {?Texture}
40169		 * @default null
40170		 */
40171		this.map = null;
40172
40173		/**
40174		 * The alpha map is a grayscale texture that controls the opacity across the
40175		 * surface (black: fully transparent; white: fully opaque).
40176		 *
40177		 * Only the color of the texture is used, ignoring the alpha channel if one
40178		 * exists. For RGB and RGBA textures, the renderer will use the green channel
40179		 * when sampling this texture due to the extra bit of precision provided for
40180		 * green in DXT-compressed and uncompressed RGB 565 formats. Luminance-only and
40181		 * luminance/alpha textures will also still work as expected.
40182		 *
40183		 * @type {?Texture}
40184		 * @default null
40185		 */
40186		this.alphaMap = null;
40187
40188		/**
40189		 * The displacement map affects the position of the mesh's vertices. Unlike
40190		 * other maps which only affect the light and shade of the material the
40191		 * displaced vertices can cast shadows, block other objects, and otherwise
40192		 * act as real geometry. The displacement texture is an image where the value
40193		 * of each pixel (white being the highest) is mapped against, and
40194		 * repositions, the vertices of the mesh.
40195		 *
40196		 * @type {?Texture}
40197		 * @default null
40198		 */
40199		this.displacementMap = null;
40200
40201		/**
40202		 * How much the displacement map affects the mesh (where black is no
40203		 * displacement, and white is maximum displacement). Without a displacement
40204		 * map set, this value is not applied.
40205		 *
40206		 * @type {number}
40207		 * @default 0
40208		 */
40209		this.displacementScale = 1;
40210
40211		/**
40212		 * The offset of the displacement map's values on the mesh's vertices.
40213		 * The bias is added to the scaled sample of the displacement map.
40214		 * Without a displacement map set, this value is not applied.
40215		 *
40216		 * @type {number}
40217		 * @default 0
40218		 */
40219		this.displacementBias = 0;
40220
40221		/**
40222		 * Renders the geometry as a wireframe.
40223		 *
40224		 * @type {boolean}
40225		 * @default false
40226		 */
40227		this.wireframe = false;
40228
40229		/**
40230		 * Controls the thickness of the wireframe.
40231		 *
40232		 * WebGL and WebGPU ignore this property and always render
40233		 * 1 pixel wide lines.
40234		 *
40235		 * @type {number}
40236		 * @default 1
40237		 */
40238		this.wireframeLinewidth = 1;
40239
40240		this.setValues( parameters );
40241
40242	}
40243
40244	copy( source ) {
40245
40246		super.copy( source );
40247
40248		this.depthPacking = source.depthPacking;
40249
40250		this.map = source.map;
40251
40252		this.alphaMap = source.alphaMap;
40253
40254		this.displacementMap = source.displacementMap;
40255		this.displacementScale = source.displacementScale;
40256		this.displacementBias = source.displacementBias;
40257
40258		this.wireframe = source.wireframe;
40259		this.wireframeLinewidth = source.wireframeLinewidth;
40260
40261		return this;
40262
40263	}
40264
40265}
40266
40267/**
40268 * A material used internally for implementing shadow mapping with
40269 * point lights.
40270 *
40271 * Can also be used to customize the shadow casting of an object by assigning
40272 * an instance of `MeshDistanceMaterial` to {@link Object3D#customDistanceMaterial}.
40273 * The following examples demonstrates this approach in order to ensure
40274 * transparent parts of objects do not cast shadows.
40275 *
40276 * @augments Material
40277 */
40278class MeshDistanceMaterial extends Material {
40279
40280	/**
40281	 * Constructs a new mesh distance material.
40282	 *
40283	 * @param {Object} [parameters] - An object with one or more properties
40284	 * defining the material's appearance. Any property of the material
40285	 * (including any property from inherited materials) can be passed
40286	 * in here. Color values can be passed any type of value accepted
40287	 * by {@link Color#set}.
40288	 */
40289	constructor( parameters ) {
40290
40291		super();
40292
40293		/**
40294		 * This flag can be used for type testing.
40295		 *
40296		 * @type {boolean}
40297		 * @readonly
40298		 * @default true
40299		 */
40300		this.isMeshDistanceMaterial = true;
40301
40302		this.type = 'MeshDistanceMaterial';
40303
40304		/**
40305		 * The color map. May optionally include an alpha channel, typically combined
40306		 * with {@link Material#transparent} or {@link Material#alphaTest}.
40307		 *
40308		 * @type {?Texture}
40309		 * @default null
40310		 */
40311		this.map = null;
40312
40313		/**
40314		 * The alpha map is a grayscale texture that controls the opacity across the
40315		 * surface (black: fully transparent; white: fully opaque).
40316		 *
40317		 * Only the color of the texture is used, ignoring the alpha channel if one
40318		 * exists. For RGB and RGBA textures, the renderer will use the green channel
40319		 * when sampling this texture due to the extra bit of precision provided for
40320		 * green in DXT-compressed and uncompressed RGB 565 formats. Luminance-only and
40321		 * luminance/alpha textures will also still work as expected.
40322		 *
40323		 * @type {?Texture}
40324		 * @default null
40325		 */
40326		this.alphaMap = null;
40327
40328		/**
40329		 * The displacement map affects the position of the mesh's vertices. Unlike
40330		 * other maps which only affect the light and shade of the material the
40331		 * displaced vertices can cast shadows, block other objects, and otherwise
40332		 * act as real geometry. The displacement texture is an image where the value
40333		 * of each pixel (white being the highest) is mapped against, and
40334		 * repositions, the vertices of the mesh.
40335		 *
40336		 * @type {?Texture}
40337		 * @default null
40338		 */
40339		this.displacementMap = null;
40340
40341		/**
40342		 * How much the displacement map affects the mesh (where black is no
40343		 * displacement, and white is maximum displacement). Without a displacement
40344		 * map set, this value is not applied.
40345		 *
40346		 * @type {number}
40347		 * @default 0
40348		 */
40349		this.displacementScale = 1;
40350
40351		/**
40352		 * The offset of the displacement map's values on the mesh's vertices.
40353		 * The bias is added to the scaled sample of the displacement map.
40354		 * Without a displacement map set, this value is not applied.
40355		 *
40356		 * @type {number}
40357		 * @default 0
40358		 */
40359		this.displacementBias = 0;
40360
40361		this.setValues( parameters );
40362
40363	}
40364
40365	copy( source ) {
40366
40367		super.copy( source );
40368
40369		this.map = source.map;
40370
40371		this.alphaMap = source.alphaMap;
40372
40373		this.displacementMap = source.displacementMap;
40374		this.displacementScale = source.displacementScale;
40375		this.displacementBias = source.displacementBias;
40376
40377		return this;
40378
40379	}
40380
40381}
40382
40383/**
40384 * This material is defined by a MatCap (or Lit Sphere) texture, which encodes the
40385 * material color and shading.
40386 *
40387 * `MeshMatcapMaterial` does not respond to lights since the matcap image file encodes
40388 * baked lighting. It will cast a shadow onto an object that receives shadows
40389 * (and shadow clipping works), but it will not self-shadow or receive
40390 * shadows.
40391 *
40392 * @augments Material
40393 * @demo scenes/material-browser.html#MeshMatcapMaterial
40394 */
40395class MeshMatcapMaterial extends Material {
40396
40397	/**
40398	 * Constructs a new mesh matcap material.
40399	 *
40400	 * @param {Object} [parameters] - An object with one or more properties
40401	 * defining the material's appearance. Any property of the material
40402	 * (including any property from inherited materials) can be passed
40403	 * in here. Color values can be passed any type of value accepted
40404	 * by {@link Color#set}.
40405	 */
40406	constructor( parameters ) {
40407
40408		super();
40409
40410		/**
40411		 * This flag can be used for type testing.
40412		 *
40413		 * @type {boolean}
40414		 * @readonly
40415		 * @default true
40416		 */
40417		this.isMeshMatcapMaterial = true;
40418
40419		this.defines = { 'MATCAP': '' };
40420
40421		this.type = 'MeshMatcapMaterial';
40422
40423		/**
40424		 * Color of the material.
40425		 *
40426		 * @type {Color}
40427		 * @default (1,1,1)
40428		 */
40429		this.color = new Color( 0xffffff ); // diffuse
40430
40431		/**
40432		 * The matcap map.
40433		 *
40434		 * @type {?Texture}
40435		 * @default null
40436		 */
40437		this.matcap = null;
40438
40439		/**
40440		 * The color map. May optionally include an alpha channel, typically combined
40441		 * with {@link Material#transparent} or {@link Material#alphaTest}. The texture map
40442		 * color is modulated by the diffuse `color`.
40443		 *
40444		 * @type {?Texture}
40445		 * @default null
40446		 */
40447		this.map = null;
40448
40449		/**
40450		 * The texture to create a bump map. The black and white values map to the
40451		 * perceived depth in relation to the lights. Bump doesn't actually affect
40452		 * the geometry of the object, only the lighting. If a normal map is defined
40453		 * this will be ignored.
40454		 *
40455		 * @type {?Texture}
40456		 * @default null
40457		 */
40458		this.bumpMap = null;
40459
40460		/**
40461		 * How much the bump map affects the material. Typical range is `[0,1]`.
40462		 *
40463		 * @type {number}
40464		 * @default 1
40465		 */
40466		this.bumpScale = 1;
40467
40468		/**
40469		 * The texture to create a normal map. The RGB values affect the surface
40470		 * normal for each pixel fragment and change the way the color is lit. Normal
40471		 * maps do not change the actual shape of the surface, only the lighting. In
40472		 * case the material has a normal map authored using the left handed
40473		 * convention, the `y` component of `normalScale` should be negated to compensate
40474		 * for the different handedness.
40475		 *
40476		 * @type {?Texture}
40477		 * @default null
40478		 */
40479		this.normalMap = null;
40480
40481		/**
40482		 * The type of normal map.
40483		 *
40484		 * @type {(TangentSpaceNormalMap|ObjectSpaceNormalMap)}
40485		 * @default TangentSpaceNormalMap
40486		 */
40487		this.normalMapType = TangentSpaceNormalMap;
40488
40489		/**
40490		 * How much the normal map affects the material. Typical value range is `[0,1]`.
40491		 *
40492		 * @type {Vector2}
40493		 * @default (1,1)
40494		 */
40495		this.normalScale = new Vector2( 1, 1 );
40496
40497		/**
40498		 * The displacement map affects the position of the mesh's vertices. Unlike
40499		 * other maps which only affect the light and shade of the material the
40500		 * displaced vertices can cast shadows, block other objects, and otherwise
40501		 * act as real geometry. The displacement texture is an image where the value
40502		 * of each pixel (white being the highest) is mapped against, and
40503		 * repositions, the vertices of the mesh.
40504		 *
40505		 * @type {?Texture}
40506		 * @default null
40507		 */
40508		this.displacementMap = null;
40509
40510		/**
40511		 * How much the displacement map affects the mesh (where black is no
40512		 * displacement, and white is maximum displacement). Without a displacement
40513		 * map set, this value is not applied.
40514		 *
40515		 * @type {number}
40516		 * @default 0
40517		 */
40518		this.displacementScale = 1;
40519
40520		/**
40521		 * The offset of the displacement map's values on the mesh's vertices.
40522		 * The bias is added to the scaled sample of the displacement map.
40523		 * Without a displacement map set, this value is not applied.
40524		 *
40525		 * @type {number}
40526		 * @default 0
40527		 */
40528		this.displacementBias = 0;
40529
40530		/**
40531		 * The alpha map is a grayscale texture that controls the opacity across the
40532		 * surface (black: fully transparent; white: fully opaque).
40533		 *
40534		 * Only the color of the texture is used, ignoring the alpha channel if one
40535		 * exists. For RGB and RGBA textures, the renderer will use the green channel
40536		 * when sampling this texture due to the extra bit of precision provided for
40537		 * green in DXT-compressed and uncompressed RGB 565 formats. Luminance-only and
40538		 * luminance/alpha textures will also still work as expected.
40539		 *
40540		 * @type {?Texture}
40541		 * @default null
40542		 */
40543		this.alphaMap = null;
40544
40545		/**
40546		 * Renders the geometry as a wireframe.
40547		 *
40548		 * @type {boolean}
40549		 * @default false
40550		 */
40551		this.wireframe = false;
40552
40553		/**
40554		 * Controls the thickness of the wireframe.
40555		 *
40556		 * Can only be used with {@link SVGRenderer}.
40557		 *
40558		 * @type {number}
40559		 * @default 1
40560		 */
40561		this.wireframeLinewidth = 1;
40562
40563		/**
40564		 * Whether the material is rendered with flat shading or not.
40565		 *
40566		 * @type {boolean}
40567		 * @default false
40568		 */
40569		this.flatShading = false;
vendor: 13,654 bytes, lines 40570-41167
40570
40571		/**
40572		 * Whether the material is affected by fog or not.
40573		 *
40574		 * @type {boolean}
40575		 * @default true
40576		 */
40577		this.fog = true;
40578
40579		this.setValues( parameters );
40580
40581	}
40582
40583
40584	copy( source ) {
40585
40586		super.copy( source );
40587
40588		this.defines = { 'MATCAP': '' };
40589
40590		this.color.copy( source.color );
40591
40592		this.matcap = source.matcap;
40593
40594		this.map = source.map;
40595
40596		this.bumpMap = source.bumpMap;
40597		this.bumpScale = source.bumpScale;
40598
40599		this.normalMap = source.normalMap;
40600		this.normalMapType = source.normalMapType;
40601		this.normalScale.copy( source.normalScale );
40602
40603		this.displacementMap = source.displacementMap;
40604		this.displacementScale = source.displacementScale;
40605		this.displacementBias = source.displacementBias;
40606
40607		this.alphaMap = source.alphaMap;
40608
40609		this.wireframe = source.wireframe;
40610		this.wireframeLinewidth = source.wireframeLinewidth;
40611
40612		this.flatShading = source.flatShading;
40613
40614		this.fog = source.fog;
40615
40616		return this;
40617
40618	}
40619
40620}
40621
40622/**
40623 * A material for rendering line primitives.
40624 *
40625 * Materials define the appearance of renderable 3D objects.
40626 *
40627 * ```js
40628 * const material = new THREE.LineDashedMaterial( {
40629 * 	color: 0xffffff,
40630 * 	scale: 1,
40631 * 	dashSize: 3,
40632 * 	gapSize: 1,
40633 * } );
40634 * ```
40635 *
40636 * @augments LineBasicMaterial
40637 */
40638class LineDashedMaterial extends LineBasicMaterial {
40639
40640	/**
40641	 * Constructs a new line dashed material.
40642	 *
40643	 * @param {Object} [parameters] - An object with one or more properties
40644	 * defining the material's appearance. Any property of the material
40645	 * (including any property from inherited materials) can be passed
40646	 * in here. Color values can be passed any type of value accepted
40647	 * by {@link Color#set}.
40648	 */
40649	constructor( parameters ) {
40650
40651		super();
40652
40653		/**
40654		 * This flag can be used for type testing.
40655		 *
40656		 * @type {boolean}
40657		 * @readonly
40658		 * @default true
40659		 */
40660		this.isLineDashedMaterial = true;
40661		this.type = 'LineDashedMaterial';
40662
40663		/**
40664		 * The scale of the dashed part of a line.
40665		 *
40666		 * @type {number}
40667		 * @default 1
40668		 */
40669		this.scale = 1;
40670
40671		/**
40672		 * The size of the dash. This is both the gap with the stroke.
40673		 *
40674		 * @type {number}
40675		 * @default 3
40676		 */
40677		this.dashSize = 3;
40678
40679		/**
40680		 * The size of the gap.
40681		 *
40682		 * @type {number}
40683		 * @default 1
40684		 */
40685		this.gapSize = 1;
40686
40687		this.setValues( parameters );
40688
40689	}
40690
40691	copy( source ) {
40692
40693		super.copy( source );
40694
40695		this.scale = source.scale;
40696		this.dashSize = source.dashSize;
40697		this.gapSize = source.gapSize;
40698
40699		return this;
40700
40701	}
40702
40703}
40704
40705/**
40706 * Converts an array to a specific type.
40707 *
40708 * @param {TypedArray|Array} array - The array to convert.
40709 * @param {TypedArray.constructor} type - The constructor of a typed array that defines the new type.
40710 * @return {TypedArray} The converted array.
40711 */
40712function convertArray( array, type ) {
40713
40714	if ( ! array || array.constructor === type ) return array;
40715
40716	if ( typeof type.BYTES_PER_ELEMENT === 'number' ) {
40717
40718		return new type( array ); // create typed array
40719
40720	}
40721
40722	return Array.prototype.slice.call( array ); // create Array
40723
40724}
40725
40726/**
40727 * Returns an array by which times and values can be sorted.
40728 *
40729 * @param {Array<number>} times - The keyframe time values.
40730 * @return {Array<number>} The array.
40731 */
40732function getKeyframeOrder( times ) {
40733
40734	function compareTime( i, j ) {
40735
40736		return times[ i ] - times[ j ];
40737
40738	}
40739
40740	const n = times.length;
40741	const result = new Array( n );
40742	for ( let i = 0; i !== n; ++ i ) result[ i ] = i;
40743
40744	result.sort( compareTime );
40745
40746	return result;
40747
40748}
40749
40750/**
40751 * Sorts the given array by the previously computed order via `getKeyframeOrder()`.
40752 *
40753 * @param {Array<number>} values - The values to sort.
40754 * @param {number} stride - The stride.
40755 * @param {Array<number>} order - The sort order.
40756 * @return {Array<number>} The sorted values.
40757 */
40758function sortedArray( values, stride, order ) {
40759
40760	const nValues = values.length;
40761	const result = new values.constructor( nValues );
40762
40763	for ( let i = 0, dstOffset = 0; dstOffset !== nValues; ++ i ) {
40764
40765		const srcOffset = order[ i ] * stride;
40766
40767		for ( let j = 0; j !== stride; ++ j ) {
40768
40769			result[ dstOffset ++ ] = values[ srcOffset + j ];
40770
40771		}
40772
40773	}
40774
40775	return result;
40776
40777}
40778
40779/**
40780 * Used for parsing AOS keyframe formats.
40781 *
40782 * @param {Array<number>} jsonKeys - A list of JSON keyframes.
40783 * @param {Array<number>} times - This array will be filled with keyframe times by this function.
40784 * @param {Array<number>} values - This array will be filled with keyframe values by this function.
40785 * @param {string} valuePropertyName - The name of the property to use.
40786 */
40787function flattenJSON( jsonKeys, times, values, valuePropertyName ) {
40788
40789	let i = 1, key = jsonKeys[ 0 ];
40790
40791	while ( key !== undefined && key[ valuePropertyName ] === undefined ) {
40792
40793		key = jsonKeys[ i ++ ];
40794
40795	}
40796
40797	if ( key === undefined ) return; // no data
40798
40799	let value = key[ valuePropertyName ];
40800	if ( value === undefined ) return; // no data
40801
40802	if ( Array.isArray( value ) ) {
40803
40804		do {
40805
40806			value = key[ valuePropertyName ];
40807
40808			if ( value !== undefined ) {
40809
40810				times.push( key.time );
40811				values.push( ...value ); // push all elements
40812
40813			}
40814
40815			key = jsonKeys[ i ++ ];
40816
40817		} while ( key !== undefined );
40818
40819	} else if ( value.toArray !== undefined ) {
40820
40821		// ...assume THREE.Math-ish
40822
40823		do {
40824
40825			value = key[ valuePropertyName ];
40826
40827			if ( value !== undefined ) {
40828
40829				times.push( key.time );
40830				value.toArray( values, values.length );
40831
40832			}
40833
40834			key = jsonKeys[ i ++ ];
40835
40836		} while ( key !== undefined );
40837
40838	} else {
40839
40840		// otherwise push as-is
40841
40842		do {
40843
40844			value = key[ valuePropertyName ];
40845
40846			if ( value !== undefined ) {
40847
40848				times.push( key.time );
40849				values.push( value );
40850
40851			}
40852
40853			key = jsonKeys[ i ++ ];
40854
40855		} while ( key !== undefined );
40856
40857	}
40858
40859}
40860
40861/**
40862 * Creates a new clip, containing only the segment of the original clip between the given frames.
40863 *
40864 * @param {AnimationClip} sourceClip - The values to sort.
40865 * @param {string} name - The name of the clip.
40866 * @param {number} startFrame - The start frame.
40867 * @param {number} endFrame - The end frame.
40868 * @param {number} [fps=30] - The FPS.
40869 * @return {AnimationClip} The new sub clip.
40870 */
40871function subclip( sourceClip, name, startFrame, endFrame, fps = 30 ) {
40872
40873	const clip = sourceClip.clone();
40874
40875	clip.name = name;
40876
40877	const tracks = [];
40878
40879	for ( let i = 0; i < clip.tracks.length; ++ i ) {
40880
40881		const track = clip.tracks[ i ];
40882		const valueSize = track.getValueSize();
40883
40884		const times = [];
40885		const values = [];
40886
40887		for ( let j = 0; j < track.times.length; ++ j ) {
40888
40889			const frame = track.times[ j ] * fps;
40890
40891			if ( frame < startFrame || frame >= endFrame ) continue;
40892
40893			times.push( track.times[ j ] );
40894
40895			for ( let k = 0; k < valueSize; ++ k ) {
40896
40897				values.push( track.values[ j * valueSize + k ] );
40898
40899			}
40900
40901		}
40902
40903		if ( times.length === 0 ) continue;
40904
40905		track.times = convertArray( times, track.times.constructor );
40906		track.values = convertArray( values, track.values.constructor );
40907
40908		tracks.push( track );
40909
40910	}
40911
40912	clip.tracks = tracks;
40913
40914	// find minimum .times value across all tracks in the trimmed clip
40915
40916	let minStartTime = Infinity;
40917
40918	for ( let i = 0; i < clip.tracks.length; ++ i ) {
40919
40920		if ( minStartTime > clip.tracks[ i ].times[ 0 ] ) {
40921
40922			minStartTime = clip.tracks[ i ].times[ 0 ];
40923
40924		}
40925
40926	}
40927
40928	// shift all tracks such that clip begins at t=0
40929
40930	for ( let i = 0; i < clip.tracks.length; ++ i ) {
40931
40932		clip.tracks[ i ].shift( -1 * minStartTime );
40933
40934	}
40935
40936	clip.resetDuration();
40937
40938	return clip;
40939
40940}
40941
40942/**
40943 * Converts the keyframes of the given animation clip to an additive format.
40944 *
40945 * @param {AnimationClip} targetClip - The clip to make additive.
40946 * @param {number} [referenceFrame=0] - The reference frame.
40947 * @param {AnimationClip} [referenceClip=targetClip] - The reference clip.
40948 * @param {number} [fps=30] - The FPS.
40949 * @return {AnimationClip} The updated clip which is now additive.
40950 */
40951function makeClipAdditive( targetClip, referenceFrame = 0, referenceClip = targetClip, fps = 30 ) {
40952
40953	if ( fps <= 0 ) fps = 30;
40954
40955	const numTracks = referenceClip.tracks.length;
40956	const referenceTime = referenceFrame / fps;
40957
40958	// Make each track's values relative to the values at the reference frame
40959	for ( let i = 0; i < numTracks; ++ i ) {
40960
40961		const referenceTrack = referenceClip.tracks[ i ];
40962		const referenceTrackType = referenceTrack.ValueTypeName;
40963
40964		// Skip this track if it's non-numeric
40965		if ( referenceTrackType === 'bool' || referenceTrackType === 'string' ) continue;
40966
40967		// Find the track in the target clip whose name and type matches the reference track
40968		const targetTrack = targetClip.tracks.find( function ( track ) {
40969
40970			return track.name === referenceTrack.name
40971				&& track.ValueTypeName === referenceTrackType;
40972
40973		} );
40974
40975		if ( targetTrack === undefined ) continue;
40976
40977		let referenceOffset = 0;
40978		const referenceValueSize = referenceTrack.getValueSize();
40979
40980		if ( referenceTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline ) {
40981
40982			referenceOffset = referenceValueSize / 3;
40983
40984		}
40985
40986		let targetOffset = 0;
40987		const targetValueSize = targetTrack.getValueSize();
40988
40989		if ( targetTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline ) {
40990
40991			targetOffset = targetValueSize / 3;
40992
40993		}
40994
40995		const lastIndex = referenceTrack.times.length - 1;
40996		let referenceValue;
40997
40998		// Find the value to subtract out of the track
40999		if ( referenceTime <= referenceTrack.times[ 0 ] ) {
41000
41001			// Reference frame is earlier than the first keyframe, so just use the first keyframe
41002			const startIndex = referenceOffset;
41003			const endIndex = referenceValueSize - referenceOffset;
41004			referenceValue = referenceTrack.values.slice( startIndex, endIndex );
41005
41006		} else if ( referenceTime >= referenceTrack.times[ lastIndex ] ) {
41007
41008			// Reference frame is after the last keyframe, so just use the last keyframe
41009			const startIndex = lastIndex * referenceValueSize + referenceOffset;
41010			const endIndex = startIndex + referenceValueSize - referenceOffset;
41011			referenceValue = referenceTrack.values.slice( startIndex, endIndex );
41012
41013		} else {
41014
41015			// Interpolate to the reference value
41016			const interpolant = referenceTrack.createInterpolant();
41017			const startIndex = referenceOffset;
41018			const endIndex = referenceValueSize - referenceOffset;
41019			interpolant.evaluate( referenceTime );
41020			referenceValue = interpolant.resultBuffer.slice( startIndex, endIndex );
41021
41022		}
41023
41024		// Conjugate the quaternion
41025		if ( referenceTrackType === 'quaternion' ) {
41026
41027			const referenceQuat = new Quaternion().fromArray( referenceValue ).normalize().conjugate();
41028			referenceQuat.toArray( referenceValue );
41029
41030		}
41031
41032		// Subtract the reference value from all of the track values
41033
41034		const numTimes = targetTrack.times.length;
41035		for ( let j = 0; j < numTimes; ++ j ) {
41036
41037			const valueStart = j * targetValueSize + targetOffset;
41038
41039			if ( referenceTrackType === 'quaternion' ) {
41040
41041				// Multiply the conjugate for quaternion track types
41042				Quaternion.multiplyQuaternionsFlat(
41043					targetTrack.values,
41044					valueStart,
41045					referenceValue,
41046					0,
41047					targetTrack.values,
41048					valueStart
41049				);
41050
41051			} else {
41052
41053				const valueEnd = targetValueSize - targetOffset * 2;
41054
41055				// Subtract each value for all other numeric track types
41056				for ( let k = 0; k < valueEnd; ++ k ) {
41057
41058					targetTrack.values[ valueStart + k ] -= referenceValue[ k ];
41059
41060				}
41061
41062			}
41063
41064		}
41065
41066	}
41067
41068	targetClip.blendMode = AdditiveAnimationBlendMode;
41069
41070	return targetClip;
41071
41072}
41073
41074/**
41075 * A class with various methods to assist with animations.
41076 *
41077 * @hideconstructor
41078 */
41079class AnimationUtils {
41080
41081	/**
41082	 * Converts an array to a specific type
41083	 *
41084	 * @static
41085	 * @param {TypedArray|Array} array - The array to convert.
41086	 * @param {TypedArray.constructor} type - The constructor of a type array.
41087	 * @return {TypedArray} The converted array
41088	 */
41089	static convertArray( array, type ) {
41090
41091		return convertArray( array, type );
41092
41093	}
41094
41095	/**
41096	 * Returns `true` if the given object is a typed array.
41097	 *
41098	 * @static
41099	 * @param {any} object - The object to check.
41100	 * @return {boolean} Whether the given object is a typed array.
41101	 */
41102	static isTypedArray( object ) {
41103
41104		return isTypedArray( object );
41105
41106	}
41107
41108	/**
41109	 * Returns an array by which times and values can be sorted.
41110	 *
41111	 * @static
41112	 * @param {Array<number>} times - The keyframe time values.
41113	 * @return {Array<number>} The array.
41114	 */
41115	static getKeyframeOrder( times ) {
41116
41117		return getKeyframeOrder( times );
41118
41119	}
41120
41121	/**
41122	 * Sorts the given array by the previously computed order via `getKeyframeOrder()`.
41123	 *
41124	 * @static
41125	 * @param {Array<number>} values - The values to sort.
41126	 * @param {number} stride - The stride.
41127	 * @param {Array<number>} order - The sort order.
41128	 * @return {Array<number>} The sorted values.
41129	 */
41130	static sortedArray( values, stride, order ) {
41131
41132		return sortedArray( values, stride, order );
41133
41134	}
41135
41136	/**
41137	 * Used for parsing AOS keyframe formats.
41138	 *
41139	 * @static
41140	 * @param {Array<number>} jsonKeys - A list of JSON keyframes.
41141	 * @param {Array<number>} times - This array will be filled with keyframe times by this method.
41142	 * @param {Array<number>} values - This array will be filled with keyframe values by this method.
41143	 * @param {string} valuePropertyName - The name of the property to use.
41144	 */
41145	static flattenJSON( jsonKeys, times, values, valuePropertyName ) {
41146
41147		flattenJSON( jsonKeys, times, values, valuePropertyName );
41148
41149	}
41150
41151	/**
41152	 * Creates a new clip, containing only the segment of the original clip between the given frames.
41153	 *
41154	 * @static
41155	 * @param {AnimationClip} sourceClip - The values to sort.
41156	 * @param {string} name - The name of the clip.
41157	 * @param {number} startFrame - The start frame.
41158	 * @param {number} endFrame - The end frame.
41159	 * @param {number} [fps=30] - The FPS.
41160	 * @return {AnimationClip} The new sub clip.
41161	 */
41162	static subclip( sourceClip, name, startFrame, endFrame, fps = 30 ) {
41163
41164		return subclip( sourceClip, name, startFrame, endFrame, fps );
41165
41166	}
41167
41168	/**
41169	 * Converts the keyframes of the given animation clip to an additive format.
41170	 *
41171	 * @static
41172	 * @param {AnimationClip} targetClip - The clip to make additive.
41173	 * @param {number} [referenceFrame=0] - The reference frame.
41174	 * @param {AnimationClip} [referenceClip=targetClip] - The reference clip.
41175	 * @param {number} [fps=30] - The FPS.
41176	 * @return {AnimationClip} The updated clip which is now additive.
41177	 */
41178	static makeClipAdditive( targetClip, referenceFrame = 0, referenceClip = targetClip, fps = 30 ) {
41179
41180		return makeClipAdditive( targetClip, referenceFrame, referenceClip, fps
vendor: 34,349 bytes, lines 41180-42758
41180 );
41181
41182	}
41183
41184}
41185
41186/**
41187 * Abstract base class of interpolants over parametric samples.
41188 *
41189 * The parameter domain is one dimensional, typically the time or a path
41190 * along a curve defined by the data.
41191 *
41192 * The sample values can have any dimensionality and derived classes may
41193 * apply special interpretations to the data.
41194 *
41195 * This class provides the interval seek in a Template Method, deferring
41196 * the actual interpolation to derived classes.
41197 *
41198 * Time complexity is O(1) for linear access crossing at most two points
41199 * and O(log N) for random access, where N is the number of positions.
41200 *
41201 * References: {@link http://www.oodesign.com/template-method-pattern.html}
41202 *
41203 * @abstract
41204 */
41205class Interpolant {
41206
41207	/**
41208	 * Constructs a new interpolant.
41209	 *
41210	 * @param {TypedArray} parameterPositions - The parameter positions hold the interpolation factors.
41211	 * @param {TypedArray} sampleValues - The sample values.
41212	 * @param {number} sampleSize - The sample size
41213	 * @param {TypedArray} [resultBuffer] - The result buffer.
41214	 */
41215	constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
41216
41217		/**
41218		 * The parameter positions.
41219		 *
41220		 * @type {TypedArray}
41221		 */
41222		this.parameterPositions = parameterPositions;
41223
41224		/**
41225		 * A cache index.
41226		 *
41227		 * @private
41228		 * @type {number}
41229		 * @default 0
41230		 */
41231		this._cachedIndex = 0;
41232
41233		/**
41234		 * The result buffer.
41235		 *
41236		 * @type {TypedArray}
41237		 */
41238		this.resultBuffer = resultBuffer !== undefined ? resultBuffer : new sampleValues.constructor( sampleSize );
41239
41240		/**
41241		 * The sample values.
41242		 *
41243		 * @type {TypedArray}
41244		 */
41245		this.sampleValues = sampleValues;
41246
41247		/**
41248		 * The value size.
41249		 *
41250		 * @type {TypedArray}
41251		 */
41252		this.valueSize = sampleSize;
41253
41254		/**
41255		 * The interpolation settings.
41256		 *
41257		 * @type {?Object}
41258		 * @default null
41259		 */
41260		this.settings = null;
41261
41262		/**
41263		 * The default settings object.
41264		 *
41265		 * @type {Object}
41266		 */
41267		this.DefaultSettings_ = {};
41268
41269	}
41270
41271	/**
41272	 * Evaluate the interpolant at position `t`.
41273	 *
41274	 * @param {number} t - The interpolation factor.
41275	 * @return {TypedArray} The result buffer.
41276	 */
41277	evaluate( t ) {
41278
41279		const pp = this.parameterPositions;
41280		let i1 = this._cachedIndex,
41281			t1 = pp[ i1 ],
41282			t0 = pp[ i1 - 1 ];
41283
41284		validate_interval: {
41285
41286			seek: {
41287
41288				let right;
41289
41290				linear_scan: {
41291
41292					//- See http://jsperf.com/comparison-to-undefined/3
41293					//- slower code:
41294					//-
41295					//- 				if ( t >= t1 || t1 === undefined ) {
41296					forward_scan: if ( ! ( t < t1 ) ) {
41297
41298						for ( let giveUpAt = i1 + 2; ; ) {
41299
41300							if ( t1 === undefined ) {
41301
41302								if ( t < t0 ) break forward_scan;
41303
41304								// after end
41305
41306								i1 = pp.length;
41307								this._cachedIndex = i1;
41308								return this.copySampleValue_( i1 - 1 );
41309
41310							}
41311
41312							if ( i1 === giveUpAt ) break; // this loop
41313
41314							t0 = t1;
41315							t1 = pp[ ++ i1 ];
41316
41317							if ( t < t1 ) {
41318
41319								// we have arrived at the sought interval
41320								break seek;
41321
41322							}
41323
41324						}
41325
41326						// prepare binary search on the right side of the index
41327						right = pp.length;
41328						break linear_scan;
41329
41330					}
41331
41332					//- slower code:
41333					//-					if ( t < t0 || t0 === undefined ) {
41334					if ( ! ( t >= t0 ) ) {
41335
41336						// looping?
41337
41338						const t1global = pp[ 1 ];
41339
41340						if ( t < t1global ) {
41341
41342							i1 = 2; // + 1, using the scan for the details
41343							t0 = t1global;
41344
41345						}
41346
41347						// linear reverse scan
41348
41349						for ( let giveUpAt = i1 - 2; ; ) {
41350
41351							if ( t0 === undefined ) {
41352
41353								// before start
41354
41355								this._cachedIndex = 0;
41356								return this.copySampleValue_( 0 );
41357
41358							}
41359
41360							if ( i1 === giveUpAt ) break; // this loop
41361
41362							t1 = t0;
41363							t0 = pp[ -- i1 - 1 ];
41364
41365							if ( t >= t0 ) {
41366
41367								// we have arrived at the sought interval
41368								break seek;
41369
41370							}
41371
41372						}
41373
41374						// prepare binary search on the left side of the index
41375						right = i1;
41376						i1 = 0;
41377						break linear_scan;
41378
41379					}
41380
41381					// the interval is valid
41382
41383					break validate_interval;
41384
41385				} // linear scan
41386
41387				// binary search
41388
41389				while ( i1 < right ) {
41390
41391					const mid = ( i1 + right ) >>> 1;
41392
41393					if ( t < pp[ mid ] ) {
41394
41395						right = mid;
41396
41397					} else {
41398
41399						i1 = mid + 1;
41400
41401					}
41402
41403				}
41404
41405				t1 = pp[ i1 ];
41406				t0 = pp[ i1 - 1 ];
41407
41408				// check boundary cases, again
41409
41410				if ( t0 === undefined ) {
41411
41412					this._cachedIndex = 0;
41413					return this.copySampleValue_( 0 );
41414
41415				}
41416
41417				if ( t1 === undefined ) {
41418
41419					i1 = pp.length;
41420					this._cachedIndex = i1;
41421					return this.copySampleValue_( i1 - 1 );
41422
41423				}
41424
41425			} // seek
41426
41427			this._cachedIndex = i1;
41428
41429			this.intervalChanged_( i1, t0, t1 );
41430
41431		} // validate_interval
41432
41433		return this.interpolate_( i1, t0, t, t1 );
41434
41435	}
41436
41437	/**
41438	 * Returns the interpolation settings.
41439	 *
41440	 * @return {Object} The interpolation settings.
41441	 */
41442	getSettings_() {
41443
41444		return this.settings || this.DefaultSettings_;
41445
41446	}
41447
41448	/**
41449	 * Copies a sample value to the result buffer.
41450	 *
41451	 * @param {number} index - An index into the sample value buffer.
41452	 * @return {TypedArray} The result buffer.
41453	 */
41454	copySampleValue_( index ) {
41455
41456		// copies a sample value to the result buffer
41457
41458		const result = this.resultBuffer,
41459			values = this.sampleValues,
41460			stride = this.valueSize,
41461			offset = index * stride;
41462
41463		for ( let i = 0; i !== stride; ++ i ) {
41464
41465			result[ i ] = values[ offset + i ];
41466
41467		}
41468
41469		return result;
41470
41471	}
41472
41473	/**
41474	 * Copies a sample value to the result buffer.
41475	 *
41476	 * @abstract
41477	 * @param {number} i1 - An index into the sample value buffer.
41478	 * @param {number} t0 - The previous interpolation factor.
41479	 * @param {number} t - The current interpolation factor.
41480	 * @param {number} t1 - The next interpolation factor.
41481	 * @return {TypedArray} The result buffer.
41482	 */
41483	interpolate_( /* i1, t0, t, t1 */ ) {
41484
41485		throw new Error( 'call to abstract method' );
41486		// implementations shall return this.resultBuffer
41487
41488	}
41489
41490	/**
41491	 * Optional method that is executed when the interval has changed.
41492	 *
41493	 * @param {number} i1 - An index into the sample value buffer.
41494	 * @param {number} t0 - The previous interpolation factor.
41495	 * @param {number} t - The current interpolation factor.
41496	 */
41497	intervalChanged_( /* i1, t0, t1 */ ) {
41498
41499		// empty
41500
41501	}
41502
41503}
41504
41505/**
41506 * Fast and simple cubic spline interpolant.
41507 *
41508 * It was derived from a Hermitian construction setting the first derivative
41509 * at each sample position to the linear slope between neighboring positions
41510 * over their parameter interval.
41511 *
41512 * @augments Interpolant
41513 */
41514class CubicInterpolant extends Interpolant {
41515
41516	/**
41517	 * Constructs a new cubic interpolant.
41518	 *
41519	 * @param {TypedArray} parameterPositions - The parameter positions hold the interpolation factors.
41520	 * @param {TypedArray} sampleValues - The sample values.
41521	 * @param {number} sampleSize - The sample size
41522	 * @param {TypedArray} [resultBuffer] - The result buffer.
41523	 */
41524	constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
41525
41526		super( parameterPositions, sampleValues, sampleSize, resultBuffer );
41527
41528		this._weightPrev = -0;
41529		this._offsetPrev = -0;
41530		this._weightNext = -0;
41531		this._offsetNext = -0;
41532
41533		this.DefaultSettings_ = {
41534
41535			endingStart: ZeroCurvatureEnding,
41536			endingEnd: ZeroCurvatureEnding
41537
41538		};
41539
41540	}
41541
41542	intervalChanged_( i1, t0, t1 ) {
41543
41544		const pp = this.parameterPositions;
41545		let iPrev = i1 - 2,
41546			iNext = i1 + 1,
41547
41548			tPrev = pp[ iPrev ],
41549			tNext = pp[ iNext ];
41550
41551		if ( tPrev === undefined ) {
41552
41553			switch ( this.getSettings_().endingStart ) {
41554
41555				case ZeroSlopeEnding:
41556
41557					// f'(t0) = 0
41558					iPrev = i1;
41559					tPrev = 2 * t0 - t1;
41560
41561					break;
41562
41563				case WrapAroundEnding:
41564
41565					// use the other end of the curve
41566					iPrev = pp.length - 2;
41567					tPrev = t0 + pp[ iPrev ] - pp[ iPrev + 1 ];
41568
41569					break;
41570
41571				default: // ZeroCurvatureEnding
41572
41573					// f''(t0) = 0 a.k.a. Natural Spline
41574					iPrev = i1;
41575					tPrev = t1;
41576
41577			}
41578
41579		}
41580
41581		if ( tNext === undefined ) {
41582
41583			switch ( this.getSettings_().endingEnd ) {
41584
41585				case ZeroSlopeEnding:
41586
41587					// f'(tN) = 0
41588					iNext = i1;
41589					tNext = 2 * t1 - t0;
41590
41591					break;
41592
41593				case WrapAroundEnding:
41594
41595					// use the other end of the curve
41596					iNext = 1;
41597					tNext = t1 + pp[ 1 ] - pp[ 0 ];
41598
41599					break;
41600
41601				default: // ZeroCurvatureEnding
41602
41603					// f''(tN) = 0, a.k.a. Natural Spline
41604					iNext = i1 - 1;
41605					tNext = t0;
41606
41607			}
41608
41609		}
41610
41611		const halfDt = ( t1 - t0 ) * 0.5,
41612			stride = this.valueSize;
41613
41614		this._weightPrev = halfDt / ( t0 - tPrev );
41615		this._weightNext = halfDt / ( tNext - t1 );
41616		this._offsetPrev = iPrev * stride;
41617		this._offsetNext = iNext * stride;
41618
41619	}
41620
41621	interpolate_( i1, t0, t, t1 ) {
41622
41623		const result = this.resultBuffer,
41624			values = this.sampleValues,
41625			stride = this.valueSize,
41626
41627			o1 = i1 * stride,		o0 = o1 - stride,
41628			oP = this._offsetPrev, 	oN = this._offsetNext,
41629			wP = this._weightPrev,	wN = this._weightNext,
41630
41631			p = ( t - t0 ) / ( t1 - t0 ),
41632			pp = p * p,
41633			ppp = pp * p;
41634
41635		// evaluate polynomials
41636
41637		const sP = - wP * ppp + 2 * wP * pp - wP * p;
41638		const s0 = ( 1 + wP ) * ppp + ( -1.5 - 2 * wP ) * pp + ( -0.5 + wP ) * p + 1;
41639		const s1 = ( -1 - wN ) * ppp + ( 1.5 + wN ) * pp + 0.5 * p;
41640		const sN = wN * ppp - wN * pp;
41641
41642		// combine data linearly
41643
41644		for ( let i = 0; i !== stride; ++ i ) {
41645
41646			result[ i ] =
41647					sP * values[ oP + i ] +
41648					s0 * values[ o0 + i ] +
41649					s1 * values[ o1 + i ] +
41650					sN * values[ oN + i ];
41651
41652		}
41653
41654		return result;
41655
41656	}
41657
41658}
41659
41660/**
41661 * A basic linear interpolant.
41662 *
41663 * @augments Interpolant
41664 */
41665class LinearInterpolant extends Interpolant {
41666
41667	/**
41668	 * Constructs a new linear interpolant.
41669	 *
41670	 * @param {TypedArray} parameterPositions - The parameter positions hold the interpolation factors.
41671	 * @param {TypedArray} sampleValues - The sample values.
41672	 * @param {number} sampleSize - The sample size
41673	 * @param {TypedArray} [resultBuffer] - The result buffer.
41674	 */
41675	constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
41676
41677		super( parameterPositions, sampleValues, sampleSize, resultBuffer );
41678
41679	}
41680
41681	interpolate_( i1, t0, t, t1 ) {
41682
41683		const result = this.resultBuffer,
41684			values = this.sampleValues,
41685			stride = this.valueSize,
41686
41687			offset1 = i1 * stride,
41688			offset0 = offset1 - stride,
41689
41690			weight1 = ( t - t0 ) / ( t1 - t0 ),
41691			weight0 = 1 - weight1;
41692
41693		for ( let i = 0; i !== stride; ++ i ) {
41694
41695			result[ i ] =
41696					values[ offset0 + i ] * weight0 +
41697					values[ offset1 + i ] * weight1;
41698
41699		}
41700
41701		return result;
41702
41703	}
41704
41705}
41706
41707/**
41708 * Interpolant that evaluates to the sample value at the position preceding
41709 * the parameter.
41710 *
41711 * @augments Interpolant
41712 */
41713class DiscreteInterpolant extends Interpolant {
41714
41715	/**
41716	 * Constructs a new discrete interpolant.
41717	 *
41718	 * @param {TypedArray} parameterPositions - The parameter positions hold the interpolation factors.
41719	 * @param {TypedArray} sampleValues - The sample values.
41720	 * @param {number} sampleSize - The sample size
41721	 * @param {TypedArray} [resultBuffer] - The result buffer.
41722	 */
41723	constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
41724
41725		super( parameterPositions, sampleValues, sampleSize, resultBuffer );
41726
41727	}
41728
41729	interpolate_( i1 /*, t0, t, t1 */ ) {
41730
41731		return this.copySampleValue_( i1 - 1 );
41732
41733	}
41734
41735}
41736
41737/**
41738 * A Bezier interpolant using cubic Bezier curves with 2D control points.
41739 *
41740 * This interpolant supports the COLLADA/Maya style of Bezier animation where
41741 * each keyframe has explicit in/out tangent control points specified as
41742 * 2D coordinates (time, value).
41743 *
41744 * The tangent data must be provided via the `settings` object:
41745 * - `settings.inTangents`: Float32Array with [time, value] pairs per keyframe per component
41746 * - `settings.outTangents`: Float32Array with [time, value] pairs per keyframe per component
41747 *
41748 * For a track with N keyframes and stride S:
41749 * - Each tangent array has N * S * 2 values
41750 * - Layout: [k0_c0_time, k0_c0_value, k0_c1_time, k0_c1_value, ..., k0_cS_time, k0_cS_value,
41751 *            k1_c0_time, k1_c0_value, ...]
41752 *
41753 * @augments Interpolant
41754 */
41755class BezierInterpolant extends Interpolant {
41756
41757	interpolate_( i1, t0, t, t1 ) {
41758
41759		const result = this.resultBuffer;
41760		const values = this.sampleValues;
41761		const stride = this.valueSize;
41762
41763		const offset1 = i1 * stride;
41764		const offset0 = offset1 - stride;
41765
41766		const settings = this.settings || this.DefaultSettings_;
41767		const inTangents = settings.inTangents;
41768		const outTangents = settings.outTangents;
41769
41770		// If no tangent data, fall back to linear interpolation
41771		if ( ! inTangents || ! outTangents ) {
41772
41773			const weight1 = ( t - t0 ) / ( t1 - t0 );
41774			const weight0 = 1 - weight1;
41775
41776			for ( let i = 0; i !== stride; ++ i ) {
41777
41778				result[ i ] = values[ offset0 + i ] * weight0 + values[ offset1 + i ] * weight1;
41779
41780			}
41781
41782			return result;
41783
41784		}
41785
41786		const tangentStride = stride * 2;
41787		const i0 = i1 - 1;
41788
41789		for ( let i = 0; i !== stride; ++ i ) {
41790
41791			const v0 = values[ offset0 + i ];
41792			const v1 = values[ offset1 + i ];
41793
41794			// outTangent of previous keyframe (C0)
41795			const outTangentOffset = i0 * tangentStride + i * 2;
41796			const c0x = outTangents[ outTangentOffset ];
41797			const c0y = outTangents[ outTangentOffset + 1 ];
41798
41799			// inTangent of current keyframe (C1)
41800			const inTangentOffset = i1 * tangentStride + i * 2;
41801			const c1x = inTangents[ inTangentOffset ];
41802			const c1y = inTangents[ inTangentOffset + 1 ];
41803
41804			// Solve for Bezier parameter s where Bx(s) = t using Newton-Raphson
41805			let s = ( t - t0 ) / ( t1 - t0 );
41806			let s2, s3, oneMinusS, oneMinusS2, oneMinusS3;
41807
41808			for ( let iter = 0; iter < 8; iter ++ ) {
41809
41810				s2 = s * s;
41811				s3 = s2 * s;
41812				oneMinusS = 1 - s;
41813				oneMinusS2 = oneMinusS * oneMinusS;
41814				oneMinusS3 = oneMinusS2 * oneMinusS;
41815
41816				// Bezier X(s) = (1-s)³·t0 + 3(1-s)²s·c0x + 3(1-s)s²·c1x + s³·t1
41817				const bx = oneMinusS3 * t0 + 3 * oneMinusS2 * s * c0x + 3 * oneMinusS * s2 * c1x + s3 * t1;
41818
41819				const error = bx - t;
41820				if ( Math.abs( error ) < 1e-10 ) break;
41821
41822				// Derivative dX/ds
41823				const dbx = 3 * oneMinusS2 * ( c0x - t0 ) + 6 * oneMinusS * s * ( c1x - c0x ) + 3 * s2 * ( t1 - c1x );
41824				if ( Math.abs( dbx ) < 1e-10 ) break;
41825
41826				s = s - error / dbx;
41827				s = Math.max( 0, Math.min( 1, s ) );
41828
41829			}
41830
41831			// Evaluate Bezier Y(s)
41832			result[ i ] = oneMinusS3 * v0 + 3 * oneMinusS2 * s * c0y + 3 * oneMinusS * s2 * c1y + s3 * v1;
41833
41834		}
41835
41836		return result;
41837
41838	}
41839
41840}
41841
41842/**
41843 * Represents a timed sequence of keyframes, which are composed of lists of
41844 * times and related values, and which are used to animate a specific property
41845 * of an object.
41846 */
41847class KeyframeTrack {
41848
41849	/**
41850	 * Constructs a new keyframe track.
41851	 *
41852	 * @param {string} name - The keyframe track's name.
41853	 * @param {Array<number>} times - A list of keyframe times.
41854	 * @param {Array<number|string|boolean>} values - A list of keyframe values.
41855	 * @param {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth|InterpolateBezier)} [interpolation] - The interpolation type.
41856	 */
41857	constructor( name, times, values, interpolation ) {
41858
41859		if ( name === undefined ) throw new Error( 'THREE.KeyframeTrack: track name is undefined' );
41860		if ( times === undefined || times.length === 0 ) throw new Error( 'THREE.KeyframeTrack: no keyframes in track named ' + name );
41861
41862		/**
41863		 * The track's name can refer to morph targets or bones or
41864		 * possibly other values within an animated object. See {@link PropertyBinding#parseTrackName}
41865		 * for the forms of strings that can be parsed for property binding.
41866		 *
41867		 * @type {string}
41868		 */
41869		this.name = name;
41870
41871		/**
41872		 * The keyframe times.
41873		 *
41874		 * @type {Float32Array}
41875		 */
41876		this.times = convertArray( times, this.TimeBufferType );
41877
41878		/**
41879		 * The keyframe values.
41880		 *
41881		 * @type {Float32Array}
41882		 */
41883		this.values = convertArray( values, this.ValueBufferType );
41884
41885		this.setInterpolation( interpolation || this.DefaultInterpolation );
41886
41887	}
41888
41889	/**
41890	 * Converts the keyframe track to JSON.
41891	 *
41892	 * @static
41893	 * @param {KeyframeTrack} track - The keyframe track to serialize.
41894	 * @return {Object} The serialized keyframe track as JSON.
41895	 */
41896	static toJSON( track ) {
41897
41898		const trackType = track.constructor;
41899
41900		let json;
41901
41902		// derived classes can define a static toJSON method
41903		if ( trackType.toJSON !== this.toJSON ) {
41904
41905			json = trackType.toJSON( track );
41906
41907		} else {
41908
41909			// by default, we assume the data can be serialized as-is
41910			json = {
41911
41912				'name': track.name,
41913				'times': convertArray( track.times, Array ),
41914				'values': convertArray( track.values, Array )
41915
41916			};
41917
41918			const interpolation = track.getInterpolation();
41919
41920			if ( interpolation !== track.DefaultInterpolation ) {
41921
41922				json.interpolation = interpolation;
41923
41924			}
41925
41926		}
41927
41928		json.type = track.ValueTypeName; // mandatory
41929
41930		return json;
41931
41932	}
41933
41934	/**
41935	 * Factory method for creating a new discrete interpolant.
41936	 *
41937	 * @static
41938	 * @param {TypedArray} [result] - The result buffer.
41939	 * @return {DiscreteInterpolant} The new interpolant.
41940	 */
41941	InterpolantFactoryMethodDiscrete( result ) {
41942
41943		return new DiscreteInterpolant( this.times, this.values, this.getValueSize(), result );
41944
41945	}
41946
41947	/**
41948	 * Factory method for creating a new linear interpolant.
41949	 *
41950	 * @static
41951	 * @param {TypedArray} [result] - The result buffer.
41952	 * @return {LinearInterpolant} The new interpolant.
41953	 */
41954	InterpolantFactoryMethodLinear( result ) {
41955
41956		return new LinearInterpolant( this.times, this.values, this.getValueSize(), result );
41957
41958	}
41959
41960	/**
41961	 * Factory method for creating a new smooth interpolant.
41962	 *
41963	 * @static
41964	 * @param {TypedArray} [result] - The result buffer.
41965	 * @return {CubicInterpolant} The new interpolant.
41966	 */
41967	InterpolantFactoryMethodSmooth( result ) {
41968
41969		return new CubicInterpolant( this.times, this.values, this.getValueSize(), result );
41970
41971	}
41972
41973	/**
41974	 * Factory method for creating a new Bezier interpolant.
41975	 *
41976	 * The Bezier interpolant requires tangent data to be set via the `settings` property
41977	 * on the track before creating the interpolant. The settings should contain:
41978	 * - `inTangents`: Float32Array with [time, value] pairs per keyframe per component
41979	 * - `outTangents`: Float32Array with [time, value] pairs per keyframe per component
41980	 *
41981	 * @static
41982	 * @param {TypedArray} [result] - The result buffer.
41983	 * @return {BezierInterpolant} The new interpolant.
41984	 */
41985	InterpolantFactoryMethodBezier( result ) {
41986
41987		const interpolant = new BezierInterpolant( this.times, this.values, this.getValueSize(), result );
41988
41989		// Pass tangent data from track settings to interpolant
41990		if ( this.settings ) {
41991
41992			interpolant.settings = this.settings;
41993
41994		}
41995
41996		return interpolant;
41997
41998	}
41999
42000	/**
42001	 * Defines the interpolation factor method for this keyframe track.
42002	 *
42003	 * @param {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth|InterpolateBezier)} interpolation - The interpolation type.
42004	 * @return {KeyframeTrack} A reference to this keyframe track.
42005	 */
42006	setInterpolation( interpolation ) {
42007
42008		let factoryMethod;
42009
42010		switch ( interpolation ) {
42011
42012			case InterpolateDiscrete:
42013
42014				factoryMethod = this.InterpolantFactoryMethodDiscrete;
42015
42016				break;
42017
42018			case InterpolateLinear:
42019
42020				factoryMethod = this.InterpolantFactoryMethodLinear;
42021
42022				break;
42023
42024			case InterpolateSmooth:
42025
42026				factoryMethod = this.InterpolantFactoryMethodSmooth;
42027
42028				break;
42029
42030			case InterpolateBezier:
42031
42032				factoryMethod = this.InterpolantFactoryMethodBezier;
42033
42034				break;
42035
42036		}
42037
42038		if ( factoryMethod === undefined ) {
42039
42040			const message = 'unsupported interpolation for ' +
42041				this.ValueTypeName + ' keyframe track named ' + this.name;
42042
42043			if ( this.createInterpolant === undefined ) {
42044
42045				// fall back to default, unless the default itself is messed up
42046				if ( interpolation !== this.DefaultInterpolation ) {
42047
42048					this.setInterpolation( this.DefaultInterpolation );
42049
42050				} else {
42051
42052					throw new Error( message ); // fatal, in this case
42053
42054				}
42055
42056			}
42057
42058			warn( 'KeyframeTrack:', message );
42059			return this;
42060
42061		}
42062
42063		this.createInterpolant = factoryMethod;
42064
42065		return this;
42066
42067	}
42068
42069	/**
42070	 * Returns the current interpolation type.
42071	 *
42072	 * @return {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth|InterpolateBezier)} The interpolation type.
42073	 */
42074	getInterpolation() {
42075
42076		switch ( this.createInterpolant ) {
42077
42078			case this.InterpolantFactoryMethodDiscrete:
42079
42080				return InterpolateDiscrete;
42081
42082			case this.InterpolantFactoryMethodLinear:
42083
42084				return InterpolateLinear;
42085
42086			case this.InterpolantFactoryMethodSmooth:
42087
42088				return InterpolateSmooth;
42089
42090			case this.InterpolantFactoryMethodBezier:
42091
42092				return InterpolateBezier;
42093
42094		}
42095
42096	}
42097
42098	/**
42099	 * Returns the value size.
42100	 *
42101	 * @return {number} The value size.
42102	 */
42103	getValueSize() {
42104
42105		return this.values.length / this.times.length;
42106
42107	}
42108
42109	/**
42110	 * Moves all keyframes either forward or backward in time.
42111	 *
42112	 * @param {number} timeOffset - The offset to move the time values.
42113	 * @return {KeyframeTrack} A reference to this keyframe track.
42114	 */
42115	shift( timeOffset ) {
42116
42117		if ( timeOffset !== 0.0 ) {
42118
42119			const times = this.times;
42120
42121			for ( let i = 0, n = times.length; i !== n; ++ i ) {
42122
42123				times[ i ] += timeOffset;
42124
42125			}
42126
42127		}
42128
42129		return this;
42130
42131	}
42132
42133	/**
42134	 * Scale all keyframe times by a factor (useful for frame - seconds conversions).
42135	 *
42136	 * @param {number} timeScale - The time scale.
42137	 * @return {KeyframeTrack} A reference to this keyframe track.
42138	 */
42139	scale( timeScale ) {
42140
42141		if ( timeScale !== 1.0 ) {
42142
42143			const times = this.times;
42144
42145			for ( let i = 0, n = times.length; i !== n; ++ i ) {
42146
42147				times[ i ] *= timeScale;
42148
42149			}
42150
42151		}
42152
42153		return this;
42154
42155	}
42156
42157	/**
42158	 * Removes keyframes before and after animation without changing any values within the defined time range.
42159	 *
42160	 * Note: The method does not shift around keys to the start of the track time, because for interpolated
42161	 * keys this will change their values
42162	 *
42163	 * @param {number} startTime - The start time.
42164	 * @param {number} endTime - The end time.
42165	 * @return {KeyframeTrack} A reference to this keyframe track.
42166	 */
42167	trim( startTime, endTime ) {
42168
42169		const times = this.times,
42170			nKeys = times.length;
42171
42172		let from = 0,
42173			to = nKeys - 1;
42174
42175		while ( from !== nKeys && times[ from ] < startTime ) {
42176
42177			++ from;
42178
42179		}
42180
42181		while ( to !== -1 && times[ to ] > endTime ) {
42182
42183			-- to;
42184
42185		}
42186
42187		++ to; // inclusive -> exclusive bound
42188
42189		if ( from !== 0 || to !== nKeys ) {
42190
42191			// empty tracks are forbidden, so keep at least one keyframe
42192			if ( from >= to ) {
42193
42194				to = Math.max( to, 1 );
42195				from = to - 1;
42196
42197			}
42198
42199			const stride = this.getValueSize();
42200			this.times = times.slice( from, to );
42201			this.values = this.values.slice( from * stride, to * stride );
42202
42203		}
42204
42205		return this;
42206
42207	}
42208
42209	/**
42210	 * Performs minimal validation on the keyframe track. Returns `true` if the values
42211	 * are valid.
42212	 *
42213	 * @return {boolean} Whether the keyframes are valid or not.
42214	 */
42215	validate() {
42216
42217		let valid = true;
42218
42219		const valueSize = this.getValueSize();
42220		if ( valueSize - Math.floor( valueSize ) !== 0 ) {
42221
42222			error( 'KeyframeTrack: Invalid value size in track.', this );
42223			valid = false;
42224
42225		}
42226
42227		const times = this.times,
42228			values = this.values,
42229
42230			nKeys = times.length;
42231
42232		if ( nKeys === 0 ) {
42233
42234			error( 'KeyframeTrack: Track is empty.', this );
42235			valid = false;
42236
42237		}
42238
42239		let prevTime = null;
42240
42241		for ( let i = 0; i !== nKeys; i ++ ) {
42242
42243			const currTime = times[ i ];
42244
42245			if ( typeof currTime === 'number' && isNaN( currTime ) ) {
42246
42247				error( 'KeyframeTrack: Time is not a valid number.', this, i, currTime );
42248				valid = false;
42249				break;
42250
42251			}
42252
42253			if ( prevTime !== null && prevTime > currTime ) {
42254
42255				error( 'KeyframeTrack: Out of order keys.', this, i, currTime, prevTime );
42256				valid = false;
42257				break;
42258
42259			}
42260
42261			prevTime = currTime;
42262
42263		}
42264
42265		if ( values !== undefined ) {
42266
42267			if ( isTypedArray( values ) ) {
42268
42269				for ( let i = 0, n = values.length; i !== n; ++ i ) {
42270
42271					const value = values[ i ];
42272
42273					if ( isNaN( value ) ) {
42274
42275						error( 'KeyframeTrack: Value is not a valid number.', this, i, value );
42276						valid = false;
42277						break;
42278
42279					}
42280
42281				}
42282
42283			}
42284
42285		}
42286
42287		return valid;
42288
42289	}
42290
42291	/**
42292	 * Optimizes this keyframe track by removing equivalent sequential keys (which are
42293	 * common in morph target sequences).
42294	 *
42295	 * @return {KeyframeTrack} A reference to this keyframe track.
42296	 */
42297	optimize() {
42298
42299		// (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0)
42300
42301		// times or values may be shared with other tracks, so overwriting is unsafe
42302		const times = this.times.slice(),
42303			values = this.values.slice(),
42304			stride = this.getValueSize(),
42305
42306			smoothInterpolation = this.getInterpolation() === InterpolateSmooth,
42307
42308			lastIndex = times.length - 1;
42309
42310		let writeIndex = 1;
42311
42312		for ( let i = 1; i < lastIndex; ++ i ) {
42313
42314			let keep = false;
42315
42316			const time = times[ i ];
42317			const timeNext = times[ i + 1 ];
42318
42319			// remove adjacent keyframes scheduled at the same time
42320
42321			if ( time !== timeNext && ( i !== 1 || time !== times[ 0 ] ) ) {
42322
42323				if ( ! smoothInterpolation ) {
42324
42325					// remove unnecessary keyframes same as their neighbors
42326
42327					const offset = i * stride,
42328						offsetP = offset - stride,
42329						offsetN = offset + stride;
42330
42331					for ( let j = 0; j !== stride; ++ j ) {
42332
42333						const value = values[ offset + j ];
42334
42335						if ( value !== values[ offsetP + j ] ||
42336							value !== values[ offsetN + j ] ) {
42337
42338							keep = true;
42339							break;
42340
42341						}
42342
42343					}
42344
42345				} else {
42346
42347					keep = true;
42348
42349				}
42350
42351			}
42352
42353			// in-place compaction
42354
42355			if ( keep ) {
42356
42357				if ( i !== writeIndex ) {
42358
42359					times[ writeIndex ] = times[ i ];
42360
42361					const readOffset = i * stride,
42362						writeOffset = writeIndex * stride;
42363
42364					for ( let j = 0; j !== stride; ++ j ) {
42365
42366						values[ writeOffset + j ] = values[ readOffset + j ];
42367
42368					}
42369
42370				}
42371
42372				++ writeIndex;
42373
42374			}
42375
42376		}
42377
42378		// flush last keyframe (compaction looks ahead)
42379
42380		if ( lastIndex > 0 ) {
42381
42382			times[ writeIndex ] = times[ lastIndex ];
42383
42384			for ( let readOffset = lastIndex * stride, writeOffset = writeIndex * stride, j = 0; j !== stride; ++ j ) {
42385
42386				values[ writeOffset + j ] = values[ readOffset + j ];
42387
42388			}
42389
42390			++ writeIndex;
42391
42392		}
42393
42394		if ( writeIndex !== times.length ) {
42395
42396			this.times = times.slice( 0, writeIndex );
42397			this.values = values.slice( 0, writeIndex * stride );
42398
42399		} else {
42400
42401			this.times = times;
42402			this.values = values;
42403
42404		}
42405
42406		return this;
42407
42408	}
42409
42410	/**
42411	 * Returns a new keyframe track with copied values from this instance.
42412	 *
42413	 * @return {KeyframeTrack} A clone of this instance.
42414	 */
42415	clone() {
42416
42417		const times = this.times.slice();
42418		const values = this.values.slice();
42419
42420		const TypedKeyframeTrack = this.constructor;
42421		const track = new TypedKeyframeTrack( this.name, times, values );
42422
42423		// Interpolant argument to constructor is not saved, so copy the factory method directly.
42424		track.createInterpolant = this.createInterpolant;
42425
42426		return track;
42427
42428	}
42429
42430}
42431
42432/**
42433 * The value type name.
42434 *
42435 * @type {string}
42436 * @default ''
42437 */
42438KeyframeTrack.prototype.ValueTypeName = '';
42439
42440/**
42441 * The time buffer type of this keyframe track.
42442 *
42443 * @type {TypedArray|Array}
42444 * @default Float32Array.constructor
42445 */
42446KeyframeTrack.prototype.TimeBufferType = Float32Array;
42447
42448/**
42449 * The value buffer type of this keyframe track.
42450 *
42451 * @type {TypedArray|Array}
42452 * @default Float32Array.constructor
42453 */
42454KeyframeTrack.prototype.ValueBufferType = Float32Array;
42455
42456/**
42457 * The default interpolation type of this keyframe track.
42458 *
42459 * @type {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth|InterpolateBezier)}
42460 * @default InterpolateLinear
42461 */
42462KeyframeTrack.prototype.DefaultInterpolation = InterpolateLinear;
42463
42464/**
42465 * A track for boolean keyframe values.
42466 *
42467 * @augments KeyframeTrack
42468 */
42469class BooleanKeyframeTrack extends KeyframeTrack {
42470
42471	/**
42472	 * Constructs a new boolean keyframe track.
42473	 *
42474	 * This keyframe track type has no `interpolation` parameter because the
42475	 * interpolation is always discrete.
42476	 *
42477	 * @param {string} name - The keyframe track's name.
42478	 * @param {Array<number>} times - A list of keyframe times.
42479	 * @param {Array<boolean>} values - A list of keyframe values.
42480	 */
42481	constructor( name, times, values ) {
42482
42483		super( name, times, values );
42484
42485	}
42486
42487}
42488
42489/**
42490 * The value type name.
42491 *
42492 * @type {string}
42493 * @default 'bool'
42494 */
42495BooleanKeyframeTrack.prototype.ValueTypeName = 'bool';
42496
42497/**
42498 * The value buffer type of this keyframe track.
42499 *
42500 * @type {TypedArray|Array}
42501 * @default Array.constructor
42502 */
42503BooleanKeyframeTrack.prototype.ValueBufferType = Array;
42504
42505/**
42506 * The default interpolation type of this keyframe track.
42507 *
42508 * @type {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth)}
42509 * @default InterpolateDiscrete
42510 */
42511BooleanKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete;
42512BooleanKeyframeTrack.prototype.InterpolantFactoryMethodLinear = undefined;
42513BooleanKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined;
42514
42515/**
42516 * A track for color keyframe values.
42517 *
42518 * @augments KeyframeTrack
42519 */
42520class ColorKeyframeTrack extends KeyframeTrack {
42521
42522	/**
42523	 * Constructs a new color keyframe track.
42524	 *
42525	 * @param {string} name - The keyframe track's name.
42526	 * @param {Array<number>} times - A list of keyframe times.
42527	 * @param {Array<number>} values - A list of keyframe values.
42528	 * @param {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth)} [interpolation] - The interpolation type.
42529	 */
42530	constructor( name, times, values, interpolation ) {
42531
42532		super( name, times, values, interpolation );
42533
42534	}
42535
42536}
42537
42538/**
42539 * The value type name.
42540 *
42541 * @type {string}
42542 * @default 'color'
42543 */
42544ColorKeyframeTrack.prototype.ValueTypeName = 'color';
42545
42546/**
42547 * A track for numeric keyframe values.
42548 *
42549 * @augments KeyframeTrack
42550 */
42551class NumberKeyframeTrack extends KeyframeTrack {
42552
42553	/**
42554	 * Constructs a new number keyframe track.
42555	 *
42556	 * @param {string} name - The keyframe track's name.
42557	 * @param {Array<number>} times - A list of keyframe times.
42558	 * @param {Array<number>} values - A list of keyframe values.
42559	 * @param {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth)} [interpolation] - The interpolation type.
42560	 */
42561	constructor( name, times, values, interpolation ) {
42562
42563		super( name, times, values, interpolation );
42564
42565	}
42566
42567}
42568
42569/**
42570 * The value type name.
42571 *
42572 * @type {string}
42573 * @default 'number'
42574 */
42575NumberKeyframeTrack.prototype.ValueTypeName = 'number';
42576
42577/**
42578 * Spherical linear unit quaternion interpolant.
42579 *
42580 * @augments Interpolant
42581 */
42582class QuaternionLinearInterpolant extends Interpolant {
42583
42584	/**
42585	 * Constructs a new SLERP interpolant.
42586	 *
42587	 * @param {TypedArray} parameterPositions - The parameter positions hold the interpolation factors.
42588	 * @param {TypedArray} sampleValues - The sample values.
42589	 * @param {number} sampleSize - The sample size
42590	 * @param {TypedArray} [resultBuffer] - The result buffer.
42591	 */
42592	constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
42593
42594		super( parameterPositions, sampleValues, sampleSize, resultBuffer );
42595
42596	}
42597
42598	interpolate_( i1, t0, t, t1 ) {
42599
42600		const result = this.resultBuffer,
42601			values = this.sampleValues,
42602			stride = this.valueSize,
42603
42604			alpha = ( t - t0 ) / ( t1 - t0 );
42605
42606		let offset = i1 * stride;
42607
42608		for ( let end = offset + stride; offset !== end; offset += 4 ) {
42609
42610			Quaternion.slerpFlat( result, 0, values, offset - stride, values, offset, alpha );
42611
42612		}
42613
42614		return result;
42615
42616	}
42617
42618}
42619
42620/**
42621 * A track for Quaternion keyframe values.
42622 *
42623 * @augments KeyframeTrack
42624 */
42625class QuaternionKeyframeTrack extends KeyframeTrack {
42626
42627	/**
42628	 * Constructs a new Quaternion keyframe track.
42629	 *
42630	 * @param {string} name - The keyframe track's name.
42631	 * @param {Array<number>} times - A list of keyframe times.
42632	 * @param {Array<number>} values - A list of keyframe values.
42633	 * @param {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth)} [interpolation] - The interpolation type.
42634	 */
42635	constructor( name, times, values, interpolation ) {
42636
42637		super( name, times, values, interpolation );
42638
42639	}
42640
42641	/**
42642	 * Overwritten so the method returns Quaternion based interpolant.
42643	 *
42644	 * @static
42645	 * @param {TypedArray} [result] - The result buffer.
42646	 * @return {QuaternionLinearInterpolant} The new interpolant.
42647	 */
42648	InterpolantFactoryMethodLinear( result ) {
42649
42650		return new QuaternionLinearInterpolant( this.times, this.values, this.getValueSize(), result );
42651
42652	}
42653
42654}
42655
42656/**
42657 * The value type name.
42658 *
42659 * @type {string}
42660 * @default 'quaternion'
42661 */
42662QuaternionKeyframeTrack.prototype.ValueTypeName = 'quaternion';
42663// ValueBufferType is inherited
42664// DefaultInterpolation is inherited;
42665QuaternionKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined;
42666
42667/**
42668 * A track for string keyframe values.
42669 *
42670 * @augments KeyframeTrack
42671 */
42672class StringKeyframeTrack extends KeyframeTrack {
42673
42674	/**
42675	 * Constructs a new string keyframe track.
42676	 *
42677	 * This keyframe track type has no `interpolation` parameter because the
42678	 * interpolation is always discrete.
42679	 *
42680	 * @param {string} name - The keyframe track's name.
42681	 * @param {Array<number>} times - A list of keyframe times.
42682	 * @param {Array<string>} values - A list of keyframe values.
42683	 */
42684	constructor( name, times, values ) {
42685
42686		super( name, times, values );
42687
42688	}
42689
42690}
42691
42692/**
42693 * The value type name.
42694 *
42695 * @type {string}
42696 * @default 'string'
42697 */
42698StringKeyframeTrack.prototype.ValueTypeName = 'string';
42699
42700/**
42701 * The value buffer type of this keyframe track.
42702 *
42703 * @type {TypedArray|Array}
42704 * @default Array.constructor
42705 */
42706StringKeyframeTrack.prototype.ValueBufferType = Array;
42707
42708/**
42709 * The default interpolation type of this keyframe track.
42710 *
42711 * @type {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth)}
42712 * @default InterpolateDiscrete
42713 */
42714StringKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete;
42715StringKeyframeTrack.prototype.InterpolantFactoryMethodLinear = undefined;
42716StringKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined;
42717
42718/**
42719 * A track for vector keyframe values.
42720 *
42721 * @augments KeyframeTrack
42722 */
42723class VectorKeyframeTrack extends KeyframeTrack {
42724
42725	/**
42726	 * Constructs a new vector keyframe track.
42727	 *
42728	 * @param {string} name - The keyframe track's name.
42729	 * @param {Array<number>} times - A list of keyframe times.
42730	 * @param {Array<number>} values - A list of keyframe values.
42731	 * @param {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth)} [interpolation] - The interpolation type.
42732	 */
42733	constructor( name, times, values, interpolation ) {
42734
42735		super( name, times, values, interpolation );
42736
42737	}
42738
42739}
42740
42741/**
42742 * The value type name.
42743 *
42744 * @type {string}
42745 * @default 'vector'
42746 */
42747VectorKeyframeTrack.prototype.ValueTypeName = 'vector';
42748
42749/**
42750 * A reusable set of keyframe tracks which represent an animation.
42751 */
42752class AnimationClip {
42753
42754	/**
42755	 * Constructs a new animation clip.
42756	 *
42757	 * Note: Instead of instantiating an AnimationClip directly with the constructor, you can
42758	 * use the static interface of this class for creating clips. In most cases though, animation clips
vendor: 4,492 bytes, lines 42759-42940
42759	 * will automatically be created by loaders when importing animated 3D assets.
42760	 *
42761	 * @param {string} [name=''] - The clip's name.
42762	 * @param {number} [duration=-1] - The clip's duration in seconds. If a negative value is passed,
42763	 * the duration will be calculated from the passed keyframes.
42764	 * @param {Array<KeyframeTrack>} tracks - An array of keyframe tracks.
42765	 * @param {(NormalAnimationBlendMode|AdditiveAnimationBlendMode)} [blendMode=NormalAnimationBlendMode] - Defines how the animation
42766	 * is blended/combined when two or more animations are simultaneously played.
42767	 */
42768	constructor( name = '', duration = -1, tracks = [], blendMode = NormalAnimationBlendMode ) {
42769
42770		/**
42771		 * The clip's name.
42772		 *
42773		 * @type {string}
42774		 */
42775		this.name = name;
42776
42777		/**
42778		 *  An array of keyframe tracks.
42779		 *
42780		 * @type {Array<KeyframeTrack>}
42781		 */
42782		this.tracks = tracks;
42783
42784		/**
42785		 * The clip's duration in seconds.
42786		 *
42787		 * @type {number}
42788		 */
42789		this.duration = duration;
42790
42791		/**
42792		 * Defines how the animation is blended/combined when two or more animations
42793		 * are simultaneously played.
42794		 *
42795		 * @type {(NormalAnimationBlendMode|AdditiveAnimationBlendMode)}
42796		 */
42797		this.blendMode = blendMode;
42798
42799		/**
42800		 * The UUID of the animation clip.
42801		 *
42802		 * @type {string}
42803		 * @readonly
42804		 */
42805		this.uuid = generateUUID();
42806
42807		/**
42808		 * An object that can be used to store custom data about the animation clip.
42809		 * It should not hold references to functions as these will not be cloned.
42810		 *
42811		 * @type {Object}
42812		 */
42813		this.userData = {};
42814
42815		// this means it should figure out its duration by scanning the tracks
42816		if ( this.duration < 0 ) {
42817
42818			this.resetDuration();
42819
42820		}
42821
42822	}
42823
42824	/**
42825	 * Factory method for creating an animation clip from the given JSON.
42826	 *
42827	 * @static
42828	 * @param {Object} json - The serialized animation clip.
42829	 * @return {AnimationClip} The new animation clip.
42830	 */
42831	static parse( json ) {
42832
42833		const tracks = [],
42834			jsonTracks = json.tracks,
42835			frameTime = 1.0 / ( json.fps || 1.0 );
42836
42837		for ( let i = 0, n = jsonTracks.length; i !== n; ++ i ) {
42838
42839			tracks.push( parseKeyframeTrack( jsonTracks[ i ] ).scale( frameTime ) );
42840
42841		}
42842
42843		const clip = new this( json.name, json.duration, tracks, json.blendMode );
42844		clip.uuid = json.uuid;
42845
42846		clip.userData = JSON.parse( json.userData || '{}' );
42847
42848		return clip;
42849
42850	}
42851
42852	/**
42853	 * Serializes the given animation clip into JSON.
42854	 *
42855	 * @static
42856	 * @param {AnimationClip} clip - The animation clip to serialize.
42857	 * @return {Object} The JSON object.
42858	 */
42859	static toJSON( clip ) {
42860
42861		const tracks = [],
42862			clipTracks = clip.tracks;
42863
42864		const json = {
42865
42866			'name': clip.name,
42867			'duration': clip.duration,
42868			'tracks': tracks,
42869			'uuid': clip.uuid,
42870			'blendMode': clip.blendMode,
42871			'userData': JSON.stringify( clip.userData ),
42872
42873		};
42874
42875		for ( let i = 0, n = clipTracks.length; i !== n; ++ i ) {
42876
42877			tracks.push( KeyframeTrack.toJSON( clipTracks[ i ] ) );
42878
42879		}
42880
42881		return json;
42882
42883	}
42884
42885	/**
42886	 * Returns a new animation clip from the passed morph targets array of a
42887	 * geometry, taking a name and the number of frames per second.
42888	 *
42889	 * Note: The fps parameter is required, but the animation speed can be
42890	 * overridden via {@link AnimationAction#setDuration}.
42891	 *
42892	 * @static
42893	 * @param {string} name - The name of the animation clip.
42894	 * @param {Array<Object>} morphTargetSequence - A sequence of morph targets.
42895	 * @param {number} fps - The Frames-Per-Second value.
42896	 * @param {boolean} noLoop - Whether the clip should be no loop or not.
42897	 * @return {AnimationClip} The new animation clip.
42898	 */
42899	static CreateFromMorphTargetSequence( name, morphTargetSequence, fps, noLoop ) {
42900
42901		const numMorphTargets = morphTargetSequence.length;
42902		const tracks = [];
42903
42904		for ( let i = 0; i < numMorphTargets; i ++ ) {
42905
42906			let times = [];
42907			let values = [];
42908
42909			times.push(
42910				( i + numMorphTargets - 1 ) % numMorphTargets,
42911				i,
42912				( i + 1 ) % numMorphTargets );
42913
42914			values.push( 0, 1, 0 );
42915
42916			const order = getKeyframeOrder( times );
42917			times = sortedArray( times, 1, order );
42918			values = sortedArray( values, 1, order );
42919
42920			// if there is a key at the first frame, duplicate it as the
42921			// last frame as well for perfect loop.
42922			if ( ! noLoop && times[ 0 ] === 0 ) {
42923
42924				times.push( numMorphTargets );
42925				values.push( values[ 0 ] );
42926
42927			}
42928
42929			tracks.push(
42930				new NumberKeyframeTrack(
42931					'.morphTargetInfluences[' + morphTargetSequence[ i ].name + ']',
42932					times, values
42933				).scale( 1.0 / fps ) );
42934
42935		}
42936
42937		return new this( name, -1, tracks );
42938
42939	}
42940
vendor: 15,646 bytes, lines 42941-43672
42941	/**
42942	 * Searches for an animation clip by name, taking as its first parameter
42943	 * either an array of clips, or a mesh or geometry that contains an
42944	 * array named "animations" property.
42945	 *
42946	 * @static
42947	 * @param {(Array<AnimationClip>|Object3D)} objectOrClipArray - The array or object to search through.
42948	 * @param {string} name - The name to search for.
42949	 * @return {?AnimationClip} The found animation clip. Returns `null` if no clip has been found.
42950	 */
42951	static findByName( objectOrClipArray, name ) {
42952
42953		let clipArray = objectOrClipArray;
42954
42955		if ( ! Array.isArray( objectOrClipArray ) ) {
42956
42957			const o = objectOrClipArray;
42958			clipArray = o.geometry && o.geometry.animations || o.animations;
42959
42960		}
42961
42962		for ( let i = 0; i < clipArray.length; i ++ ) {
42963
42964			if ( clipArray[ i ].name === name ) {
42965
42966				return clipArray[ i ];
42967
42968			}
42969
42970		}
42971
42972		return null;
42973
42974	}
42975
42976	/**
42977	 * Returns an array of new AnimationClips created from the morph target
42978	 * sequences of a geometry, trying to sort morph target names into
42979	 * animation-group-based patterns like "Walk_001, Walk_002, Run_001, Run_002...".
42980	 *
42981	 * See {@link MD2Loader#parse} as an example for how the method should be used.
42982	 *
42983	 * @static
42984	 * @param {Array<Object>} morphTargets - A sequence of morph targets.
42985	 * @param {number} fps - The Frames-Per-Second value.
42986	 * @param {boolean} noLoop - Whether the clip should be no loop or not.
42987	 * @return {Array<AnimationClip>} An array of new animation clips.
42988	 */
42989	static CreateClipsFromMorphTargetSequences( morphTargets, fps, noLoop ) {
42990
42991		const animationToMorphTargets = {};
42992
42993		// tested with https://regex101.com/ on trick sequences
42994		// such flamingo_flyA_003, flamingo_run1_003, crdeath0059
42995		const pattern = /^([\w-]*?)([\d]+)$/;
42996
42997		// sort morph target names into animation groups based
42998		// patterns like Walk_001, Walk_002, Run_001, Run_002
42999		for ( let i = 0, il = morphTargets.length; i < il; i ++ ) {
43000
43001			const morphTarget = morphTargets[ i ];
43002			const parts = morphTarget.name.match( pattern );
43003
43004			if ( parts && parts.length > 1 ) {
43005
43006				const name = parts[ 1 ];
43007
43008				let animationMorphTargets = animationToMorphTargets[ name ];
43009
43010				if ( ! animationMorphTargets ) {
43011
43012					animationToMorphTargets[ name ] = animationMorphTargets = [];
43013
43014				}
43015
43016				animationMorphTargets.push( morphTarget );
43017
43018			}
43019
43020		}
43021
43022		const clips = [];
43023
43024		for ( const name in animationToMorphTargets ) {
43025
43026			clips.push( this.CreateFromMorphTargetSequence( name, animationToMorphTargets[ name ], fps, noLoop ) );
43027
43028		}
43029
43030		return clips;
43031
43032	}
43033
43034	/**
43035	 * Parses the `animation.hierarchy` format and returns a new animation clip.
43036	 *
43037	 * @static
43038	 * @deprecated since r175.
43039	 * @param {Object} animation - A serialized animation clip as JSON.
43040	 * @param {Array<Bone>} bones - An array of bones.
43041	 * @return {?AnimationClip} The new animation clip.
43042	 */
43043	static parseAnimation( animation, bones ) {
43044
43045		warn( 'AnimationClip: parseAnimation() is deprecated and will be removed with r185' );
43046
43047		if ( ! animation ) {
43048
43049			error( 'AnimationClip: No animation in JSONLoader data.' );
43050			return null;
43051
43052		}
43053
43054		const addNonemptyTrack = function ( trackType, trackName, animationKeys, propertyName, destTracks ) {
43055
43056			// only return track if there are actually keys.
43057			if ( animationKeys.length !== 0 ) {
43058
43059				const times = [];
43060				const values = [];
43061
43062				flattenJSON( animationKeys, times, values, propertyName );
43063
43064				// empty keys are filtered out, so check again
43065				if ( times.length !== 0 ) {
43066
43067					destTracks.push( new trackType( trackName, times, values ) );
43068
43069				}
43070
43071			}
43072
43073		};
43074
43075		const tracks = [];
43076
43077		const clipName = animation.name || 'default';
43078		const fps = animation.fps || 30;
43079		const blendMode = animation.blendMode;
43080
43081		// automatic length determination in AnimationClip.
43082		let duration = animation.length || -1;
43083
43084		const hierarchyTracks = animation.hierarchy || [];
43085
43086		for ( let h = 0; h < hierarchyTracks.length; h ++ ) {
43087
43088			const animationKeys = hierarchyTracks[ h ].keys;
43089
43090			// skip empty tracks
43091			if ( ! animationKeys || animationKeys.length === 0 ) continue;
43092
43093			// process morph targets
43094			if ( animationKeys[ 0 ].morphTargets ) {
43095
43096				// figure out all morph targets used in this track
43097				const morphTargetNames = {};
43098
43099				let k;
43100
43101				for ( k = 0; k < animationKeys.length; k ++ ) {
43102
43103					if ( animationKeys[ k ].morphTargets ) {
43104
43105						for ( let m = 0; m < animationKeys[ k ].morphTargets.length; m ++ ) {
43106
43107							morphTargetNames[ animationKeys[ k ].morphTargets[ m ] ] = -1;
43108
43109						}
43110
43111					}
43112
43113				}
43114
43115				// create a track for each morph target with all zero
43116				// morphTargetInfluences except for the keys in which
43117				// the morphTarget is named.
43118				for ( const morphTargetName in morphTargetNames ) {
43119
43120					const times = [];
43121					const values = [];
43122
43123					for ( let m = 0; m !== animationKeys[ k ].morphTargets.length; ++ m ) {
43124
43125						const animationKey = animationKeys[ k ];
43126
43127						times.push( animationKey.time );
43128						values.push( ( animationKey.morphTarget === morphTargetName ) ? 1 : 0 );
43129
43130					}
43131
43132					tracks.push( new NumberKeyframeTrack( '.morphTargetInfluence[' + morphTargetName + ']', times, values ) );
43133
43134				}
43135
43136				duration = morphTargetNames.length * fps;
43137
43138			} else {
43139
43140				// ...assume skeletal animation
43141
43142				const boneName = '.bones[' + bones[ h ].name + ']';
43143
43144				addNonemptyTrack(
43145					VectorKeyframeTrack, boneName + '.position',
43146					animationKeys, 'pos', tracks );
43147
43148				addNonemptyTrack(
43149					QuaternionKeyframeTrack, boneName + '.quaternion',
43150					animationKeys, 'rot', tracks );
43151
43152				addNonemptyTrack(
43153					VectorKeyframeTrack, boneName + '.scale',
43154					animationKeys, 'scl', tracks );
43155
43156			}
43157
43158		}
43159
43160		if ( tracks.length === 0 ) {
43161
43162			return null;
43163
43164		}
43165
43166		const clip = new this( clipName, duration, tracks, blendMode );
43167
43168		return clip;
43169
43170	}
43171
43172	/**
43173	 * Sets the duration of this clip to the duration of its longest keyframe track.
43174	 *
43175	 * @return {AnimationClip} A reference to this animation clip.
43176	 */
43177	resetDuration() {
43178
43179		const tracks = this.tracks;
43180		let duration = 0;
43181
43182		for ( let i = 0, n = tracks.length; i !== n; ++ i ) {
43183
43184			const track = this.tracks[ i ];
43185
43186			duration = Math.max( duration, track.times[ track.times.length - 1 ] );
43187
43188		}
43189
43190		this.duration = duration;
43191
43192		return this;
43193
43194	}
43195
43196	/**
43197	 * Trims all tracks to the clip's duration.
43198	 *
43199	 * @return {AnimationClip} A reference to this animation clip.
43200	 */
43201	trim() {
43202
43203		for ( let i = 0; i < this.tracks.length; i ++ ) {
43204
43205			this.tracks[ i ].trim( 0, this.duration );
43206
43207		}
43208
43209		return this;
43210
43211	}
43212
43213	/**
43214	 * Performs minimal validation on each track in the clip. Returns `true` if all
43215	 * tracks are valid.
43216	 *
43217	 * @return {boolean} Whether the clip's keyframes are valid or not.
43218	 */
43219	validate() {
43220
43221		let valid = true;
43222
43223		for ( let i = 0; i < this.tracks.length; i ++ ) {
43224
43225			valid = valid && this.tracks[ i ].validate();
43226
43227		}
43228
43229		return valid;
43230
43231	}
43232
43233	/**
43234	 * Optimizes each track by removing equivalent sequential keys (which are
43235	 * common in morph target sequences).
43236	 *
43237	 * @return {AnimationClip} A reference to this animation clip.
43238	 */
43239	optimize() {
43240
43241		for ( let i = 0; i < this.tracks.length; i ++ ) {
43242
43243			this.tracks[ i ].optimize();
43244
43245		}
43246
43247		return this;
43248
43249	}
43250
43251	/**
43252	 * Returns a new animation clip with copied values from this instance.
43253	 *
43254	 * @return {AnimationClip} A clone of this instance.
43255	 */
43256	clone() {
43257
43258		const tracks = [];
43259
43260		for ( let i = 0; i < this.tracks.length; i ++ ) {
43261
43262			tracks.push( this.tracks[ i ].clone() );
43263
43264		}
43265
43266		const clip = new this.constructor( this.name, this.duration, tracks, this.blendMode );
43267
43268		clip.userData = JSON.parse( JSON.stringify( this.userData ) );
43269
43270		return clip;
43271
43272	}
43273
43274	/**
43275	 * Serializes this animation clip into JSON.
43276	 *
43277	 * @return {Object} The JSON object.
43278	 */
43279	toJSON() {
43280
43281		return this.constructor.toJSON( this );
43282
43283	}
43284
43285}
43286
43287function getTrackTypeForValueTypeName( typeName ) {
43288
43289	switch ( typeName.toLowerCase() ) {
43290
43291		case 'scalar':
43292		case 'double':
43293		case 'float':
43294		case 'number':
43295		case 'integer':
43296
43297			return NumberKeyframeTrack;
43298
43299		case 'vector':
43300		case 'vector2':
43301		case 'vector3':
43302		case 'vector4':
43303
43304			return VectorKeyframeTrack;
43305
43306		case 'color':
43307
43308			return ColorKeyframeTrack;
43309
43310		case 'quaternion':
43311
43312			return QuaternionKeyframeTrack;
43313
43314		case 'bool':
43315		case 'boolean':
43316
43317			return BooleanKeyframeTrack;
43318
43319		case 'string':
43320
43321			return StringKeyframeTrack;
43322
43323	}
43324
43325	throw new Error( 'THREE.KeyframeTrack: Unsupported typeName: ' + typeName );
43326
43327}
43328
43329function parseKeyframeTrack( json ) {
43330
43331	if ( json.type === undefined ) {
43332
43333		throw new Error( 'THREE.KeyframeTrack: track type undefined, can not parse' );
43334
43335	}
43336
43337	const trackType = getTrackTypeForValueTypeName( json.type );
43338
43339	if ( json.times === undefined ) {
43340
43341		const times = [], values = [];
43342
43343		flattenJSON( json.keys, times, values, 'value' );
43344
43345		json.times = times;
43346		json.values = values;
43347
43348	}
43349
43350	// derived classes can define a static parse method
43351	if ( trackType.parse !== undefined ) {
43352
43353		return trackType.parse( json );
43354
43355	} else {
43356
43357		// by default, we assume a constructor compatible with the base
43358		return new trackType( json.name, json.times, json.values, json.interpolation );
43359
43360	}
43361
43362}
43363
43364/**
43365 * @class
43366 * @classdesc A simple caching system, used internally by {@link FileLoader}.
43367 * To enable caching across all loaders that use {@link FileLoader}, add `THREE.Cache.enabled = true.` once in your app.
43368 * @hideconstructor
43369 */
43370const Cache = {
43371
43372	/**
43373	 * Whether caching is enabled or not.
43374	 *
43375	 * @static
43376	 * @type {boolean}
43377	 * @default false
43378	 */
43379	enabled: false,
43380
43381	/**
43382	 * A dictionary that holds cached files.
43383	 *
43384	 * @static
43385	 * @type {Object<string,Object>}
43386	 */
43387	files: {},
43388
43389	/**
43390	 * Adds a cache entry with a key to reference the file. If this key already
43391	 * holds a file, it is overwritten.
43392	 *
43393	 * @static
43394	 * @param {string} key - The key to reference the cached file.
43395	 * @param {Object} file -  The file to be cached.
43396	 */
43397	add: function ( key, file ) {
43398
43399		if ( this.enabled === false ) return;
43400
43401		if ( isBlobURL( key ) ) return;
43402
43403		// log( 'Cache', 'Adding key:', key );
43404
43405		this.files[ key ] = file;
43406
43407	},
43408
43409	/**
43410	 * Gets the cached value for the given key.
43411	 *
43412	 * @static
43413	 * @param {string} key - The key to reference the cached file.
43414	 * @return {Object|undefined} The cached file. If the key does not exist `undefined` is returned.
43415	 */
43416	get: function ( key ) {
43417
43418		if ( this.enabled === false ) return;
43419
43420		if ( isBlobURL( key ) ) return;
43421
43422		// log( 'Cache', 'Checking key:', key );
43423
43424		return this.files[ key ];
43425
43426	},
43427
43428	/**
43429	 * Removes the cached file associated with the given key.
43430	 *
43431	 * @static
43432	 * @param {string} key - The key to reference the cached file.
43433	 */
43434	remove: function ( key ) {
43435
43436		delete this.files[ key ];
43437
43438	},
43439
43440	/**
43441	 * Remove all values from the cache.
43442	 *
43443	 * @static
43444	 */
43445	clear: function () {
43446
43447		this.files = {};
43448
43449	}
43450
43451};
43452
43453/**
43454 * Returns true if the given cache key contains the blob: scheme.
43455 *
43456 * @private
43457 * @param {string} key - The cache key.
43458 * @return {boolean} Whether the given cache key contains the blob: scheme or not.
43459 */
43460function isBlobURL( key ) {
43461
43462	try {
43463
43464		const urlString = key.slice( key.indexOf( ':' ) + 1 ); // remove type identifier
43465
43466		const url = new URL( urlString );
43467		return url.protocol === 'blob:';
43468
43469	} catch ( e ) {
43470
43471		// If the string is not a valid URL, it throws an error
43472		return false;
43473
43474	}
43475
43476}
43477
43478/**
43479 * Handles and keeps track of loaded and pending data. A default global
43480 * instance of this class is created and used by loaders if not supplied
43481 * manually.
43482 *
43483 * In general that should be sufficient, however there are times when it can
43484 * be useful to have separate loaders - for example if you want to show
43485 * separate loading bars for objects and textures.
43486 *
43487 * ```js
43488 * const manager = new THREE.LoadingManager();
43489 * manager.onLoad = () => console.log( 'Loading complete!' );
43490 *
43491 * const loader1 = new OBJLoader( manager );
43492 * const loader2 = new ColladaLoader( manager );
43493 * ```
43494 */
43495class LoadingManager {
43496
43497	/**
43498	 * Constructs a new loading manager.
43499	 *
43500	 * @param {Function} [onLoad] - Executes when all items have been loaded.
43501	 * @param {Function} [onProgress] - Executes when single items have been loaded.
43502	 * @param {Function} [onError] - Executes when an error occurs.
43503	 */
43504	constructor( onLoad, onProgress, onError ) {
43505
43506		const scope = this;
43507
43508		let isLoading = false;
43509		let itemsLoaded = 0;
43510		let itemsTotal = 0;
43511		let urlModifier = undefined;
43512		const handlers = [];
43513
43514		// Refer to #5689 for the reason why we don't set .onStart
43515		// in the constructor
43516
43517		/**
43518		 * Executes when an item starts loading.
43519		 *
43520		 * @type {Function|undefined}
43521		 * @default undefined
43522		 */
43523		this.onStart = undefined;
43524
43525		/**
43526		 * Executes when all items have been loaded.
43527		 *
43528		 * @type {Function|undefined}
43529		 * @default undefined
43530		 */
43531		this.onLoad = onLoad;
43532
43533		/**
43534		 * Executes when single items have been loaded.
43535		 *
43536		 * @type {Function|undefined}
43537		 * @default undefined
43538		 */
43539		this.onProgress = onProgress;
43540
43541		/**
43542		 * Executes when an error occurs.
43543		 *
43544		 * @type {Function|undefined}
43545		 * @default undefined
43546		 */
43547		this.onError = onError;
43548
43549		/**
43550		 * Used for aborting ongoing requests in loaders using this manager.
43551		 *
43552		 * @private
43553		 * @type {AbortController | null}
43554		 */
43555		this._abortController = null;
43556
43557		/**
43558		 * This should be called by any loader using the manager when the loader
43559		 * starts loading an item.
43560		 *
43561		 * @param {string} url - The URL to load.
43562		 */
43563		this.itemStart = function ( url ) {
43564
43565			itemsTotal ++;
43566
43567			if ( isLoading === false ) {
43568
43569				if ( scope.onStart !== undefined ) {
43570
43571					scope.onStart( url, itemsLoaded, itemsTotal );
43572
43573				}
43574
43575			}
43576
43577			isLoading = true;
43578
43579		};
43580
43581		/**
43582		 * This should be called by any loader using the manager when the loader
43583		 * ended loading an item.
43584		 *
43585		 * @param {string} url - The URL of the loaded item.
43586		 */
43587		this.itemEnd = function ( url ) {
43588
43589			itemsLoaded ++;
43590
43591			if ( scope.onProgress !== undefined ) {
43592
43593				scope.onProgress( url, itemsLoaded, itemsTotal );
43594
43595			}
43596
43597			if ( itemsLoaded === itemsTotal ) {
43598
43599				isLoading = false;
43600
43601				if ( scope.onLoad !== undefined ) {
43602
43603					scope.onLoad();
43604
43605				}
43606
43607			}
43608
43609		};
43610
43611		/**
43612		 * This should be called by any loader using the manager when the loader
43613		 * encounters an error when loading an item.
43614		 *
43615		 * @param {string} url - The URL of the item that produces an error.
43616		 */
43617		this.itemError = function ( url ) {
43618
43619			if ( scope.onError !== undefined ) {
43620
43621				scope.onError( url );
43622
43623			}
43624
43625		};
43626
43627		/**
43628		 * Given a URL, uses the URL modifier callback (if any) and returns a
43629		 * resolved URL. If no URL modifier is set, returns the original URL.
43630		 *
43631		 * @param {string} url - The URL to load.
43632		 * @return {string} The resolved URL.
43633		 */
43634		this.resolveURL = function ( url ) {
43635
43636			if ( urlModifier ) {
43637
43638				return urlModifier( url );
43639
43640			}
43641
43642			return url;
43643
43644		};
43645
43646		/**
43647		 * If provided, the callback will be passed each resource URL before a
43648		 * request is sent. The callback may return the original URL, or a new URL to
43649		 * override loading behavior. This behavior can be used to load assets from
43650		 * .ZIP files, drag-and-drop APIs, and Data URIs.
43651		 *
43652		 * ```js
43653		 * const blobs = {'fish.gltf': blob1, 'diffuse.png': blob2, 'normal.png': blob3};
43654		 *
43655		 * const manager = new THREE.LoadingManager();
43656		 *
43657		 * // Initialize loading manager with URL callback.
43658		 * const objectURLs = [];
43659		 * manager.setURLModifier( ( url ) => {
43660		 *
43661		 * 	url = URL.createObjectURL( blobs[ url ] );
43662		 * 	objectURLs.push( url );
43663		 * 	return url;
43664		 *
43665		 * } );
43666		 *
43667		 * // Load as usual, then revoke the blob URLs.
43668		 * const loader = new GLTFLoader( manager );
43669		 * loader.load( 'fish.gltf', (gltf) => {
43670		 *
43671		 * 	scene.add( gltf.scene );
43672		 * 	objectURLs.forEach( ( url ) =>
vendor: 29,134 bytes, lines 43672-44953
43672 URL.revokeObjectURL( url ) );
43673		 *
43674		 * } );
43675		 * ```
43676		 *
43677		 * @param {function(string):string} transform - URL modifier callback. Called with an URL and must return a resolved URL.
43678		 * @return {LoadingManager} A reference to this loading manager.
43679		 */
43680		this.setURLModifier = function ( transform ) {
43681
43682			urlModifier = transform;
43683
43684			return this;
43685
43686		};
43687
43688		/**
43689		 * Registers a loader with the given regular expression. Can be used to
43690		 * define what loader should be used in order to load specific files. A
43691		 * typical use case is to overwrite the default loader for textures.
43692		 *
43693		 * ```js
43694		 * // add handler for TGA textures
43695		 * manager.addHandler( /\.tga$/i, new TGALoader() );
43696		 * ```
43697		 *
43698		 * @param {string} regex - A regular expression.
43699		 * @param {Loader} loader - A loader that should handle matched cases.
43700		 * @return {LoadingManager} A reference to this loading manager.
43701		 */
43702		this.addHandler = function ( regex, loader ) {
43703
43704			handlers.push( regex, loader );
43705
43706			return this;
43707
43708		};
43709
43710		/**
43711		 * Removes the loader for the given regular expression.
43712		 *
43713		 * @param {string} regex - A regular expression.
43714		 * @return {LoadingManager} A reference to this loading manager.
43715		 */
43716		this.removeHandler = function ( regex ) {
43717
43718			const index = handlers.indexOf( regex );
43719
43720			if ( index !== -1 ) {
43721
43722				handlers.splice( index, 2 );
43723
43724			}
43725
43726			return this;
43727
43728		};
43729
43730		/**
43731		 * Can be used to retrieve the registered loader for the given file path.
43732		 *
43733		 * @param {string} file - The file path.
43734		 * @return {?Loader} The registered loader. Returns `null` if no loader was found.
43735		 */
43736		this.getHandler = function ( file ) {
43737
43738			for ( let i = 0, l = handlers.length; i < l; i += 2 ) {
43739
43740				const regex = handlers[ i ];
43741				const loader = handlers[ i + 1 ];
43742
43743				if ( regex.global ) regex.lastIndex = 0; // see #17920
43744
43745				if ( regex.test( file ) ) {
43746
43747					return loader;
43748
43749				}
43750
43751			}
43752
43753			return null;
43754
43755		};
43756
43757		/**
43758		 * Can be used to abort ongoing loading requests in loaders using this manager.
43759		 * The abort only works if the loaders implement {@link Loader#abort} and `AbortSignal.any()`
43760		 * is supported in the browser.
43761		 *
43762		 * @return {LoadingManager} A reference to this loading manager.
43763		 */
43764		this.abort = function () {
43765
43766
43767			this.abortController.abort();
43768			this._abortController = null;
43769
43770			return this;
43771
43772		};
43773
43774	}
43775
43776	// TODO: Revert this back to a single member variable once this issue has been fixed
43777	// https://github.com/cloudflare/workerd/issues/3657
43778
43779	/**
43780	 * Used for aborting ongoing requests in loaders using this manager.
43781	 *
43782	 * @type {AbortController}
43783	 */
43784	get abortController() {
43785
43786		if ( ! this._abortController ) {
43787
43788			this._abortController = new AbortController();
43789
43790		}
43791
43792		return this._abortController;
43793
43794	}
43795
43796}
43797
43798/**
43799 * The global default loading manager.
43800 *
43801 * @constant
43802 * @type {LoadingManager}
43803 */
43804const DefaultLoadingManager = /*@__PURE__*/ new LoadingManager();
43805
43806/**
43807 * Abstract base class for loaders.
43808 *
43809 * @abstract
43810 */
43811class Loader {
43812
43813	/**
43814	 * Constructs a new loader.
43815	 *
43816	 * @param {LoadingManager} [manager] - The loading manager.
43817	 */
43818	constructor( manager ) {
43819
43820		/**
43821		 * The loading manager.
43822		 *
43823		 * @type {LoadingManager}
43824		 * @default DefaultLoadingManager
43825		 */
43826		this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
43827
43828		/**
43829		 * The crossOrigin string to implement CORS for loading the url from a
43830		 * different domain that allows CORS.
43831		 *
43832		 * @type {string}
43833		 * @default 'anonymous'
43834		 */
43835		this.crossOrigin = 'anonymous';
43836
43837		/**
43838		 * Whether the XMLHttpRequest uses credentials.
43839		 *
43840		 * @type {boolean}
43841		 * @default false
43842		 */
43843		this.withCredentials = false;
43844
43845		/**
43846		 * The base path from which the asset will be loaded.
43847		 *
43848		 * @type {string}
43849		 */
43850		this.path = '';
43851
43852		/**
43853		 * The base path from which additional resources like textures will be loaded.
43854		 *
43855		 * @type {string}
43856		 */
43857		this.resourcePath = '';
43858
43859		/**
43860		 * The [request header](https://developer.mozilla.org/en-US/docs/Glossary/Request_header)
43861		 * used in HTTP request.
43862		 *
43863		 * @type {Object<string, any>}
43864		 */
43865		this.requestHeader = {};
43866
43867		if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {
43868
43869			__THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) );
43870
43871		}
43872
43873	}
43874
43875	/**
43876	 * This method needs to be implemented by all concrete loaders. It holds the
43877	 * logic for loading assets from the backend.
43878	 *
43879	 * @abstract
43880	 * @param {string} url - The path/URL of the file to be loaded.
43881	 * @param {Function} onLoad - Executed when the loading process has been finished.
43882	 * @param {onProgressCallback} [onProgress] - Executed while the loading is in progress.
43883	 * @param {onErrorCallback} [onError] - Executed when errors occur.
43884	 */
43885	load( /* url, onLoad, onProgress, onError */ ) {}
43886
43887	/**
43888	 * A async version of {@link Loader#load}.
43889	 *
43890	 * @param {string} url - The path/URL of the file to be loaded.
43891	 * @param {onProgressCallback} [onProgress] - Executed while the loading is in progress.
43892	 * @return {Promise} A Promise that resolves when the asset has been loaded.
43893	 */
43894	loadAsync( url, onProgress ) {
43895
43896		const scope = this;
43897
43898		return new Promise( function ( resolve, reject ) {
43899
43900			scope.load( url, resolve, onProgress, reject );
43901
43902		} );
43903
43904	}
43905
43906	/**
43907	 * This method needs to be implemented by all concrete loaders. It holds the
43908	 * logic for parsing the asset into three.js entities.
43909	 *
43910	 * @abstract
43911	 * @param {any} data - The data to parse.
43912	 */
43913	parse( /* data */ ) {}
43914
43915	/**
43916	 * Sets the `crossOrigin` String to implement CORS for loading the URL
43917	 * from a different domain that allows CORS.
43918	 *
43919	 * @param {string} crossOrigin - The `crossOrigin` value.
43920	 * @return {Loader} A reference to this instance.
43921	 */
43922	setCrossOrigin( crossOrigin ) {
43923
43924		this.crossOrigin = crossOrigin;
43925		return this;
43926
43927	}
43928
43929	/**
43930	 * Whether the XMLHttpRequest uses credentials such as cookies, authorization
43931	 * headers or TLS client certificates, see [XMLHttpRequest.withCredentials](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials).
43932	 *
43933	 * Note: This setting has no effect if you are loading files locally or from the same domain.
43934	 *
43935	 * @param {boolean} value - The `withCredentials` value.
43936	 * @return {Loader} A reference to this instance.
43937	 */
43938	setWithCredentials( value ) {
43939
43940		this.withCredentials = value;
43941		return this;
43942
43943	}
43944
43945	/**
43946	 * Sets the base path for the asset.
43947	 *
43948	 * @param {string} path - The base path.
43949	 * @return {Loader} A reference to this instance.
43950	 */
43951	setPath( path ) {
43952
43953		this.path = path;
43954		return this;
43955
43956	}
43957
43958	/**
43959	 * Sets the base path for dependent resources like textures.
43960	 *
43961	 * @param {string} resourcePath - The resource path.
43962	 * @return {Loader} A reference to this instance.
43963	 */
43964	setResourcePath( resourcePath ) {
43965
43966		this.resourcePath = resourcePath;
43967		return this;
43968
43969	}
43970
43971	/**
43972	 * Sets the given request header.
43973	 *
43974	 * @param {Object} requestHeader - A [request header](https://developer.mozilla.org/en-US/docs/Glossary/Request_header)
43975	 * for configuring the HTTP request.
43976	 * @return {Loader} A reference to this instance.
43977	 */
43978	setRequestHeader( requestHeader ) {
43979
43980		this.requestHeader = requestHeader;
43981		return this;
43982
43983	}
43984
43985	/**
43986	 * This method can be implemented in loaders for aborting ongoing requests.
43987	 *
43988	 * @abstract
43989	 * @return {Loader} A reference to this instance.
43990	 */
43991	abort() {
43992
43993		return this;
43994
43995	}
43996
43997}
43998
43999/**
44000 * Callback for onProgress in loaders.
44001 *
44002 * @callback onProgressCallback
44003 * @param {ProgressEvent} event - An instance of `ProgressEvent` that represents the current loading status.
44004 */
44005
44006/**
44007 * Callback for onError in loaders.
44008 *
44009 * @callback onErrorCallback
44010 * @param {Error} error - The error which occurred during the loading process.
44011 */
44012
44013/**
44014 * The default material name that is used by loaders
44015 * when creating materials for loaded 3D objects.
44016 *
44017 * Note: Not all loaders might honor this setting.
44018 *
44019 * @static
44020 * @type {string}
44021 * @default '__DEFAULT'
44022 */
44023Loader.DEFAULT_MATERIAL_NAME = '__DEFAULT';
44024
44025const loading = {};
44026
44027class HttpError extends Error {
44028
44029	constructor( message, response ) {
44030
44031		super( message );
44032		this.response = response;
44033
44034	}
44035
44036}
44037
44038/**
44039 * A low level class for loading resources with the Fetch API, used internally by
44040 * most loaders. It can also be used directly to load any file type that does
44041 * not have a loader.
44042 *
44043 * This loader supports caching. If you want to use it, add `THREE.Cache.enabled = true;`
44044 * once to your application.
44045 *
44046 * ```js
44047 * const loader = new THREE.FileLoader();
44048 * const data = await loader.loadAsync( 'example.txt' );
44049 * ```
44050 *
44051 * @augments Loader
44052 */
44053class FileLoader extends Loader {
44054
44055	/**
44056	 * Constructs a new file loader.
44057	 *
44058	 * @param {LoadingManager} [manager] - The loading manager.
44059	 */
44060	constructor( manager ) {
44061
44062		super( manager );
44063
44064		/**
44065		 * The expected mime type. Valid values can be found
44066		 * [here](https://developer.mozilla.org/en-US/docs/Web/API/DOMParser/parseFromString#mimetype)
44067		 *
44068		 * @type {string}
44069		 */
44070		this.mimeType = '';
44071
44072		/**
44073		 * The expected response type.
44074		 *
44075		 * @type {('arraybuffer'|'blob'|'document'|'json'|'')}
44076		 * @default ''
44077		 */
44078		this.responseType = '';
44079
44080		/**
44081		 * Used for aborting requests.
44082		 *
44083		 * @private
44084		 * @type {AbortController}
44085		 */
44086		this._abortController = new AbortController();
44087
44088	}
44089
44090	/**
44091	 * Starts loading from the given URL and pass the loaded response to the `onLoad()` callback.
44092	 *
44093	 * @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
44094	 * @param {function(any)} onLoad - Executed when the loading process has been finished.
44095	 * @param {onProgressCallback} [onProgress] - Executed while the loading is in progress.
44096	 * @param {onErrorCallback} [onError] - Executed when errors occur.
44097	 */
44098	load( url, onLoad, onProgress, onError ) {
44099
44100		if ( url === undefined ) url = '';
44101
44102		if ( this.path !== undefined ) url = this.path + url;
44103
44104		url = this.manager.resolveURL( url );
44105
44106		const cached = Cache.get( `file:${url}` );
44107
44108		if ( cached !== undefined ) {
44109
44110			this.manager.itemStart( url );
44111
44112			setTimeout( () => {
44113
44114				if ( onLoad ) onLoad( cached );
44115
44116				this.manager.itemEnd( url );
44117
44118			}, 0 );
44119
44120			return;
44121
44122		}
44123
44124		// Check if request is duplicate
44125
44126		if ( loading[ url ] !== undefined ) {
44127
44128			loading[ url ].push( {
44129
44130				onLoad: onLoad,
44131				onProgress: onProgress,
44132				onError: onError
44133
44134			} );
44135
44136			return;
44137
44138		}
44139
44140		// Initialise array for duplicate requests
44141		loading[ url ] = [];
44142
44143		loading[ url ].push( {
44144			onLoad: onLoad,
44145			onProgress: onProgress,
44146			onError: onError,
44147		} );
44148
44149		// create request
44150		const req = new Request( url, {
44151			headers: new Headers( this.requestHeader ),
44152			credentials: this.withCredentials ? 'include' : 'same-origin',
44153			signal: ( typeof AbortSignal.any === 'function' ) ? AbortSignal.any( [ this._abortController.signal, this.manager.abortController.signal ] ) : this._abortController.signal
44154		} );
44155
44156		// record states ( avoid data race )
44157		const mimeType = this.mimeType;
44158		const responseType = this.responseType;
44159
44160		// start the fetch
44161		fetch( req )
44162			.then( response => {
44163
44164				if ( response.status === 200 || response.status === 0 ) {
44165
44166					// Some browsers return HTTP Status 0 when using non-http protocol
44167					// e.g. 'file://' or 'data://'. Handle as success.
44168
44169					if ( response.status === 0 ) {
44170
44171						warn( 'FileLoader: HTTP Status 0 received.' );
44172
44173					}
44174
44175					// Workaround: Checking if response.body === undefined for Alipay browser #23548
44176
44177					if ( typeof ReadableStream === 'undefined' || response.body === undefined || response.body.getReader === undefined ) {
44178
44179						return response;
44180
44181					}
44182
44183					const callbacks = loading[ url ];
44184					const reader = response.body.getReader();
44185
44186					// Nginx needs X-File-Size check
44187					// https://serverfault.com/questions/482875/why-does-nginx-remove-content-length-header-for-chunked-content
44188					const contentLength = response.headers.get( 'X-File-Size' ) || response.headers.get( 'Content-Length' );
44189					const total = contentLength ? parseInt( contentLength ) : 0;
44190					const lengthComputable = total !== 0;
44191					let loaded = 0;
44192
44193					// periodically read data into the new stream tracking while download progress
44194					const stream = new ReadableStream( {
44195						start( controller ) {
44196
44197							readData();
44198
44199							function readData() {
44200
44201								reader.read().then( ( { done, value } ) => {
44202
44203									if ( done ) {
44204
44205										controller.close();
44206
44207									} else {
44208
44209										loaded += value.byteLength;
44210
44211										const event = new ProgressEvent( 'progress', { lengthComputable, loaded, total } );
44212										for ( let i = 0, il = callbacks.length; i < il; i ++ ) {
44213
44214											const callback = callbacks[ i ];
44215											if ( callback.onProgress ) callback.onProgress( event );
44216
44217										}
44218
44219										controller.enqueue( value );
44220										readData();
44221
44222									}
44223
44224								}, ( e ) => {
44225
44226									controller.error( e );
44227
44228								} );
44229
44230							}
44231
44232						}
44233
44234					} );
44235
44236					return new Response( stream );
44237
44238				} else {
44239
44240					throw new HttpError( `fetch for "${response.url}" responded with ${response.status}: ${response.statusText}`, response );
44241
44242				}
44243
44244			} )
44245			.then( response => {
44246
44247				switch ( responseType ) {
44248
44249					case 'arraybuffer':
44250
44251						return response.arrayBuffer();
44252
44253					case 'blob':
44254
44255						return response.blob();
44256
44257					case 'document':
44258
44259						return response.text()
44260							.then( text => {
44261
44262								const parser = new DOMParser();
44263								return parser.parseFromString( text, mimeType );
44264
44265							} );
44266
44267					case 'json':
44268
44269						return response.json();
44270
44271					default:
44272
44273						if ( mimeType === '' ) {
44274
44275							return response.text();
44276
44277						} else {
44278
44279							// sniff encoding
44280							const re = /charset="?([^;"\s]*)"?/i;
44281							const exec = re.exec( mimeType );
44282							const label = exec && exec[ 1 ] ? exec[ 1 ].toLowerCase() : undefined;
44283							const decoder = new TextDecoder( label );
44284							return response.arrayBuffer().then( ab => decoder.decode( ab ) );
44285
44286						}
44287
44288				}
44289
44290			} )
44291			.then( data => {
44292
44293				// Add to cache only on HTTP success, so that we do not cache
44294				// error response bodies as proper responses to requests.
44295				Cache.add( `file:${url}`, data );
44296
44297				const callbacks = loading[ url ];
44298				delete loading[ url ];
44299
44300				for ( let i = 0, il = callbacks.length; i < il; i ++ ) {
44301
44302					const callback = callbacks[ i ];
44303					if ( callback.onLoad ) callback.onLoad( data );
44304
44305				}
44306
44307			} )
44308			.catch( err => {
44309
44310				// Abort errors and other errors are handled the same
44311
44312				const callbacks = loading[ url ];
44313
44314				if ( callbacks === undefined ) {
44315
44316					// When onLoad was called and url was deleted in `loading`
44317					this.manager.itemError( url );
44318					throw err;
44319
44320				}
44321
44322				delete loading[ url ];
44323
44324				for ( let i = 0, il = callbacks.length; i < il; i ++ ) {
44325
44326					const callback = callbacks[ i ];
44327					if ( callback.onError ) callback.onError( err );
44328
44329				}
44330
44331				this.manager.itemError( url );
44332
44333			} )
44334			.finally( () => {
44335
44336				this.manager.itemEnd( url );
44337
44338			} );
44339
44340		this.manager.itemStart( url );
44341
44342	}
44343
44344	/**
44345	 * Sets the expected response type.
44346	 *
44347	 * @param {('arraybuffer'|'blob'|'document'|'json'|'')} value - The response type.
44348	 * @return {FileLoader} A reference to this file loader.
44349	 */
44350	setResponseType( value ) {
44351
44352		this.responseType = value;
44353		return this;
44354
44355	}
44356
44357	/**
44358	 * Sets the expected mime type of the loaded file.
44359	 *
44360	 * @param {string} value - The mime type.
44361	 * @return {FileLoader} A reference to this file loader.
44362	 */
44363	setMimeType( value ) {
44364
44365		this.mimeType = value;
44366		return this;
44367
44368	}
44369
44370	/**
44371	 * Aborts ongoing fetch requests.
44372	 *
44373	 * @return {FileLoader} A reference to this instance.
44374	 */
44375	abort() {
44376
44377		this._abortController.abort();
44378		this._abortController = new AbortController();
44379
44380		return this;
44381
44382	}
44383
44384}
44385
44386/**
44387 * Class for loading animation clips in the JSON format. The files are internally
44388 * loaded via {@link FileLoader}.
44389 *
44390 * ```js
44391 * const loader = new THREE.AnimationLoader();
44392 * const animations = await loader.loadAsync( 'animations/animation.js' );
44393 * ```
44394 *
44395 * @augments Loader
44396 */
44397class AnimationLoader extends Loader {
44398
44399	/**
44400	 * Constructs a new animation loader.
44401	 *
44402	 * @param {LoadingManager} [manager] - The loading manager.
44403	 */
44404	constructor( manager ) {
44405
44406		super( manager );
44407
44408	}
44409
44410	/**
44411	 * Starts loading from the given URL and pass the loaded animations as an array
44412	 * holding instances of {@link AnimationClip} to the `onLoad()` callback.
44413	 *
44414	 * @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
44415	 * @param {function(Array<AnimationClip>)} onLoad - Executed when the loading process has been finished.
44416	 * @param {onProgressCallback} onProgress - Executed while the loading is in progress.
44417	 * @param {onErrorCallback} onError - Executed when errors occur.
44418	 */
44419	load( url, onLoad, onProgress, onError ) {
44420
44421		const scope = this;
44422
44423		const loader = new FileLoader( this.manager );
44424		loader.setPath( this.path );
44425		loader.setRequestHeader( this.requestHeader );
44426		loader.setWithCredentials( this.withCredentials );
44427		loader.load( url, function ( text ) {
44428
44429			try {
44430
44431				onLoad( scope.parse( JSON.parse( text ) ) );
44432
44433			} catch ( e ) {
44434
44435				if ( onError ) {
44436
44437					onError( e );
44438
44439				} else {
44440
44441					error( e );
44442
44443				}
44444
44445				scope.manager.itemError( url );
44446
44447			}
44448
44449		}, onProgress, onError );
44450
44451	}
44452
44453	/**
44454	 * Parses the given JSON object and returns an array of animation clips.
44455	 *
44456	 * @param {Object} json - The serialized animation clips.
44457	 * @return {Array<AnimationClip>} The parsed animation clips.
44458	 */
44459	parse( json ) {
44460
44461		const animations = [];
44462
44463		for ( let i = 0; i < json.length; i ++ ) {
44464
44465			const clip = AnimationClip.parse( json[ i ] );
44466
44467			animations.push( clip );
44468
44469		}
44470
44471		return animations;
44472
44473	}
44474
44475}
44476
44477/**
44478 * Abstract base class for loading compressed texture formats S3TC, ASTC or ETC.
44479 * Textures are internally loaded via {@link FileLoader}.
44480 *
44481 * Derived classes have to implement the `parse()` method which holds the parsing
44482 * for the respective format.
44483 *
44484 * @abstract
44485 * @augments Loader
44486 */
44487class CompressedTextureLoader extends Loader {
44488
44489	/**
44490	 * Constructs a new compressed texture loader.
44491	 *
44492	 * @param {LoadingManager} [manager] - The loading manager.
44493	 */
44494	constructor( manager ) {
44495
44496		super( manager );
44497
44498	}
44499
44500	/**
44501	 * Starts loading from the given URL and passes the loaded compressed texture
44502	 * to the `onLoad()` callback. The method also returns a new texture object which can
44503	 * directly be used for material creation. If you do it this way, the texture
44504	 * may pop up in your scene once the respective loading process is finished.
44505	 *
44506	 * @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
44507	 * @param {function(CompressedTexture)} onLoad - Executed when the loading process has been finished.
44508	 * @param {onProgressCallback} onProgress - Executed while the loading is in progress.
44509	 * @param {onErrorCallback} onError - Executed when errors occur.
44510	 * @return {CompressedTexture} The compressed texture.
44511	 */
44512	load( url, onLoad, onProgress, onError ) {
44513
44514		const scope = this;
44515
44516		const images = [];
44517
44518		const texture = new CompressedTexture();
44519
44520		const loader = new FileLoader( this.manager );
44521		loader.setPath( this.path );
44522		loader.setResponseType( 'arraybuffer' );
44523		loader.setRequestHeader( this.requestHeader );
44524		loader.setWithCredentials( scope.withCredentials );
44525
44526		let loaded = 0;
44527
44528		function loadTexture( i ) {
44529
44530			loader.load( url[ i ], function ( buffer ) {
44531
44532				const texDatas = scope.parse( buffer, true );
44533
44534				images[ i ] = {
44535					width: texDatas.width,
44536					height: texDatas.height,
44537					format: texDatas.format,
44538					mipmaps: texDatas.mipmaps
44539				};
44540
44541				loaded += 1;
44542
44543				if ( loaded === 6 ) {
44544
44545					if ( texDatas.mipmapCount === 1 ) texture.minFilter = LinearFilter;
44546
44547					texture.image = images;
44548					texture.format = texDatas.format;
44549					texture.needsUpdate = true;
44550
44551					if ( onLoad ) onLoad( texture );
44552
44553				}
44554
44555			}, onProgress, onError );
44556
44557		}
44558
44559		if ( Array.isArray( url ) ) {
44560
44561			for ( let i = 0, il = url.length; i < il; ++ i ) {
44562
44563				loadTexture( i );
44564
44565			}
44566
44567		} else {
44568
44569			// compressed cubemap texture stored in a single DDS file
44570
44571			loader.load( url, function ( buffer ) {
44572
44573				const texDatas = scope.parse( buffer, true );
44574
44575				if ( texDatas.isCubemap ) {
44576
44577					const faces = texDatas.mipmaps.length / texDatas.mipmapCount;
44578
44579					for ( let f = 0; f < faces; f ++ ) {
44580
44581						images[ f ] = { mipmaps: [] };
44582
44583						for ( let i = 0; i < texDatas.mipmapCount; i ++ ) {
44584
44585							images[ f ].mipmaps.push( texDatas.mipmaps[ f * texDatas.mipmapCount + i ] );
44586							images[ f ].format = texDatas.format;
44587							images[ f ].width = texDatas.width;
44588							images[ f ].height = texDatas.height;
44589
44590						}
44591
44592					}
44593
44594					texture.image = images;
44595
44596				} else {
44597
44598					texture.image.width = texDatas.width;
44599					texture.image.height = texDatas.height;
44600					texture.mipmaps = texDatas.mipmaps;
44601
44602				}
44603
44604				if ( texDatas.mipmapCount === 1 ) {
44605
44606					texture.minFilter = LinearFilter;
44607
44608				}
44609
44610				texture.format = texDatas.format;
44611				texture.needsUpdate = true;
44612
44613				if ( onLoad ) onLoad( texture );
44614
44615			}, onProgress, onError );
44616
44617		}
44618
44619		return texture;
44620
44621	}
44622
44623}
44624
44625const _loading = new WeakMap();
44626
44627/**
44628 * A loader for loading images. The class loads images with the HTML `Image` API.
44629 *
44630 * ```js
44631 * const loader = new THREE.ImageLoader();
44632 * const image = await loader.loadAsync( 'image.png' );
44633 * ```
44634 * Please note that `ImageLoader` has dropped support for progress
44635 * events in `r84`. For an `ImageLoader` that supports progress events, see
44636 * [this thread](https://github.com/mrdoob/three.js/issues/10439#issuecomment-275785639).
44637 *
44638 * @augments Loader
44639 */
44640class ImageLoader extends Loader {
44641
44642	/**
44643	 * Constructs a new image loader.
44644	 *
44645	 * @param {LoadingManager} [manager] - The loading manager.
44646	 */
44647	constructor( manager ) {
44648
44649		super( manager );
44650
44651	}
44652
44653	/**
44654	 * Starts loading from the given URL and passes the loaded image
44655	 * to the `onLoad()` callback. The method also returns a new `Image` object which can
44656	 * directly be used for texture creation. If you do it this way, the texture
44657	 * may pop up in your scene once the respective loading process is finished.
44658	 *
44659	 * @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
44660	 * @param {function(Image)} onLoad - Executed when the loading process has been finished.
44661	 * @param {onProgressCallback} onProgress - Unsupported in this loader.
44662	 * @param {onErrorCallback} onError - Executed when errors occur.
44663	 * @return {Image} The image.
44664	 */
44665	load( url, onLoad, onProgress, onError ) {
44666
44667		if ( this.path !== undefined ) url = this.path + url;
44668
44669		url = this.manager.resolveURL( url );
44670
44671		const scope = this;
44672
44673		const cached = Cache.get( `image:${url}` );
44674
44675		if ( cached !== undefined ) {
44676
44677			if ( cached.complete === true ) {
44678
44679				scope.manager.itemStart( url );
44680
44681				setTimeout( function () {
44682
44683					if ( onLoad ) onLoad( cached );
44684
44685					scope.manager.itemEnd( url );
44686
44687				}, 0 );
44688
44689			} else {
44690
44691				let arr = _loading.get( cached );
44692
44693				if ( arr === undefined ) {
44694
44695					arr = [];
44696					_loading.set( cached, arr );
44697
44698				}
44699
44700				arr.push( { onLoad, onError } );
44701
44702			}
44703
44704			return cached;
44705
44706		}
44707
44708		const image = createElementNS( 'img' );
44709
44710		function onImageLoad() {
44711
44712			removeEventListeners();
44713
44714			if ( onLoad ) onLoad( this );
44715
44716			//
44717
44718			const callbacks = _loading.get( this ) || [];
44719
44720			for ( let i = 0; i < callbacks.length; i ++ ) {
44721
44722				const callback = callbacks[ i ];
44723				if ( callback.onLoad ) callback.onLoad( this );
44724
44725			}
44726
44727			_loading.delete( this );
44728
44729			scope.manager.itemEnd( url );
44730
44731		}
44732
44733		function onImageError( event ) {
44734
44735			removeEventListeners();
44736
44737			if ( onError ) onError( event );
44738
44739			Cache.remove( `image:${url}` );
44740
44741			//
44742
44743			const callbacks = _loading.get( this ) || [];
44744
44745			for ( let i = 0; i < callbacks.length; i ++ ) {
44746
44747				const callback = callbacks[ i ];
44748				if ( callback.onError ) callback.onError( event );
44749
44750			}
44751
44752			_loading.delete( this );
44753
44754
44755			scope.manager.itemError( url );
44756			scope.manager.itemEnd( url );
44757
44758		}
44759
44760		function removeEventListeners() {
44761
44762			image.removeEventListener( 'load', onImageLoad, false );
44763			image.removeEventListener( 'error', onImageError, false );
44764
44765		}
44766
44767		image.addEventListener( 'load', onImageLoad, false );
44768		image.addEventListener( 'error', onImageError, false );
44769
44770		if ( url.slice( 0, 5 ) !== 'data:' ) {
44771
44772			if ( this.crossOrigin !== undefined ) image.crossOrigin = this.crossOrigin;
44773
44774		}
44775
44776		Cache.add( `image:${url}`, image );
44777		scope.manager.itemStart( url );
44778
44779		image.src = url;
44780
44781		return image;
44782
44783	}
44784
44785}
44786
44787/**
44788 * Class for loading cube textures. Images are internally loaded via {@link ImageLoader}.
44789 *
44790 * The loader returns an instance of {@link CubeTexture} and expects the cube map to
44791 * be defined as six separate images representing the sides of a cube. Other cube map definitions
44792 * like vertical and horizontal cross, column and row layouts are not supported.
44793 *
44794 * Note that, by convention, cube maps are specified in a coordinate system
44795 * in which positive-x is to the right when looking up the positive-z axis --
44796 * in other words, using a left-handed coordinate system. Since three.js uses
44797 * a right-handed coordinate system, environment maps used in three.js will
44798 * have pos-x and neg-x swapped.
44799 *
44800 * The loaded cube texture is in sRGB color space. Meaning {@link Texture#colorSpace}
44801 * is set to `SRGBColorSpace` by default.
44802 *
44803 * ```js
44804 * const loader = new THREE.CubeTextureLoader().setPath( 'textures/cubeMaps/' );
44805 * const cubeTexture = await loader.loadAsync( [
44806 * 	'px.png', 'nx.png', 'py.png', 'ny.png', 'pz.png', 'nz.png'
44807 * ] );
44808 * scene.background = cubeTexture;
44809 * ```
44810 *
44811 * @augments Loader
44812 */
44813class CubeTextureLoader extends Loader {
44814
44815	/**
44816	 * Constructs a new cube texture loader.
44817	 *
44818	 * @param {LoadingManager} [manager] - The loading manager.
44819	 */
44820	constructor( manager ) {
44821
44822		super( manager );
44823
44824	}
44825
44826	/**
44827	 * Starts loading from the given URL and pass the fully loaded cube texture
44828	 * to the `onLoad()` callback. The method also returns a new cube texture object which can
44829	 * directly be used for material creation. If you do it this way, the cube texture
44830	 * may pop up in your scene once the respective loading process is finished.
44831	 *
44832	 * @param {Array<string>} urls - Array of 6 URLs to images, one for each side of the
44833	 * cube texture. The urls should be specified in the following order: pos-x,
44834	 * neg-x, pos-y, neg-y, pos-z, neg-z. An array of data URIs are allowed as well.
44835	 * @param {function(CubeTexture)} onLoad - Executed when the loading process has been finished.
44836	 * @param {onProgressCallback} onProgress - Unsupported in this loader.
44837	 * @param {onErrorCallback} onError - Executed when errors occur.
44838	 * @return {CubeTexture} The cube texture.
44839	 */
44840	load( urls, onLoad, onProgress, onError ) {
44841
44842		const texture = new CubeTexture();
44843		texture.colorSpace = SRGBColorSpace;
44844
44845		const loader = new ImageLoader( this.manager );
44846		loader.setCrossOrigin( this.crossOrigin );
44847		loader.setPath( this.path );
44848
44849		let loaded = 0;
44850
44851		function loadTexture( i ) {
44852
44853			loader.load( urls[ i ], function ( image ) {
44854
44855				texture.images[ i ] = image;
44856
44857				loaded ++;
44858
44859				if ( loaded === 6 ) {
44860
44861					texture.needsUpdate = true;
44862
44863					if ( onLoad ) onLoad( texture );
44864
44865				}
44866
44867			}, undefined, onError );
44868
44869		}
44870
44871		for ( let i = 0; i < urls.length; ++ i ) {
44872
44873			loadTexture( i );
44874
44875		}
44876
44877		return texture;
44878
44879	}
44880
44881}
44882
44883/**
44884 * Abstract base class for loading binary texture formats RGBE, EXR or TGA.
44885 * Textures are internally loaded via {@link FileLoader}.
44886 *
44887 * Derived classes have to implement the `parse()` method which holds the parsing
44888 * for the respective format.
44889 *
44890 * @abstract
44891 * @augments Loader
44892 */
44893class DataTextureLoader extends Loader {
44894
44895	/**
44896	 * Constructs a new data texture loader.
44897	 *
44898	 * @param {LoadingManager} [manager] - The loading manager.
44899	 */
44900	constructor( manager ) {
44901
44902		super( manager );
44903
44904	}
44905
44906	/**
44907	 * Starts loading from the given URL and passes the loaded data texture
44908	 * to the `onLoad()` callback. The method also returns a new texture object which can
44909	 * directly be used for material creation. If you do it this way, the texture
44910	 * may pop up in your scene once the respective loading process is finished.
44911	 *
44912	 * @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
44913	 * @param {function(DataTexture)} onLoad - Executed when the loading process has been finished.
44914	 * @param {onProgressCallback} onProgress - Executed while the loading is in progress.
44915	 * @param {onErrorCallback} onError - Executed when errors occur.
44916	 * @return {DataTexture} The data texture.
44917	 */
44918	load( url, onLoad, onProgress, onError ) {
44919
44920		const scope = this;
44921
44922		const texture = new DataTexture();
44923
44924		const loader = new FileLoader( this.manager );
44925		loader.setResponseType( 'arraybuffer' );
44926		loader.setRequestHeader( this.requestHeader );
44927		loader.setPath( this.path );
44928		loader.setWithCredentials( scope.withCredentials );
44929		loader.load( url, function ( buffer ) {
44930
44931			let texData;
44932
44933			try {
44934
44935				texData = scope.parse( buffer );
44936
44937			} catch ( e ) {
44938
44939				if ( onError !== undefined ) {
44940
44941					onError( e );
44942
44943				} else {
44944
44945					error( e );
44946
44947				}
44948
44949				return;
44950
44951			}
44952
44953			
vendor: 1,839 bytes, lines 44953-45038
44953if ( texData.image !== undefined ) {
44954
44955				texture.image = texData.image;
44956
44957			} else if ( texData.data !== undefined ) {
44958
44959				texture.image.width = texData.width;
44960				texture.image.height = texData.height;
44961				texture.image.data = texData.data;
44962
44963			}
44964
44965			texture.wrapS = texData.wrapS !== undefined ? texData.wrapS : ClampToEdgeWrapping;
44966			texture.wrapT = texData.wrapT !== undefined ? texData.wrapT : ClampToEdgeWrapping;
44967
44968			texture.magFilter = texData.magFilter !== undefined ? texData.magFilter : LinearFilter;
44969			texture.minFilter = texData.minFilter !== undefined ? texData.minFilter : LinearFilter;
44970
44971			texture.anisotropy = texData.anisotropy !== undefined ? texData.anisotropy : 1;
44972
44973			if ( texData.colorSpace !== undefined ) {
44974
44975				texture.colorSpace = texData.colorSpace;
44976
44977			}
44978
44979			if ( texData.flipY !== undefined ) {
44980
44981				texture.flipY = texData.flipY;
44982
44983			}
44984
44985			if ( texData.format !== undefined ) {
44986
44987				texture.format = texData.format;
44988
44989			}
44990
44991			if ( texData.type !== undefined ) {
44992
44993				texture.type = texData.type;
44994
44995			}
44996
44997			if ( texData.mipmaps !== undefined ) {
44998
44999				texture.mipmaps = texData.mipmaps;
45000				texture.minFilter = LinearMipmapLinearFilter; // presumably...
45001
45002			}
45003
45004			if ( texData.mipmapCount === 1 ) {
45005
45006				texture.minFilter = LinearFilter;
45007
45008			}
45009
45010			if ( texData.generateMipmaps !== undefined ) {
45011
45012				texture.generateMipmaps = texData.generateMipmaps;
45013
45014			}
45015
45016			texture.needsUpdate = true;
45017
45018			if ( onLoad ) onLoad( texture, texData );
45019
45020		}, onProgress, onError );
45021
45022
45023		return texture;
45024
45025	}
45026
45027}
45028
45029/**
45030 * Class for loading textures. Images are internally
45031 * loaded via {@link ImageLoader}.
45032 *
45033 * ```js
45034 * const loader = new THREE.TextureLoader();
45035 * const texture = await loader.loadAsync( 'textures/land_ocean_ice_cloud_2048.jpg' );
45036 *
45037 * const material = new THREE.MeshBasicMaterial( { map:texture } );
45038 * ```
45039 * Please note that `TextureLoader` has dropped support for progress
45040 * events in `r84`. For a `TextureLoader` that supports progress events, see
45041 * [this thread](https://github.com/mrdoob/three.js/issues/10439#issuecomment-293260145).
45042 *
45043 * @augments Loader
45044 */
45045class TextureLoader extends Loader {
45046
45047	/**
45048	 * Constructs a new texture loader.
45049	 *
45050	 * @param {LoadingManager} [manager] - The loading manager.
45051	 */
45052	constructor( manager ) {
45053
45054		super( manager );
45055
45056	}
45057
45058	/**
45059	 * Starts loading from the given URL and pass the fully loaded texture
45060	 * to the `onLoad()` callback. The method also returns a new texture object which can
45061	 * directly be used for material creation. If you do it this way, the texture
45062	 * may pop up in your scene once the respective loading process is finished.
45063	 *
45064	 * @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
45065	 * @param {function(Texture)} onLoad - Executed when the loading process has been finished.
45066	 * @param {onProgressCallback} onProgress - Unsupported in this loader.
45067	 * @param {onErrorCallback} onError - Executed when errors occur.
45068	 * @return {Texture} The texture.
45069	 */
45070	load( url, onLoad, onProgress, onError ) {
45071
45072		const texture = new Texture();
45073
45074		const loader = new ImageLoader( this.manager );
45075		loader.setCrossOrigin( this.crossOrigin );
45076		loader.setPath( this.path );
45077
45078		loader.load( url, function ( image ) {
45079
45080			texture.image = image;
45081			texture.needsUpdate = true;
45082
45083			if ( onLoad !== undefined ) {
45084
45085				onLoad( texture );
45086
45087			}
45088
45089		}, onProgress, onError );
45090
45091		return texture;
45092
45093	}
45094
45095}
45096
45097/**
45098 * Abstract base class for lights - all other light types inherit the
45099 * properties and methods described here.
45100 *
45101 * @abstract
45102 * @augments Object3D
45103 */
45104class Light extends Object3D {
45105
45106	/**
45107	 * Constructs a new light.
45108	 *
45109	 * @param {(number|Color|string)} [color=0xffffff] - The light's color.
45110	 * @param {number} [intensity=1] - The light's strength/intensity.
45111	 */
45112	constructor( color, intensity = 1 ) {
45113
45114		super();
45115
45116		/**
45117		 * This flag can be used for type testing.
45118		 *
45119		 * @type {boolean}
45120		 * @readonly
45121		 * @default true
45122		 */
45123		this.isLight = true;
45124
45125		this.type = 'Light';
45126
45127		/**
45128		 * The light's color.
45129		 *
45130		 * @type {Color}
45131		 */
45132		this.color = new Color( color );
45133
45134		/**
45135		 * The light's intensity.
45136		 *
45137		 * @type {number}
45138		 * @default 1
45139		 */
45140		this.intensity = intensity;
45141
45142	}
45143
45144	/**
45145	 * Frees the GPU-related resources allocated by this instance. Call this
45146	 * method whenever this instance is no longer used in your app.
45147	 */
45148	dispose() {
45149
45150		this.dispatchEvent( { type: 'dispose' } )
vendor: 6,027 bytes, lines 45150-45427
45150;
45151
45152	}
45153
45154	copy( source, recursive ) {
45155
45156		super.copy( source, recursive );
45157
45158		this.color.copy( source.color );
45159		this.intensity = source.intensity;
45160
45161		return this;
45162
45163	}
45164
45165	toJSON( meta ) {
45166
45167		const data = super.toJSON( meta );
45168
45169		data.object.color = this.color.getHex();
45170		data.object.intensity = this.intensity;
45171
45172		return data;
45173
45174	}
45175
45176}
45177
45178/**
45179 * A light source positioned directly above the scene, with color fading from
45180 * the sky color to the ground color.
45181 *
45182 * This light cannot be used to cast shadows.
45183 *
45184 * ```js
45185 * const light = new THREE.HemisphereLight( 0xffffbb, 0x080820, 1 );
45186 * scene.add( light );
45187 * ```
45188 *
45189 * @augments Light
45190 */
45191class HemisphereLight extends Light {
45192
45193	/**
45194	 * Constructs a new hemisphere light.
45195	 *
45196	 * @param {(number|Color|string)} [skyColor=0xffffff] - The light's sky color.
45197	 * @param {(number|Color|string)} [groundColor=0xffffff] - The light's ground color.
45198	 * @param {number} [intensity=1] - The light's strength/intensity.
45199	 */
45200	constructor( skyColor, groundColor, intensity ) {
45201
45202		super( skyColor, intensity );
45203
45204		/**
45205		 * This flag can be used for type testing.
45206		 *
45207		 * @type {boolean}
45208		 * @readonly
45209		 * @default true
45210		 */
45211		this.isHemisphereLight = true;
45212
45213		this.type = 'HemisphereLight';
45214
45215		this.position.copy( Object3D.DEFAULT_UP );
45216		this.updateMatrix();
45217
45218		/**
45219		 * The light's ground color.
45220		 *
45221		 * @type {Color}
45222		 */
45223		this.groundColor = new Color( groundColor );
45224
45225	}
45226
45227	copy( source, recursive ) {
45228
45229		super.copy( source, recursive );
45230
45231		this.groundColor.copy( source.groundColor );
45232
45233		return this;
45234
45235	}
45236
45237	toJSON( meta ) {
45238
45239		const data = super.toJSON( meta );
45240
45241		data.object.groundColor = this.groundColor.getHex();
45242
45243		return data;
45244
45245	}
45246
45247}
45248
45249const _projScreenMatrix = /*@__PURE__*/ new Matrix4();
45250const _lightPositionWorld = /*@__PURE__*/ new Vector3();
45251const _lookTarget = /*@__PURE__*/ new Vector3();
45252
45253/**
45254 * Abstract base class for light shadow classes. These classes
45255 * represent the shadow configuration for different light types.
45256 *
45257 * @abstract
45258 */
45259class LightShadow {
45260
45261	/**
45262	 * Constructs a new light shadow.
45263	 *
45264	 * @param {Camera} camera - The light's view of the world.
45265	 */
45266	constructor( camera ) {
45267
45268		/**
45269		 * The light's view of the world.
45270		 *
45271		 * @type {Camera}
45272		 */
45273		this.camera = camera;
45274
45275		/**
45276		 * The intensity of the shadow. The default is `1`.
45277		 * Valid values are in the range `[0, 1]`.
45278		 *
45279		 * @type {number}
45280		 * @default 1
45281		 */
45282		this.intensity = 1;
45283
45284		/**
45285		 * Shadow map bias, how much to add or subtract from the normalized depth
45286		 * when deciding whether a surface is in shadow.
45287		 *
45288		 * The default is `0`. Very tiny adjustments here (in the order of `0.0001`)
45289		 * may help reduce artifacts in shadows.
45290		 *
45291		 * @type {number}
45292		 * @default 0
45293		 */
45294		this.bias = 0;
45295
45296		/**
45297		 * A node version of `bias`. Only supported with `WebGPURenderer`.
45298		 *
45299		 * If a bias node is defined, `bias` has no effect.
45300		 *
45301		 * @type {?Node<float>}
45302		 * @default null
45303		 */
45304		this.biasNode = null;
45305
45306		/**
45307		 * Defines how much the position used to query the shadow map is offset along
45308		 * the object normal. The default is `0`. Increasing this value can be used to
45309		 * reduce shadow acne especially in large scenes where light shines onto
45310		 * geometry at a shallow angle. The cost is that shadows may appear distorted.
45311		 *
45312		 * @type {number}
45313		 * @default 0
45314		 */
45315		this.normalBias = 0;
45316
45317		/**
45318		 * Setting this to values greater than 1 will blur the edges of the shadow.
45319		 * High values will cause unwanted banding effects in the shadows - a greater
45320		 * map size will allow for a higher value to be used here before these effects
45321		 * become visible.
45322		 *
45323		 * The property has no effect when the shadow map type is `BasicShadowMap`.
45324		 *
45325		 * @type {number}
45326		 * @default 1
45327		 */
45328		this.radius = 1;
45329
45330		/**
45331		 * The amount of samples to use when blurring a VSM shadow map.
45332		 *
45333		 * @type {number}
45334		 * @default 8
45335		 */
45336		this.blurSamples = 8;
45337
45338		/**
45339		 * Defines the width and height of the shadow map. Higher values give better quality
45340		 * shadows at the cost of computation time. Values must be powers of two.
45341		 *
45342		 * @type {Vector2}
45343		 * @default (512,512)
45344		 */
45345		this.mapSize = new Vector2( 512, 512 );
45346
45347		/**
45348		 * The type of shadow texture. The default is `UnsignedByteType`.
45349		 *
45350		 * @type {number}
45351		 * @default UnsignedByteType
45352		 */
45353		this.mapType = UnsignedByteType;
45354
45355		/**
45356		 * The depth map generated using the internal camera; a location beyond a
45357		 * pixel's depth is in shadow. Computed internally during rendering.
45358		 *
45359		 * @type {?RenderTarget}
45360		 * @default null
45361		 */
45362		this.map = null;
45363
45364		/**
45365		 * The distribution map generated using the internal camera; an occlusion is
45366		 * calculated based on the distribution of depths. Computed internally during
45367		 * rendering.
45368		 *
45369		 * @type {?RenderTarget}
45370		 * @default null
45371		 */
45372		this.mapPass = null;
45373
45374		/**
45375		 * Model to shadow camera space, to compute location and depth in shadow map.
45376		 * This is computed internally during rendering.
45377		 *
45378		 * @type {Matrix4}
45379		 */
45380		this.matrix = new Matrix4();
45381
45382		/**
45383		 * Enables automatic updates of the light's shadow. If you do not require dynamic
45384		 * lighting / shadows, you may set this to `false`.
45385		 *
45386		 * @type {boolean}
45387		 * @default true
45388		 */
45389		this.autoUpdate = true;
45390
45391		/**
45392		 * When set to `true`, shadow maps will be updated in the next `render` call.
45393		 * If you have set {@link LightShadow#autoUpdate} to `false`, you will need to
45394		 * set this property to `true` and then make a render call to update the light's shadow.
45395		 *
45396		 * @type {boolean}
45397		 * @default false
45398		 */
45399		this.needsUpdate = false;
45400
45401		this._frustum = new Frustum();
45402		this._frameExtents = new Vector2( 1, 1 );
45403
45404		this._viewportCount = 1;
45405
45406		this._viewports = [
45407
45408			new Vector4( 0, 0, 1, 1 )
45409
45410		];
45411
45412	}
45413
45414	/**
45415	 * Used internally by the renderer to get the number of viewports that need
45416	 * to be rendered for this shadow.
45417	 *
45418	 * @return {number} The viewport count.
45419	 */
45420	getViewportCount() {
45421
45422		return this._viewportCount;
45423
45424	}
45425
45426	/**
45427	 * 
45427Gets the shadow cameras frustum. Used internally by the renderer to cull objects.
45428	 *
45429	 * @return {Frustum} The shadow camera frustum.
45430	 */
45431	getFrustum() {
45432
45433		return this._frustum;
45434
45435	}
45436
45437	/**
45438	 * Update the matrices for the camera and shadow, used internally by the renderer.
45439	 *
45440	 * @param {Light} light - The light for which the shadow is being rendered.
45441	 */
45442	updateMatrices( light ) {
45443
45444		const shadowCamera = this.camera;
45445		const shadowMatrix = this.matrix;
45446
45447		_lightPositionWorld.setFromMatrixPosition( light.matrixWorld );
45448		shadowCamera.position.copy( _lightPositionWorld );
45449
45450		_lookTarget.setFromMatrixPosition( light.target.matrixWorld );
45451		shadowCamera.lookAt( _lookTarget );
45452		shadowCamera.updateMatrixWorld();
45453
45454		_projScreenMatrix.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse );
45455		this._frustum.setFromProjectionMatrix( _projScreenMatrix, shadowCamera.coordinateSystem, shadowCamera.reversedDepth );
45456
45457		if ( shadowCamera.coordinateSystem === WebGPUCoordinateSystem || shadowCamera.reversedDepth ) {
45458
45459			shadowMatrix.set(
45460				0.5, 0.0, 0.0, 0.5,
45461				0.0, 0.5, 0.0, 0.5,
45462				0.0, 0.0, 1.0, 0.0, // Identity Z (preserving the correct [0, 1] range from the projection matrix)
45463				0.0, 0.0, 0.0, 1.0
45464			);
45465
45466		} else {
45467
45468			shadowMatrix.set(
45469				0.5, 0.0, 0.0, 0.5,
45470				0.0, 0.5, 0.0, 0.5,
45471				0.0, 0.0, 0.5, 0.5,
45472				0.0, 0.0, 0.0, 1.0
45473			);
45474
45475		}
45476
45477		shadowMatrix.multiply( _projScreenMatrix
vendor: 8,639 bytes, lines 45477-45878
45477 );
45478
45479	}
45480
45481	/**
45482	 * Returns a viewport definition for the given viewport index.
45483	 *
45484	 * @param {number} viewportIndex - The viewport index.
45485	 * @return {Vector4} The viewport.
45486	 */
45487	getViewport( viewportIndex ) {
45488
45489		return this._viewports[ viewportIndex ];
45490
45491	}
45492
45493	/**
45494	 * Returns the frame extends.
45495	 *
45496	 * @return {Vector2} The frame extends.
45497	 */
45498	getFrameExtents() {
45499
45500		return this._frameExtents;
45501
45502	}
45503
45504	/**
45505	 * Frees the GPU-related resources allocated by this instance. Call this
45506	 * method whenever this instance is no longer used in your app.
45507	 */
45508	dispose() {
45509
45510		if ( this.map ) {
45511
45512			this.map.dispose();
45513
45514		}
45515
45516		if ( this.mapPass ) {
45517
45518			this.mapPass.dispose();
45519
45520		}
45521
45522	}
45523
45524	/**
45525	 * Copies the values of the given light shadow instance to this instance.
45526	 *
45527	 * @param {LightShadow} source - The light shadow to copy.
45528	 * @return {LightShadow} A reference to this light shadow instance.
45529	 */
45530	copy( source ) {
45531
45532		this.camera = source.camera.clone();
45533
45534		this.intensity = source.intensity;
45535
45536		this.bias = source.bias;
45537		this.radius = source.radius;
45538
45539		this.autoUpdate = source.autoUpdate;
45540		this.needsUpdate = source.needsUpdate;
45541		this.normalBias = source.normalBias;
45542		this.blurSamples = source.blurSamples;
45543
45544		this.mapSize.copy( source.mapSize );
45545
45546		this.biasNode = source.biasNode;
45547
45548		return this;
45549
45550	}
45551
45552	/**
45553	 * Returns a new light shadow instance with copied values from this instance.
45554	 *
45555	 * @return {LightShadow} A clone of this instance.
45556	 */
45557	clone() {
45558
45559		return new this.constructor().copy( this );
45560
45561	}
45562
45563	/**
45564	 * Serializes the light shadow into JSON.
45565	 *
45566	 * @return {Object} A JSON object representing the serialized light shadow.
45567	 * @see {@link ObjectLoader#parse}
45568	 */
45569	toJSON() {
45570
45571		const object = {};
45572
45573		if ( this.intensity !== 1 ) object.intensity = this.intensity;
45574		if ( this.bias !== 0 ) object.bias = this.bias;
45575		if ( this.normalBias !== 0 ) object.normalBias = this.normalBias;
45576		if ( this.radius !== 1 ) object.radius = this.radius;
45577		if ( this.mapSize.x !== 512 || this.mapSize.y !== 512 ) object.mapSize = this.mapSize.toArray();
45578
45579		object.camera = this.camera.toJSON( false ).object;
45580		delete object.camera.matrix;
45581
45582		return object;
45583
45584	}
45585
45586}
45587
45588const _position$2 = /*@__PURE__*/ new Vector3();
45589const _quaternion$2 = /*@__PURE__*/ new Quaternion();
45590const _scale$2 = /*@__PURE__*/ new Vector3();
45591
45592/**
45593 * Abstract base class for cameras. This class should always be inherited
45594 * when you build a new camera.
45595 *
45596 * @abstract
45597 * @augments Object3D
45598 */
45599class Camera extends Object3D {
45600
45601	/**
45602	 * Constructs a new camera.
45603	 */
45604	constructor() {
45605
45606		super();
45607
45608		/**
45609		 * This flag can be used for type testing.
45610		 *
45611		 * @type {boolean}
45612		 * @readonly
45613		 * @default true
45614		 */
45615		this.isCamera = true;
45616
45617		this.type = 'Camera';
45618
45619		/**
45620		 * The inverse of the camera's world matrix.
45621		 *
45622		 * @type {Matrix4}
45623		 */
45624		this.matrixWorldInverse = new Matrix4();
45625
45626		/**
45627		 * The camera's projection matrix.
45628		 *
45629		 * @type {Matrix4}
45630		 */
45631		this.projectionMatrix = new Matrix4();
45632
45633		/**
45634		 * The inverse of the camera's projection matrix.
45635		 *
45636		 * @type {Matrix4}
45637		 */
45638		this.projectionMatrixInverse = new Matrix4();
45639
45640		/**
45641		 * The coordinate system in which the camera is used.
45642		 *
45643		 * @type {(WebGLCoordinateSystem|WebGPUCoordinateSystem)}
45644		 */
45645		this.coordinateSystem = WebGLCoordinateSystem;
45646
45647		this._reversedDepth = false;
45648
45649	}
45650
45651	/**
45652	 * The flag that indicates whether the camera uses a reversed depth buffer.
45653	 *
45654	 * @type {boolean}
45655	 * @default false
45656	 */
45657	get reversedDepth() {
45658
45659		return this._reversedDepth;
45660
45661	}
45662
45663	copy( source, recursive ) {
45664
45665		super.copy( source, recursive );
45666
45667		this.matrixWorldInverse.copy( source.matrixWorldInverse );
45668
45669		this.projectionMatrix.copy( source.projectionMatrix );
45670		this.projectionMatrixInverse.copy( source.projectionMatrixInverse );
45671
45672		this.coordinateSystem = source.coordinateSystem;
45673
45674		return this;
45675
45676	}
45677
45678	/**
45679	 * Returns a vector representing the ("look") direction of the 3D object in world space.
45680	 *
45681	 * This method is overwritten since cameras have a different forward vector compared to other
45682	 * 3D objects. A camera looks down its local, negative z-axis by default.
45683	 *
45684	 * @param {Vector3} target - The target vector the result is stored to.
45685	 * @return {Vector3} The 3D object's direction in world space.
45686	 */
45687	getWorldDirection( target ) {
45688
45689		return super.getWorldDirection( target ).negate();
45690
45691	}
45692
45693	updateMatrixWorld( force ) {
45694
45695		super.updateMatrixWorld( force );
45696
45697		// exclude scale from view matrix to be glTF conform
45698
45699		this.matrixWorld.decompose( _position$2, _quaternion$2, _scale$2 );
45700
45701		if ( _scale$2.x === 1 && _scale$2.y === 1 && _scale$2.z === 1 ) {
45702
45703			this.matrixWorldInverse.copy( this.matrixWorld ).invert();
45704
45705		} else {
45706
45707			this.matrixWorldInverse.compose( _position$2, _quaternion$2, _scale$2.set( 1, 1, 1 ) ).invert();
45708
45709		}
45710
45711	}
45712
45713	updateWorldMatrix( updateParents, updateChildren ) {
45714
45715		super.updateWorldMatrix( updateParents, updateChildren );
45716
45717		// exclude scale from view matrix to be glTF conform
45718
45719		this.matrixWorld.decompose( _position$2, _quaternion$2, _scale$2 );
45720
45721		if ( _scale$2.x === 1 && _scale$2.y === 1 && _scale$2.z === 1 ) {
45722
45723			this.matrixWorldInverse.copy( this.matrixWorld ).invert();
45724
45725		} else {
45726
45727			this.matrixWorldInverse.compose( _position$2, _quaternion$2, _scale$2.set( 1, 1, 1 ) ).invert();
45728
45729		}
45730
45731	}
45732
45733	clone() {
45734
45735		return new this.constructor().copy( this );
45736
45737	}
45738
45739}
45740
45741const _v3$1 = /*@__PURE__*/ new Vector3();
45742const _minTarget = /*@__PURE__*/ new Vector2();
45743const _maxTarget = /*@__PURE__*/ new Vector2();
45744
45745/**
45746 * Camera that uses [perspective projection](https://en.wikipedia.org/wiki/Perspective_(graphical)).
45747 *
45748 * This projection mode is designed to mimic the way the human eye sees. It
45749 * is the most common projection mode used for rendering a 3D scene.
45750 *
45751 * ```js
45752 * const camera = new THREE.PerspectiveCamera( 45, width / height, 1, 1000 );
45753 * scene.add( camera );
45754 * ```
45755 *
45756 * @augments Camera
45757 */
45758class PerspectiveCamera extends Camera {
45759
45760	/**
45761	 * Constructs a new perspective camera.
45762	 *
45763	 * @param {number} [fov=50] - The vertical field of view.
45764	 * @param {number} [aspect=1] - The aspect ratio.
45765	 * @param {number} [near=0.1] - The camera's near plane.
45766	 * @param {number} [far=2000] - The camera's far plane.
45767	 */
45768	constructor( fov = 50, aspect = 1, near = 0.1, far = 2000 ) {
45769
45770		super();
45771
45772		/**
45773		 * This flag can be used for type testing.
45774		 *
45775		 * @type {boolean}
45776		 * @readonly
45777		 * @default true
45778		 */
45779		this.isPerspectiveCamera = true;
45780
45781		this.type = 'PerspectiveCamera';
45782
45783		/**
45784		 * The vertical field of view, from bottom to top of view,
45785		 * in degrees.
45786		 *
45787		 * @type {number}
45788		 * @default 50
45789		 */
45790		this.fov = fov;
45791
45792		/**
45793		 * The zoom factor of the camera.
45794		 *
45795		 * @type {number}
45796		 * @default 1
45797		 */
45798		this.zoom = 1;
45799
45800		/**
45801		 * The camera's near plane. The valid range is greater than `0`
45802		 * and less than the current value of {@link PerspectiveCamera#far}.
45803		 *
45804		 * Note that, unlike for the {@link OrthographicCamera}, `0` is <em>not</em> a
45805		 * valid value for a perspective camera's near plane.
45806		 *
45807		 * @type {number}
45808		 * @default 0.1
45809		 */
45810		this.near = near;
45811
45812		/**
45813		 * The camera's far plane. Must be greater than the
45814		 * current value of {@link PerspectiveCamera#near}.
45815		 *
45816		 * @type {number}
45817		 * @default 2000
45818		 */
45819		this.far = far;
45820
45821		/**
45822		 * Object distance used for stereoscopy and depth-of-field effects. This
45823		 * parameter does not influence the projection matrix unless a
45824		 * {@link StereoCamera} is being used.
45825		 *
45826		 * @type {number}
45827		 * @default 10
45828		 */
45829		this.focus = 10;
45830
45831		/**
45832		 * The aspect ratio, usually the canvas width / canvas height.
45833		 *
45834		 * @type {number}
45835		 * @default 1
45836		 */
45837		this.aspect = aspect;
45838
45839		/**
45840		 * Represents the frustum window specification. This property should not be edited
45841		 * directly but via {@link PerspectiveCamera#setViewOffset} and {@link PerspectiveCamera#clearViewOffset}.
45842		 *
45843		 * @type {?Object}
45844		 * @default null
45845		 */
45846		this.view = null;
45847
45848		/**
45849		 * Film size used for the larger axis. Default is `35` (millimeters). This
45850		 * parameter does not influence the projection matrix unless {@link PerspectiveCamera#filmOffset}
45851		 * is set to a nonzero value.
45852		 *
45853		 * @type {number}
45854		 * @default 35
45855		 */
45856		this.filmGauge = 35;
45857
45858		/**
45859		 * Horizontal off-center offset in the same unit as {@link PerspectiveCamera#filmGauge}.
45860		 *
45861		 * @type {number}
45862		 * @default 0
45863		 */
45864		this.filmOffset = 0;
45865
45866		this.updateProjectionMatrix();
45867
45868	}
45869
45870	copy( source, recursive ) {
45871
45872		super.copy( source, recursive );
45873
45874		this.fov = source.fov;
45875		this.zoom = source.zoom;
45876
45877		this.near = source.near;
45878		this.far = source.far;
vendor: 5,593 bytes, lines 45879-46068
45879		this.focus = source.focus;
45880
45881		this.aspect = source.aspect;
45882		this.view = source.view === null ? null : Object.assign( {}, source.view );
45883
45884		this.filmGauge = source.filmGauge;
45885		this.filmOffset = source.filmOffset;
45886
45887		return this;
45888
45889	}
45890
45891	/**
45892	 * Sets the FOV by focal length in respect to the current {@link PerspectiveCamera#filmGauge}.
45893	 *
45894	 * The default film gauge is 35, so that the focal length can be specified for
45895	 * a 35mm (full frame) camera.
45896	 *
45897	 * @param {number} focalLength - Values for focal length and film gauge must have the same unit.
45898	 */
45899	setFocalLength( focalLength ) {
45900
45901		/** see {@link http://www.bobatkins.com/photography/technical/field_of_view.html} */
45902		const vExtentSlope = 0.5 * this.getFilmHeight() / focalLength;
45903
45904		this.fov = RAD2DEG * 2 * Math.atan( vExtentSlope );
45905		this.updateProjectionMatrix();
45906
45907	}
45908
45909	/**
45910	 * Returns the focal length from the current {@link PerspectiveCamera#fov} and
45911	 * {@link PerspectiveCamera#filmGauge}.
45912	 *
45913	 * @return {number} The computed focal length.
45914	 */
45915	getFocalLength() {
45916
45917		const vExtentSlope = Math.tan( DEG2RAD * 0.5 * this.fov );
45918
45919		return 0.5 * this.getFilmHeight() / vExtentSlope;
45920
45921	}
45922
45923	/**
45924	 * Returns the current vertical field of view angle in degrees considering {@link PerspectiveCamera#zoom}.
45925	 *
45926	 * @return {number} The effective FOV.
45927	 */
45928	getEffectiveFOV() {
45929
45930		return RAD2DEG * 2 * Math.atan(
45931			Math.tan( DEG2RAD * 0.5 * this.fov ) / this.zoom );
45932
45933	}
45934
45935	/**
45936	 * Returns the width of the image on the film. If {@link PerspectiveCamera#aspect} is greater than or
45937	 * equal to one (landscape format), the result equals {@link PerspectiveCamera#filmGauge}.
45938	 *
45939	 * @return {number} The film width.
45940	 */
45941	getFilmWidth() {
45942
45943		// film not completely covered in portrait format (aspect < 1)
45944		return this.filmGauge * Math.min( this.aspect, 1 );
45945
45946	}
45947
45948	/**
45949	 * Returns the height of the image on the film. If {@link PerspectiveCamera#aspect} is greater than or
45950	 * equal to one (landscape format), the result equals {@link PerspectiveCamera#filmGauge}.
45951	 *
45952	 * @return {number} The film width.
45953	 */
45954	getFilmHeight() {
45955
45956		// film not completely covered in landscape format (aspect > 1)
45957		return this.filmGauge / Math.max( this.aspect, 1 );
45958
45959	}
45960
45961	/**
45962	 * Computes the 2D bounds of the camera's viewable rectangle at a given distance along the viewing direction.
45963	 * Sets `minTarget` and `maxTarget` to the coordinates of the lower-left and upper-right corners of the view rectangle.
45964	 *
45965	 * @param {number} distance - The viewing distance.
45966	 * @param {Vector2} minTarget - The lower-left corner of the view rectangle is written into this vector.
45967	 * @param {Vector2} maxTarget - The upper-right corner of the view rectangle is written into this vector.
45968	 */
45969	getViewBounds( distance, minTarget, maxTarget ) {
45970
45971		_v3$1.set( -1, -1, 0.5 ).applyMatrix4( this.projectionMatrixInverse );
45972
45973		minTarget.set( _v3$1.x, _v3$1.y ).multiplyScalar( - distance / _v3$1.z );
45974
45975		_v3$1.set( 1, 1, 0.5 ).applyMatrix4( this.projectionMatrixInverse );
45976
45977		maxTarget.set( _v3$1.x, _v3$1.y ).multiplyScalar( - distance / _v3$1.z );
45978
45979	}
45980
45981	/**
45982	 * Computes the width and height of the camera's viewable rectangle at a given distance along the viewing direction.
45983	 *
45984	 * @param {number} distance - The viewing distance.
45985	 * @param {Vector2} target - The target vector that is used to store result where x is width and y is height.
45986	 * @returns {Vector2} The view size.
45987	 */
45988	getViewSize( distance, target ) {
45989
45990		this.getViewBounds( distance, _minTarget, _maxTarget );
45991
45992		return target.subVectors( _maxTarget, _minTarget );
45993
45994	}
45995
45996	/**
45997	 * Sets an offset in a larger frustum. This is useful for multi-window or
45998	 * multi-monitor/multi-machine setups.
45999	 *
46000	 * For example, if you have 3x2 monitors and each monitor is 1920x1080 and
46001	 * the monitors are in grid like this
46002	 *```
46003	 *   +---+---+---+
46004	 *   | A | B | C |
46005	 *   +---+---+---+
46006	 *   | D | E | F |
46007	 *   +---+---+---+
46008	 *```
46009	 * then for each monitor you would call it like this:
46010	 *```js
46011	 * const w = 1920;
46012	 * const h = 1080;
46013	 * const fullWidth = w * 3;
46014	 * const fullHeight = h * 2;
46015	 *
46016	 * // --A--
46017	 * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 0, w, h );
46018	 * // --B--
46019	 * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 0, w, h );
46020	 * // --C--
46021	 * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 0, w, h );
46022	 * // --D--
46023	 * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 1, w, h );
46024	 * // --E--
46025	 * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 1, w, h );
46026	 * // --F--
46027	 * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 1, w, h );
46028	 * ```
46029	 *
46030	 * Note there is no reason monitors have to be the same size or in a grid.
46031	 *
46032	 * @param {number} fullWidth - The full width of multiview setup.
46033	 * @param {number} fullHeight - The full height of multiview setup.
46034	 * @param {number} x - The horizontal offset of the subcamera.
46035	 * @param {number} y - The vertical offset of the subcamera.
46036	 * @param {number} width - The width of subcamera.
46037	 * @param {number} height - The height of subcamera.
46038	 */
46039	setViewOffset( fullWidth, fullHeight, x, y, width, height ) {
46040
46041		this.aspect = fullWidth / fullHeight;
46042
46043		if ( this.view === null ) {
46044
46045			this.view = {
46046				enabled: true,
46047				fullWidth: 1,
46048				fullHeight: 1,
46049				offsetX: 0,
46050				offsetY: 0,
46051				width: 1,
46052				height: 1
46053			};
46054
46055		}
46056
46057		this.view.enabled = true;
46058		this.view.fullWidth = fullWidth;
46059		this.view.fullHeight = fullHeight;
46060		this.view.offsetX = x;
46061		this.view.offsetY = y;
46062		this.view.width = width;
46063		this.view.height = height;
46064
46065		this.updateProjectionMatrix();
46066
46067	}
46068
vendor: 6,394 bytes, lines 46069-46338
46069	/**
46070	 * Removes the view offset from the projection matrix.
46071	 */
46072	clearViewOffset() {
46073
46074		if ( this.view !== null ) {
46075
46076			this.view.enabled = false;
46077
46078		}
46079
46080		this.updateProjectionMatrix();
46081
46082	}
46083
46084	/**
46085	 * Updates the camera's projection matrix. Must be called after any change of
46086	 * camera properties.
46087	 */
46088	updateProjectionMatrix() {
46089
46090		const near = this.near;
46091		let top = near * Math.tan( DEG2RAD * 0.5 * this.fov ) / this.zoom;
46092		let height = 2 * top;
46093		let width = this.aspect * height;
46094		let left = -0.5 * width;
46095		const view = this.view;
46096
46097		if ( this.view !== null && this.view.enabled ) {
46098
46099			const fullWidth = view.fullWidth,
46100				fullHeight = view.fullHeight;
46101
46102			left += view.offsetX * width / fullWidth;
46103			top -= view.offsetY * height / fullHeight;
46104			width *= view.width / fullWidth;
46105			height *= view.height / fullHeight;
46106
46107		}
46108
46109		const skew = this.filmOffset;
46110		if ( skew !== 0 ) left += near * skew / this.getFilmWidth();
46111
46112		this.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far, this.coordinateSystem, this.reversedDepth );
46113
46114		this.projectionMatrixInverse.copy( this.projectionMatrix ).invert();
46115
46116	}
46117
46118	toJSON( meta ) {
46119
46120		const data = super.toJSON( meta );
46121
46122		data.object.fov = this.fov;
46123		data.object.zoom = this.zoom;
46124
46125		data.object.near = this.near;
46126		data.object.far = this.far;
46127		data.object.focus = this.focus;
46128
46129		data.object.aspect = this.aspect;
46130
46131		if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
46132
46133		data.object.filmGauge = this.filmGauge;
46134		data.object.filmOffset = this.filmOffset;
46135
46136		return data;
46137
46138	}
46139
46140}
46141
46142/**
46143 * Represents the shadow configuration of directional lights.
46144 *
46145 * @augments LightShadow
46146 */
46147class SpotLightShadow extends LightShadow {
46148
46149	/**
46150	 * Constructs a new spot light shadow.
46151	 */
46152	constructor() {
46153
46154		super( new PerspectiveCamera( 50, 1, 0.5, 500 ) );
46155
46156		/**
46157		 * This flag can be used for type testing.
46158		 *
46159		 * @type {boolean}
46160		 * @readonly
46161		 * @default true
46162		 */
46163		this.isSpotLightShadow = true;
46164
46165		/**
46166		 * Used to focus the shadow camera. The camera's field of view is set as a
46167		 * percentage of the spotlight's field-of-view. Range is `[0, 1]`.
46168		 *
46169		 * @type {number}
46170		 * @default 1
46171		 */
46172		this.focus = 1;
46173
46174		/**
46175		 * Texture aspect ratio.
46176		 *
46177		 * @type {number}
46178		 * @default 1
46179		 */
46180		this.aspect = 1;
46181
46182	}
46183
46184	updateMatrices( light ) {
46185
46186		const camera = this.camera;
46187
46188		const fov = RAD2DEG * 2 * light.angle * this.focus;
46189		const aspect = ( this.mapSize.width / this.mapSize.height ) * this.aspect;
46190		const far = light.distance || camera.far;
46191
46192		if ( fov !== camera.fov || aspect !== camera.aspect || far !== camera.far ) {
46193
46194			camera.fov = fov;
46195			camera.aspect = aspect;
46196			camera.far = far;
46197			camera.updateProjectionMatrix();
46198
46199		}
46200
46201		super.updateMatrices( light );
46202
46203	}
46204
46205	copy( source ) {
46206
46207		super.copy( source );
46208
46209		this.focus = source.focus;
46210
46211		return this;
46212
46213	}
46214
46215}
46216
46217/**
46218 * This light gets emitted from a single point in one direction, along a cone
46219 * that increases in size the further from the light it gets.
46220 *
46221 * This light can cast shadows - see the {@link SpotLightShadow} for details.
46222 *
46223 * ```js
46224 * // white spotlight shining from the side, modulated by a texture
46225 * const spotLight = new THREE.SpotLight( 0xffffff );
46226 * spotLight.position.set( 100, 1000, 100 );
46227 * spotLight.map = new THREE.TextureLoader().load( url );
46228 *
46229 * spotLight.castShadow = true;
46230 * spotLight.shadow.mapSize.width = 1024;
46231 * spotLight.shadow.mapSize.height = 1024;
46232 * spotLight.shadow.camera.near = 500;
46233 * spotLight.shadow.camera.far = 4000;
46234 * spotLight.shadow.camera.fov = 30;s
46235 * ```
46236 *
46237 * @augments Light
46238 */
46239class SpotLight extends Light {
46240
46241	/**
46242	 * Constructs a new spot light.
46243	 *
46244	 * @param {(number|Color|string)} [color=0xffffff] - The light's color.
46245	 * @param {number} [intensity=1] - The light's strength/intensity measured in candela (cd).
46246	 * @param {number} [distance=0] - Maximum range of the light. `0` means no limit.
46247	 * @param {number} [angle=Math.PI/3] - Maximum angle of light dispersion from its direction whose upper bound is `Math.PI/2`.
46248	 * @param {number} [penumbra=0] - Percent of the spotlight cone that is attenuated due to penumbra. Value range is `[0,1]`.
46249	 * @param {number} [decay=2] - The amount the light dims along the distance of the light.
46250	 */
46251	constructor( color, intensity, distance = 0, angle = Math.PI / 3, penumbra = 0, decay = 2 ) {
46252
46253		super( color, intensity );
46254
46255		/**
46256		 * This flag can be used for type testing.
46257		 *
46258		 * @type {boolean}
46259		 * @readonly
46260		 * @default true
46261		 */
46262		this.isSpotLight = true;
46263
46264		this.type = 'SpotLight';
46265
46266		this.position.copy( Object3D.DEFAULT_UP );
46267		this.updateMatrix();
46268
46269		/**
46270		 * The spot light points from its position to the
46271		 * target's position.
46272		 *
46273		 * For the target's position to be changed to anything other
46274		 * than the default, it must be added to the scene.
46275		 *
46276		 * It is also possible to set the target to be another 3D object
46277		 * in the scene. The light will now track the target object.
46278		 *
46279		 * @type {Object3D}
46280		 */
46281		this.target = new Object3D();
46282
46283		/**
46284		 * Maximum range of the light. `0` means no limit.
46285		 *
46286		 * @type {number}
46287		 * @default 0
46288		 */
46289		this.distance = distance;
46290
46291		/**
46292		 * Maximum angle of light dispersion from its direction whose upper bound is `Math.PI/2`.
46293		 *
46294		 * @type {number}
46295		 * @default Math.PI/3
46296		 */
46297		this.angle = angle;
46298
46299		/**
46300		 * Percent of the spotlight cone that is attenuated due to penumbra.
46301		 * Value range is `[0,1]`.
46302		 *
46303		 * @type {number}
46304		 * @default 0
46305		 */
46306		this.penumbra = penumbra;
46307
46308		/**
46309		 * The amount the light dims along the distance of the light. In context of
46310		 * physically-correct rendering the default value should not be changed.
46311		 *
46312		 * @type {number}
46313		 * @default 2
46314		 */
46315		this.decay = decay;
46316
46317		/**
46318		 * A texture used to modulate the color of the light. The spot light
46319		 * color is mixed with the RGB value of this texture, with a ratio
46320		 * corresponding to its alpha value. The cookie-like masking effect is
46321		 * reproduced using pixel values (0, 0, 0, 1-cookie_value).
46322		 *
46323		 * *Warning*: This property is disabled if {@link Object3D#castShadow} is set to `false`.
46324		 *
46325		 * @type {?Texture}
46326		 * @default null
46327		 */
46328		this.map = null;
46329
46330		/**
46331		 * This property holds the light's shadow configuration.
46332		 *
46333		 * @type {SpotLightShadow}
46334		 */
46335		this.shadow = new SpotLightShadow();
46336
46337	}
46338
vendor: 26,517 bytes, lines 46339-47496
46339	/**
46340	 * The light's power. Power is the luminous power of the light measured in lumens (lm).
46341	 *  Changing the power will also change the light's intensity.
46342	 *
46343	 * @type {number}
46344	 */
46345	get power() {
46346
46347		// compute the light's luminous power (in lumens) from its intensity (in candela)
46348		// by convention for a spotlight, luminous power (lm) = π * luminous intensity (cd)
46349		return this.intensity * Math.PI;
46350
46351	}
46352
46353	set power( power ) {
46354
46355		// set the light's intensity (in candela) from the desired luminous power (in lumens)
46356		this.intensity = power / Math.PI;
46357
46358	}
46359
46360	dispose() {
46361
46362		super.dispose();
46363
46364		this.shadow.dispose();
46365
46366	}
46367
46368	copy( source, recursive ) {
46369
46370		super.copy( source, recursive );
46371
46372		this.distance = source.distance;
46373		this.angle = source.angle;
46374		this.penumbra = source.penumbra;
46375		this.decay = source.decay;
46376
46377		this.target = source.target.clone();
46378		this.map = source.map;
46379		this.shadow = source.shadow.clone();
46380
46381		return this;
46382
46383	}
46384
46385	toJSON( meta ) {
46386
46387		const data = super.toJSON( meta );
46388
46389		data.object.distance = this.distance;
46390		data.object.angle = this.angle;
46391		data.object.decay = this.decay;
46392		data.object.penumbra = this.penumbra;
46393
46394		data.object.target = this.target.uuid;
46395
46396		if ( this.map && this.map.isTexture ) data.object.map = this.map.toJSON( meta ).uuid;
46397
46398		data.object.shadow = this.shadow.toJSON();
46399
46400		return data;
46401
46402	}
46403
46404}
46405
46406/**
46407 * Represents the shadow configuration of point lights.
46408 *
46409 * @augments LightShadow
46410 */
46411class PointLightShadow extends LightShadow {
46412
46413	/**
46414	 * Constructs a new point light shadow.
46415	 */
46416	constructor() {
46417
46418		super( new PerspectiveCamera( 90, 1, 0.5, 500 ) );
46419
46420		/**
46421		 * This flag can be used for type testing.
46422		 *
46423		 * @type {boolean}
46424		 * @readonly
46425		 * @default true
46426		 */
46427		this.isPointLightShadow = true;
46428
46429	}
46430
46431}
46432
46433/**
46434 * A light that gets emitted from a single point in all directions. A common
46435 * use case for this is to replicate the light emitted from a bare
46436 * lightbulb.
46437 *
46438 * This light can cast shadows - see the {@link PointLightShadow} for details.
46439 *
46440 * ```js
46441 * const light = new THREE.PointLight( 0xff0000, 1, 100 );
46442 * light.position.set( 50, 50, 50 );
46443 * scene.add( light );
46444 * ```
46445 *
46446 * @augments Light
46447 */
46448class PointLight extends Light {
46449
46450	/**
46451	 * Constructs a new point light.
46452	 *
46453	 * @param {(number|Color|string)} [color=0xffffff] - The light's color.
46454	 * @param {number} [intensity=1] - The light's strength/intensity measured in candela (cd).
46455	 * @param {number} [distance=0] - Maximum range of the light. `0` means no limit.
46456	 * @param {number} [decay=2] - The amount the light dims along the distance of the light.
46457	 */
46458	constructor( color, intensity, distance = 0, decay = 2 ) {
46459
46460		super( color, intensity );
46461
46462		/**
46463		 * This flag can be used for type testing.
46464		 *
46465		 * @type {boolean}
46466		 * @readonly
46467		 * @default true
46468		 */
46469		this.isPointLight = true;
46470
46471		this.type = 'PointLight';
46472
46473		/**
46474		 * When distance is zero, light will attenuate according to inverse-square
46475		 * law to infinite distance. When distance is non-zero, light will attenuate
46476		 * according to inverse-square law until near the distance cutoff, where it
46477		 * will then attenuate quickly and smoothly to 0. Inherently, cutoffs are not
46478		 * physically correct.
46479		 *
46480		 * @type {number}
46481		 * @default 0
46482		 */
46483		this.distance = distance;
46484
46485		/**
46486		 * The amount the light dims along the distance of the light. In context of
46487		 * physically-correct rendering the default value should not be changed.
46488		 *
46489		 * @type {number}
46490		 * @default 2
46491		 */
46492		this.decay = decay;
46493
46494		/**
46495		 * This property holds the light's shadow configuration.
46496		 *
46497		 * @type {PointLightShadow}
46498		 */
46499		this.shadow = new PointLightShadow();
46500
46501	}
46502
46503	/**
46504	 * The light's power. Power is the luminous power of the light measured in lumens (lm).
46505	 * Changing the power will also change the light's intensity.
46506	 *
46507	 * @type {number}
46508	 */
46509	get power() {
46510
46511		// compute the light's luminous power (in lumens) from its intensity (in candela)
46512		// for an isotropic light source, luminous power (lm) = 4 π luminous intensity (cd)
46513		return this.intensity * 4 * Math.PI;
46514
46515	}
46516
46517	set power( power ) {
46518
46519		// set the light's intensity (in candela) from the desired luminous power (in lumens)
46520		this.intensity = power / ( 4 * Math.PI );
46521
46522	}
46523
46524	dispose() {
46525
46526		super.dispose();
46527
46528		this.shadow.dispose();
46529
46530	}
46531
46532	copy( source, recursive ) {
46533
46534		super.copy( source, recursive );
46535
46536		this.distance = source.distance;
46537		this.decay = source.decay;
46538
46539		this.shadow = source.shadow.clone();
46540
46541		return this;
46542
46543	}
46544
46545	toJSON( meta ) {
46546
46547		const data = super.toJSON( meta );
46548
46549		data.object.distance = this.distance;
46550		data.object.decay = this.decay;
46551
46552		data.object.shadow = this.shadow.toJSON();
46553
46554		return data;
46555
46556	}
46557
46558}
46559
46560/**
46561 * Camera that uses [orthographic projection](https://en.wikipedia.org/wiki/Orthographic_projection).
46562 *
46563 * In this projection mode, an object's size in the rendered image stays
46564 * constant regardless of its distance from the camera. This can be useful
46565 * for rendering 2D scenes and UI elements, amongst other things.
46566 *
46567 * ```js
46568 * const camera = new THREE.OrthographicCamera( width / - 2, width / 2, height / 2, height / - 2, 1, 1000 );
46569 * scene.add( camera );
46570 * ```
46571 *
46572 * @augments Camera
46573 */
46574class OrthographicCamera extends Camera {
46575
46576	/**
46577	 * Constructs a new orthographic camera.
46578	 *
46579	 * @param {number} [left=-1] - The left plane of the camera's frustum.
46580	 * @param {number} [right=1] - The right plane of the camera's frustum.
46581	 * @param {number} [top=1] - The top plane of the camera's frustum.
46582	 * @param {number} [bottom=-1] - The bottom plane of the camera's frustum.
46583	 * @param {number} [near=0.1] - The camera's near plane.
46584	 * @param {number} [far=2000] - The camera's far plane.
46585	 */
46586	constructor( left = -1, right = 1, top = 1, bottom = -1, near = 0.1, far = 2000 ) {
46587
46588		super();
46589
46590		/**
46591		 * This flag can be used for type testing.
46592		 *
46593		 * @type {boolean}
46594		 * @readonly
46595		 * @default true
46596		 */
46597		this.isOrthographicCamera = true;
46598
46599		this.type = 'OrthographicCamera';
46600
46601		/**
46602		 * The zoom factor of the camera.
46603		 *
46604		 * @type {number}
46605		 * @default 1
46606		 */
46607		this.zoom = 1;
46608
46609		/**
46610		 * Represents the frustum window specification. This property should not be edited
46611		 * directly but via {@link PerspectiveCamera#setViewOffset} and {@link PerspectiveCamera#clearViewOffset}.
46612		 *
46613		 * @type {?Object}
46614		 * @default null
46615		 */
46616		this.view = null;
46617
46618		/**
46619		 * The left plane of the camera's frustum.
46620		 *
46621		 * @type {number}
46622		 * @default -1
46623		 */
46624		this.left = left;
46625
46626		/**
46627		 * The right plane of the camera's frustum.
46628		 *
46629		 * @type {number}
46630		 * @default 1
46631		 */
46632		this.right = right;
46633
46634		/**
46635		 * The top plane of the camera's frustum.
46636		 *
46637		 * @type {number}
46638		 * @default 1
46639		 */
46640		this.top = top;
46641
46642		/**
46643		 * The bottom plane of the camera's frustum.
46644		 *
46645		 * @type {number}
46646		 * @default -1
46647		 */
46648		this.bottom = bottom;
46649
46650		/**
46651		 * The camera's near plane. The valid range is greater than `0`
46652		 * and less than the current value of {@link OrthographicCamera#far}.
46653		 *
46654		 * Note that, unlike for the {@link PerspectiveCamera}, `0` is a
46655		 * valid value for an orthographic camera's near plane.
46656		 *
46657		 * @type {number}
46658		 * @default 0.1
46659		 */
46660		this.near = near;
46661
46662		/**
46663		 * The camera's far plane. Must be greater than the
46664		 * current value of {@link OrthographicCamera#near}.
46665		 *
46666		 * @type {number}
46667		 * @default 2000
46668		 */
46669		this.far = far;
46670
46671		this.updateProjectionMatrix();
46672
46673	}
46674
46675	copy( source, recursive ) {
46676
46677		super.copy( source, recursive );
46678
46679		this.left = source.left;
46680		this.right = source.right;
46681		this.top = source.top;
46682		this.bottom = source.bottom;
46683		this.near = source.near;
46684		this.far = source.far;
46685
46686		this.zoom = source.zoom;
46687		this.view = source.view === null ? null : Object.assign( {}, source.view );
46688
46689		return this;
46690
46691	}
46692
46693	/**
46694	 * Sets an offset in a larger frustum. This is useful for multi-window or
46695	 * multi-monitor/multi-machine setups.
46696	 *
46697	 * @param {number} fullWidth - The full width of multiview setup.
46698	 * @param {number} fullHeight - The full height of multiview setup.
46699	 * @param {number} x - The horizontal offset of the subcamera.
46700	 * @param {number} y - The vertical offset of the subcamera.
46701	 * @param {number} width - The width of subcamera.
46702	 * @param {number} height - The height of subcamera.
46703	 * @see {@link PerspectiveCamera#setViewOffset}
46704	 */
46705	setViewOffset( fullWidth, fullHeight, x, y, width, height ) {
46706
46707		if ( this.view === null ) {
46708
46709			this.view = {
46710				enabled: true,
46711				fullWidth: 1,
46712				fullHeight: 1,
46713				offsetX: 0,
46714				offsetY: 0,
46715				width: 1,
46716				height: 1
46717			};
46718
46719		}
46720
46721		this.view.enabled = true;
46722		this.view.fullWidth = fullWidth;
46723		this.view.fullHeight = fullHeight;
46724		this.view.offsetX = x;
46725		this.view.offsetY = y;
46726		this.view.width = width;
46727		this.view.height = height;
46728
46729		this.updateProjectionMatrix();
46730
46731	}
46732
46733	/**
46734	 * Removes the view offset from the projection matrix.
46735	 */
46736	clearViewOffset() {
46737
46738		if ( this.view !== null ) {
46739
46740			this.view.enabled = false;
46741
46742		}
46743
46744		this.updateProjectionMatrix();
46745
46746	}
46747
46748	/**
46749	 * Updates the camera's projection matrix. Must be called after any change of
46750	 * camera properties.
46751	 */
46752	updateProjectionMatrix() {
46753
46754		const dx = ( this.right - this.left ) / ( 2 * this.zoom );
46755		const dy = ( this.top - this.bottom ) / ( 2 * this.zoom );
46756		const cx = ( this.right + this.left ) / 2;
46757		const cy = ( this.top + this.bottom ) / 2;
46758
46759		let left = cx - dx;
46760		let right = cx + dx;
46761		let top = cy + dy;
46762		let bottom = cy - dy;
46763
46764		if ( this.view !== null && this.view.enabled ) {
46765
46766			const scaleW = ( this.right - this.left ) / this.view.fullWidth / this.zoom;
46767			const scaleH = ( this.top - this.bottom ) / this.view.fullHeight / this.zoom;
46768
46769			left += scaleW * this.view.offsetX;
46770			right = left + scaleW * this.view.width;
46771			top -= scaleH * this.view.offsetY;
46772			bottom = top - scaleH * this.view.height;
46773
46774		}
46775
46776		this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far, this.coordinateSystem, this.reversedDepth );
46777
46778		this.projectionMatrixInverse.copy( this.projectionMatrix ).invert();
46779
46780	}
46781
46782	toJSON( meta ) {
46783
46784		const data = super.toJSON( meta );
46785
46786		data.object.zoom = this.zoom;
46787		data.object.left = this.left;
46788		data.object.right = this.right;
46789		data.object.top = this.top;
46790		data.object.bottom = this.bottom;
46791		data.object.near = this.near;
46792		data.object.far = this.far;
46793
46794		if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
46795
46796		return data;
46797
46798	}
46799
46800}
46801
46802/**
46803 * Represents the shadow configuration of directional lights.
46804 *
46805 * @augments LightShadow
46806 */
46807class DirectionalLightShadow extends LightShadow {
46808
46809	/**
46810	 * Constructs a new directional light shadow.
46811	 */
46812	constructor() {
46813
46814		super( new OrthographicCamera( -5, 5, 5, -5, 0.5, 500 ) );
46815
46816		/**
46817		 * This flag can be used for type testing.
46818		 *
46819		 * @type {boolean}
46820		 * @readonly
46821		 * @default true
46822		 */
46823		this.isDirectionalLightShadow = true;
46824
46825	}
46826
46827}
46828
46829/**
46830 * A light that gets emitted in a specific direction. This light will behave
46831 * as though it is infinitely far away and the rays produced from it are all
46832 * parallel. The common use case for this is to simulate daylight; the sun is
46833 * far enough away that its position can be considered to be infinite, and
46834 * all light rays coming from it are parallel.
46835 *
46836 * A common point of confusion for directional lights is that setting the
46837 * rotation has no effect. This is because three.js's DirectionalLight is the
46838 * equivalent to what is often called a 'Target Direct Light' in other
46839 * applications.
46840 *
46841 * This means that its direction is calculated as pointing from the light's
46842 * {@link Object3D#position} to the {@link DirectionalLight#target} position
46843 * (as opposed to a 'Free Direct Light' that just has a rotation
46844 * component).
46845 *
46846 * This light can cast shadows - see the {@link DirectionalLightShadow} for details.
46847 *
46848 * ```js
46849 * // White directional light at half intensity shining from the top.
46850 * const directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
46851 * scene.add( directionalLight );
46852 * ```
46853 *
46854 * @augments Light
46855 */
46856class DirectionalLight extends Light {
46857
46858	/**
46859	 * Constructs a new directional light.
46860	 *
46861	 * @param {(number|Color|string)} [color=0xffffff] - The light's color.
46862	 * @param {number} [intensity=1] - The light's strength/intensity.
46863	 */
46864	constructor( color, intensity ) {
46865
46866		super( color, intensity );
46867
46868		/**
46869		 * This flag can be used for type testing.
46870		 *
46871		 * @type {boolean}
46872		 * @readonly
46873		 * @default true
46874		 */
46875		this.isDirectionalLight = true;
46876
46877		this.type = 'DirectionalLight';
46878
46879		this.position.copy( Object3D.DEFAULT_UP );
46880		this.updateMatrix();
46881
46882		/**
46883		 * The directional light points from its position to the
46884		 * target's position.
46885		 *
46886		 * For the target's position to be changed to anything other
46887		 * than the default, it must be added to the scene.
46888		 *
46889		 * It is also possible to set the target to be another 3D object
46890		 * in the scene. The light will now track the target object.
46891		 *
46892		 * @type {Object3D}
46893		 */
46894		this.target = new Object3D();
46895
46896		/**
46897		 * This property holds the light's shadow configuration.
46898		 *
46899		 * @type {DirectionalLightShadow}
46900		 */
46901		this.shadow = new DirectionalLightShadow();
46902
46903	}
46904
46905	dispose() {
46906
46907		super.dispose();
46908
46909		this.shadow.dispose();
46910
46911	}
46912
46913	copy( source ) {
46914
46915		super.copy( source );
46916
46917		this.target = source.target.clone();
46918		this.shadow = source.shadow.clone();
46919
46920		return this;
46921
46922	}
46923
46924	toJSON( meta ) {
46925
46926		const data = super.toJSON( meta );
46927
46928		data.object.shadow = this.shadow.toJSON();
46929		data.object.target = this.target.uuid;
46930
46931		return data;
46932
46933	}
46934
46935}
46936
46937/**
46938 * This light globally illuminates all objects in the scene equally.
46939 *
46940 * It cannot be used to cast shadows as it does not have a direction.
46941 *
46942 * ```js
46943 * const light = new THREE.AmbientLight( 0x404040 ); // soft white light
46944 * scene.add( light );
46945 * ```
46946 *
46947 * @augments Light
46948 */
46949class AmbientLight extends Light {
46950
46951	/**
46952	 * Constructs a new ambient light.
46953	 *
46954	 * @param {(number|Color|string)} [color=0xffffff] - The light's color.
46955	 * @param {number} [intensity=1] - The light's strength/intensity.
46956	 */
46957	constructor( color, intensity ) {
46958
46959		super( color, intensity );
46960
46961		/**
46962		 * This flag can be used for type testing.
46963		 *
46964		 * @type {boolean}
46965		 * @readonly
46966		 * @default true
46967		 */
46968		this.isAmbientLight = true;
46969
46970		this.type = 'AmbientLight';
46971
46972	}
46973
46974}
46975
46976/**
46977 * This class emits light uniformly across the face a rectangular plane.
46978 * This light type can be used to simulate light sources such as bright
46979 * windows or strip lighting.
46980 *
46981 * Important Notes:
46982 *
46983 * - There is no shadow support.
46984 * - Only PBR materials are supported.
46985 * - You have to include `RectAreaLightUniformsLib` (`WebGLRenderer`) or `RectAreaLightTexturesLib` (`WebGPURenderer`)
46986 * into your app and init the uniforms/textures.
46987 *
46988 * ```js
46989 * RectAreaLightUniformsLib.init(); // only relevant for WebGLRenderer
46990 * THREE.RectAreaLightNode.setLTC( RectAreaLightTexturesLib.init() ); //  only relevant for WebGPURenderer
46991 *
46992 * const intensity = 1; const width = 10; const height = 10;
46993 * const rectLight = new THREE.RectAreaLight( 0xffffff, intensity, width, height );
46994 * rectLight.position.set( 5, 5, 0 );
46995 * rectLight.lookAt( 0, 0, 0 );
46996 * scene.add( rectLight )
46997 * ```
46998 *
46999 * @augments Light
47000 */
47001class RectAreaLight extends Light {
47002
47003	/**
47004	 * Constructs a new area light.
47005	 *
47006	 * @param {(number|Color|string)} [color=0xffffff] - The light's color.
47007	 * @param {number} [intensity=1] - The light's strength/intensity.
47008	 * @param {number} [width=10] - The width of the light.
47009	 * @param {number} [height=10] - The height of the light.
47010	 */
47011	constructor( color, intensity, width = 10, height = 10 ) {
47012
47013		super( color, intensity );
47014
47015		/**
47016		 * This flag can be used for type testing.
47017		 *
47018		 * @type {boolean}
47019		 * @readonly
47020		 * @default true
47021		 */
47022		this.isRectAreaLight = true;
47023
47024		this.type = 'RectAreaLight';
47025
47026		/**
47027		 * The width of the light.
47028		 *
47029		 * @type {number}
47030		 * @default 10
47031		 */
47032		this.width = width;
47033
47034		/**
47035		 * The height of the light.
47036		 *
47037		 * @type {number}
47038		 * @default 10
47039		 */
47040		this.height = height;
47041
47042	}
47043
47044	/**
47045	 * The light's power. Power is the luminous power of the light measured in lumens (lm).
47046	 * Changing the power will also change the light's intensity.
47047	 *
47048	 * @type {number}
47049	 */
47050	get power() {
47051
47052		// compute the light's luminous power (in lumens) from its intensity (in nits)
47053		return this.intensity * this.width * this.height * Math.PI;
47054
47055	}
47056
47057	set power( power ) {
47058
47059		// set the light's intensity (in nits) from the desired luminous power (in lumens)
47060		this.intensity = power / ( this.width * this.height * Math.PI );
47061
47062	}
47063
47064	copy( source ) {
47065
47066		super.copy( source );
47067
47068		this.width = source.width;
47069		this.height = source.height;
47070
47071		return this;
47072
47073	}
47074
47075	toJSON( meta ) {
47076
47077		const data = super.toJSON( meta );
47078
47079		data.object.width = this.width;
47080		data.object.height = this.height;
47081
47082		return data;
47083
47084	}
47085
47086}
47087
47088/**
47089 * Represents a third-order spherical harmonics (SH). Light probes use this class
47090 * to encode lighting information.
47091 *
47092 * - Primary reference: {@link https://graphics.stanford.edu/papers/envmap/envmap.pdf}
47093 * - Secondary reference: {@link https://www.ppsloan.org/publications/StupidSH36.pdf}
47094 */
47095class SphericalHarmonics3 {
47096
47097	/**
47098	 * Constructs a new spherical harmonics.
47099	 */
47100	constructor() {
47101
47102		/**
47103		 * This flag can be used for type testing.
47104		 *
47105		 * @type {boolean}
47106		 * @readonly
47107		 * @default true
47108		 */
47109		this.isSphericalHarmonics3 = true;
47110
47111		/**
47112		 * An array holding the (9) SH coefficients.
47113		 *
47114		 * @type {Array<Vector3>}
47115		 */
47116		this.coefficients = [];
47117
47118		for ( let i = 0; i < 9; i ++ ) {
47119
47120			this.coefficients.push( new Vector3() );
47121
47122		}
47123
47124	}
47125
47126	/**
47127	 * Sets the given SH coefficients to this instance by copying
47128	 * the values.
47129	 *
47130	 * @param {Array<Vector3>} coefficients - The SH coefficients.
47131	 * @return {SphericalHarmonics3} A reference to this spherical harmonics.
47132	 */
47133	set( coefficients ) {
47134
47135		for ( let i = 0; i < 9; i ++ ) {
47136
47137			this.coefficients[ i ].copy( coefficients[ i ] );
47138
47139		}
47140
47141		return this;
47142
47143	}
47144
47145	/**
47146	 * Sets all SH coefficients to `0`.
47147	 *
47148	 * @return {SphericalHarmonics3} A reference to this spherical harmonics.
47149	 */
47150	zero() {
47151
47152		for ( let i = 0; i < 9; i ++ ) {
47153
47154			this.coefficients[ i ].set( 0, 0, 0 );
47155
47156		}
47157
47158		return this;
47159
47160	}
47161
47162	/**
47163	 * Returns the radiance in the direction of the given normal.
47164	 *
47165	 * @param {Vector3} normal - The normal vector (assumed to be unit length)
47166	 * @param {Vector3} target - The target vector that is used to store the method's result.
47167	 * @return {Vector3} The radiance.
47168	 */
47169	getAt( normal, target ) {
47170
47171		// normal is assumed to be unit length
47172
47173		const x = normal.x, y = normal.y, z = normal.z;
47174
47175		const coeff = this.coefficients;
47176
47177		// band 0
47178		target.copy( coeff[ 0 ] ).multiplyScalar( 0.282095 );
47179
47180		// band 1
47181		target.addScaledVector( coeff[ 1 ], 0.488603 * y );
47182		target.addScaledVector( coeff[ 2 ], 0.488603 * z );
47183		target.addScaledVector( coeff[ 3 ], 0.488603 * x );
47184
47185		// band 2
47186		target.addScaledVector( coeff[ 4 ], 1.092548 * ( x * y ) );
47187		target.addScaledVector( coeff[ 5 ], 1.092548 * ( y * z ) );
47188		target.addScaledVector( coeff[ 6 ], 0.315392 * ( 3.0 * z * z - 1.0 ) );
47189		target.addScaledVector( coeff[ 7 ], 1.092548 * ( x * z ) );
47190		target.addScaledVector( coeff[ 8 ], 0.546274 * ( x * x - y * y ) );
47191
47192		return target;
47193
47194	}
47195
47196	/**
47197	 * Returns the irradiance (radiance convolved with cosine lobe) in the
47198	 * direction of the given normal.
47199	 *
47200	 * @param {Vector3} normal - The normal vector (assumed to be unit length)
47201	 * @param {Vector3} target - The target vector that is used to store the method's result.
47202	 * @return {Vector3} The irradiance.
47203	 */
47204	getIrradianceAt( normal, target ) {
47205
47206		// normal is assumed to be unit length
47207
47208		const x = normal.x, y = normal.y, z = normal.z;
47209
47210		const coeff = this.coefficients;
47211
47212		// band 0
47213		target.copy( coeff[ 0 ] ).multiplyScalar( 0.886227 ); // π * 0.282095
47214
47215		// band 1
47216		target.addScaledVector( coeff[ 1 ], 2.0 * 0.511664 * y ); // ( 2 * π / 3 ) * 0.488603
47217		target.addScaledVector( coeff[ 2 ], 2.0 * 0.511664 * z );
47218		target.addScaledVector( coeff[ 3 ], 2.0 * 0.511664 * x );
47219
47220		// band 2
47221		target.addScaledVector( coeff[ 4 ], 2.0 * 0.429043 * x * y ); // ( π / 4 ) * 1.092548
47222		target.addScaledVector( coeff[ 5 ], 2.0 * 0.429043 * y * z );
47223		target.addScaledVector( coeff[ 6 ], 0.743125 * z * z - 0.247708 ); // ( π / 4 ) * 0.315392 * 3
47224		target.addScaledVector( coeff[ 7 ], 2.0 * 0.429043 * x * z );
47225		target.addScaledVector( coeff[ 8 ], 0.429043 * ( x * x - y * y ) ); // ( π / 4 ) * 0.546274
47226
47227		return target;
47228
47229	}
47230
47231	/**
47232	 * Adds the given SH to this instance.
47233	 *
47234	 * @param {SphericalHarmonics3} sh - The SH to add.
47235	 * @return {SphericalHarmonics3} A reference to this spherical harmonics.
47236	 */
47237	add( sh ) {
47238
47239		for ( let i = 0; i < 9; i ++ ) {
47240
47241			this.coefficients[ i ].add( sh.coefficients[ i ] );
47242
47243		}
47244
47245		return this;
47246
47247	}
47248
47249	/**
47250	 * A convenience method for performing {@link SphericalHarmonics3#add} and
47251	 * {@link SphericalHarmonics3#scale} at once.
47252	 *
47253	 * @param {SphericalHarmonics3} sh - The SH to add.
47254	 * @param {number} s - The scale factor.
47255	 * @return {SphericalHarmonics3} A reference to this spherical harmonics.
47256	 */
47257	addScaledSH( sh, s ) {
47258
47259		for ( let i = 0; i < 9; i ++ ) {
47260
47261			this.coefficients[ i ].addScaledVector( sh.coefficients[ i ], s );
47262
47263		}
47264
47265		return this;
47266
47267	}
47268
47269	/**
47270	 * Scales this SH by the given scale factor.
47271	 *
47272	 * @param {number} s - The scale factor.
47273	 * @return {SphericalHarmonics3} A reference to this spherical harmonics.
47274	 */
47275	scale( s ) {
47276
47277		for ( let i = 0; i < 9; i ++ ) {
47278
47279			this.coefficients[ i ].multiplyScalar( s );
47280
47281		}
47282
47283		return this;
47284
47285	}
47286
47287	/**
47288	 * Linear interpolates between the given SH and this instance by the given
47289	 * alpha factor.
47290	 *
47291	 * @param {SphericalHarmonics3} sh - The SH to interpolate with.
47292	 * @param {number} alpha - The alpha factor.
47293	 * @return {SphericalHarmonics3} A reference to this spherical harmonics.
47294	 */
47295	lerp( sh, alpha ) {
47296
47297		for ( let i = 0; i < 9; i ++ ) {
47298
47299			this.coefficients[ i ].lerp( sh.coefficients[ i ], alpha );
47300
47301		}
47302
47303		return this;
47304
47305	}
47306
47307	/**
47308	 * Returns `true` if this spherical harmonics is equal with the given one.
47309	 *
47310	 * @param {SphericalHarmonics3} sh - The spherical harmonics to test for equality.
47311	 * @return {boolean} Whether this spherical harmonics is equal with the given one.
47312	 */
47313	equals( sh ) {
47314
47315		for ( let i = 0; i < 9; i ++ ) {
47316
47317			if ( ! this.coefficients[ i ].equals( sh.coefficients[ i ] ) ) {
47318
47319				return false;
47320
47321			}
47322
47323		}
47324
47325		return true;
47326
47327	}
47328
47329	/**
47330	 * Copies the values of the given spherical harmonics to this instance.
47331	 *
47332	 * @param {SphericalHarmonics3} sh - The spherical harmonics to copy.
47333	 * @return {SphericalHarmonics3} A reference to this spherical harmonics.
47334	 */
47335	copy( sh ) {
47336
47337		return this.set( sh.coefficients );
47338
47339	}
47340
47341	/**
47342	 * Returns a new spherical harmonics with copied values from this instance.
47343	 *
47344	 * @return {SphericalHarmonics3} A clone of this instance.
47345	 */
47346	clone() {
47347
47348		return new this.constructor().copy( this );
47349
47350	}
47351
47352	/**
47353	 * Sets the SH coefficients of this instance from the given array.
47354	 *
47355	 * @param {Array<number>} array - An array holding the SH coefficients.
47356	 * @param {number} [offset=0] - The array offset where to start copying.
47357	 * @return {SphericalHarmonics3} A clone of this instance.
47358	 */
47359	fromArray( array, offset = 0 ) {
47360
47361		const coefficients = this.coefficients;
47362
47363		for ( let i = 0; i < 9; i ++ ) {
47364
47365			coefficients[ i ].fromArray( array, offset + ( i * 3 ) );
47366
47367		}
47368
47369		return this;
47370
47371	}
47372
47373	/**
47374	 * Returns an array with the SH coefficients, or copies them into the provided
47375	 * array. The coefficients are represented as numbers.
47376	 *
47377	 * @param {Array<number>} [array=[]] - The target array.
47378	 * @param {number} [offset=0] - The array offset where to start copying.
47379	 * @return {Array<number>} An array with flat SH coefficients.
47380	 */
47381	toArray( array = [], offset = 0 ) {
47382
47383		const coefficients = this.coefficients;
47384
47385		for ( let i = 0; i < 9; i ++ ) {
47386
47387			coefficients[ i ].toArray( array, offset + ( i * 3 ) );
47388
47389		}
47390
47391		return array;
47392
47393	}
47394
47395	/**
47396	 * Computes the SH basis for the given normal vector.
47397	 *
47398	 * @param {Vector3} normal - The normal.
47399	 * @param {Array<number>} shBasis - The target array holding the SH basis.
47400	 */
47401	static getBasisAt( normal, shBasis ) {
47402
47403		// normal is assumed to be unit length
47404
47405		const x = normal.x, y = normal.y, z = normal.z;
47406
47407		// band 0
47408		shBasis[ 0 ] = 0.282095;
47409
47410		// band 1
47411		shBasis[ 1 ] = 0.488603 * y;
47412		shBasis[ 2 ] = 0.488603 * z;
47413		shBasis[ 3 ] = 0.488603 * x;
47414
47415		// band 2
47416		shBasis[ 4 ] = 1.092548 * x * y;
47417		shBasis[ 5 ] = 1.092548 * y * z;
47418		shBasis[ 6 ] = 0.315392 * ( 3 * z * z - 1 );
47419		shBasis[ 7 ] = 1.092548 * x * z;
47420		shBasis[ 8 ] = 0.546274 * ( x * x - y * y );
47421
47422	}
47423
47424}
47425
47426/**
47427 * Light probes are an alternative way of adding light to a 3D scene. Unlike
47428 * classical light sources (e.g. directional, point or spot lights), light
47429 * probes do not emit light. Instead they store information about light
47430 * passing through 3D space. During rendering, the light that hits a 3D
47431 * object is approximated by using the data from the light probe.
47432 *
47433 * Light probes are usually created from (radiance) environment maps. The
47434 * class {@link LightProbeGenerator} can be used to create light probes from
47435 * cube textures or render targets. However, light estimation data could also
47436 * be provided in other forms e.g. by WebXR. This enables the rendering of
47437 * augmented reality content that reacts to real world lighting.
47438 *
47439 * The current probe implementation in three.js supports so-called diffuse
47440 * light probes. This type of light probe is functionally equivalent to an
47441 * irradiance environment map.
47442 *
47443 * @augments Light
47444 */
47445class LightProbe extends Light {
47446
47447	/**
47448	 * Constructs a new light probe.
47449	 *
47450	 * @param {SphericalHarmonics3} sh - The spherical harmonics which represents encoded lighting information.
47451	 * @param {number} [intensity=1] - The light's strength/intensity.
47452	 */
47453	constructor( sh = new SphericalHarmonics3(), intensity = 1 ) {
47454
47455		super( undefined, intensity );
47456
47457		/**
47458		 * This flag can be used for type testing.
47459		 *
47460		 * @type {boolean}
47461		 * @readonly
47462		 * @default true
47463		 */
47464		this.isLightProbe = true;
47465
47466		/**
47467		 * A light probe uses spherical harmonics to encode lighting information.
47468		 *
47469		 * @type {SphericalHarmonics3}
47470		 */
47471		this.sh = sh;
47472
47473	}
47474
47475	copy( source ) {
47476
47477		super.copy( source );
47478
47479		this.sh.copy( source.sh );
47480
47481		return this;
47482
47483	}
47484
47485	toJSON( meta ) {
47486
47487		const data = super.toJSON( meta );
47488
47489		data.object.sh = this.sh.toArray();
47490
47491		return data;
47492
47493	}
47494
47495}
47496
47497/**
47498 * Class for loading materials. The files are internally
47499 * loaded via {@link FileLoader}.
47500 *
47501 * ```js
47502 * const loader = new THREE.MaterialLoader();
47503 * const material = await loader.loadAsync( 'material.json' );
47504 * ```
47505 * This loader does not support node materials. Use {@link NodeMaterialLoader} instead.
47506 *
47507 * @augments Loader
47508 */
47509class MaterialLoader extends Loader {
47510
47511	/**
47512	 * Constructs a new material loader.
47513	 *
47514	 * @param {LoadingManager} [manager] - The loading manager.
47515	 */
47516	constructor( manager ) {
47517
47518		super( manager );
47519
47520		/**
47521		 * A dictionary holding textures used by the material.
47522		 *
47523		 * @type {Object<string,Texture>}
47524		 */
47525		this.textures = {};
47526
47527	}
47528
47529	/**
47530	 * Starts loading from the given URL and pass the loaded material to the `onLoad()` callback.
47531	 *
47532	 * @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
47533	 * @param {function(Material)} onLoad - Executed when the loading process has been finished.
47534	 * @param {onProgressCallback} onProgress - Executed while the loading is in progress.
47535	 * @param {onErrorCallback} onError - Executed when errors occur.
47536	 */
47537	load( url, onLoad, onProgress, onError ) {
47538
47539		const scope = this;
47540
47541		const loader = new FileLoader( scope.manager );
47542		loader.setPath( scope.path );
47543		loader.setRequestHeader( scope.requestHeader );
47544		loader.setWithCredentials( scope.withCredentials );
47545		loader.load( url, function ( text ) {
47546
47547			try {
47548
47549				onLoad( scope.parse( JSON.parse( text ) ) );
47550
47551			} catch ( e ) {
47552
47553				if ( onError ) {
47554
47555					onError( e );
47556
47557				} else {
47558
47559					error( e );
47560
47561				}
47562
47563				scope.manager.itemError( url );
47564
47565			}
47566
47567		}, onProgress, onError );
47568
47569	}
47570
47571	/**
47572	 * Parses the given JSON object and returns a material.
47573	 *
47574	 * @param {Object} json - The serialized material.
47575	 * @return {Material} The parsed material.
47576	 */
47577	parse( json ) {
47578
47579		const textures = this.textures;
47580
47581		function getTexture( name ) {
47582
47583			if ( textures[ name ] === undefined ) {
47584
47585				warn( 'MaterialLoader: Undefined texture', name );
47586
47587			}
47588
47589			return textures[ name ];
47590
47591		}
47592
47593		const material = this.createMaterialFromType( json.type );
47594
47595		if ( json.uuid !== undefined ) material.uuid = json.uuid;
47596		if ( json.name !== undefined ) material.name = json.name;
47597		if ( json.color !== undefined && material.color !== undefined ) material.color.setHex( json.color );
47598		if ( json.roughness !== undefined ) material.roughness = json.roughness;
47599		if ( json.metalness !== undefined ) material.metalness = json.metalness;
47600		if ( json.sheen !== undefined ) material.sheen = json.sheen;
47601		if ( json.sheenColor !== undefined ) material.sheenColor = new Color().setHex( json.sheenColor );
47602		if ( json.sheenRoughness !== undefined ) material.sheenRoughness = json.sheenRoughness;
47603		if ( json.emissive !== undefined && material.emissive !== undefined ) material.emissive.setHex( json.emissive );
47604		if ( json.specular !== undefined && material.specular !== undefined ) material.specular.setHex( json.specular );
47605		if ( json.specularIntensity !== undefined ) material.specularIntensity = json.specularIntensity;
47606		if ( json.specularColor !== undefined && material.specularColor !== undefined ) material.specularColor.setHex( json.specularColor );
47607		if ( json.shininess !== undefined ) material.shininess = json.shininess;
47608		if ( json.clearcoat !== undefined ) material.clearcoat = json.clearcoat;
47609		if ( json.clearcoatRoughness !== undefined ) material.clearcoatRoughness = json.clearcoatRoughness;
47610		if ( json.dispersion !== undefined ) material.dispersion = json.dispersion;
47611		if ( json.iridescence !== undefined ) material.iridescence = json.iridescence;
47612		if ( json.iridescenceIOR !== undefined ) material.iridescenceIOR = json.iridescenceIOR;
47613		if ( json.iridescenceThicknessRange !== undefined ) material.iridescenceThicknessRange = json.iridescenceThicknessRange;
47614		if ( json.transmission !== undefined ) material.transmission = json.transmission;
47615		if ( json.thickness !== undefined ) material.thickness = json.thickness;
47616		if ( json.attenuationDistance !== undefined ) material.attenuationDistance = json.attenuationDistance;
47617		if ( json.attenuationColor !== undefined && material.attenuationColor !== undefined ) material.attenuationColor.setHex( json.attenuationColor );
47618		if ( json.anisotropy !== undefined ) material.anisotropy = json.anisotropy;
47619		if ( json.anisotropyRotation !== undefined ) material.anisotropyRotation = json.anisotropyRotation;
47620		if ( json.fog !== undefined ) material.fog = json.fog;
47621		if ( json.flatShading !== undefined ) material.flatShading = json.flatShading;
47622		if ( json.blending !== undefined ) material.blending = json.blending;
47623		if ( json.combine !== undefined ) material.combine = json.combine;
47624		if ( json.side !== undefined ) material.side = json.side;
47625		if ( json.shadowSide !== undefined ) material.shadowSide = json.shadowSide;
47626		if ( json.opacity !== undefined ) material.opacity = json.opacity;
47627		if ( json.transparent !== undefined ) material.transparent = json.transparent;
47628		if ( json.alphaTest !== undefined ) material.alphaTest = json.alphaTest;
47629		if ( json.alphaHash !== undefined ) material.alphaHash = json.alphaHash;
47630		if ( json.depthFunc !== undefined ) material.depthFunc = json.depthFunc;
47631		if ( json.depthTest !== undefined ) material.depthTest = json.depthTest;
47632		if ( json.depthWrite !== undefined ) material.depthWrite = json.depthWrite;
47633		if ( json.colorWrite !== undefined ) material.colorWrite = json.colorWrite;
47634		if ( json.blendSrc !== undefined ) material.blendSrc = json.blendSrc;
47635		if ( json.blendDst !== undefined ) material.blendDst = json.blendDst;
47636		if ( json.blendEquation !== undefined ) material.blendEquation = json.blendEquation;
47637		if ( json.blendSrcAlpha !== undefined ) material.blendSrcAlpha = json.blendSrcAlpha;
47638		if ( json.blendDstAlpha !== undefined ) material.blendDstAlpha = json.blendDstAlpha;
47639		if ( json.blendEquationAlpha !== undefined ) material.blendEquationAlpha = json.blendEquationAlpha;
47640		if ( json.blendColor !== undefined && material.blendColor !== undefined ) material.blendColor.setHex( json.blendColor );
47641		if ( json.blendAlpha !== undefined ) material.blendAlpha = json.blendAlpha;
47642		if ( json.stencilWriteMask !== undefined ) material.stencilWriteMask = json.stencilWriteMask;
47643		if ( json.stencilFunc !== undefined ) material.stencilFunc = json.stencilFunc;
47644		if ( json.stencilRef !== undefined ) material.stencilRef = json.stencilRef;
47645		if ( json.stencilFuncMask !== undefined ) material.stencilFuncMask = json.stencilFuncMask;
vendor: 17,999 bytes, lines 47646-48280
47646		if ( json.stencilFail !== undefined ) material.stencilFail = json.stencilFail;
47647		if ( json.stencilZFail !== undefined ) material.stencilZFail = json.stencilZFail;
47648		if ( json.stencilZPass !== undefined ) material.stencilZPass = json.stencilZPass;
47649		if ( json.stencilWrite !== undefined ) material.stencilWrite = json.stencilWrite;
47650
47651		if ( json.wireframe !== undefined ) material.wireframe = json.wireframe;
47652		if ( json.wireframeLinewidth !== undefined ) material.wireframeLinewidth = json.wireframeLinewidth;
47653		if ( json.wireframeLinecap !== undefined ) material.wireframeLinecap = json.wireframeLinecap;
47654		if ( json.wireframeLinejoin !== undefined ) material.wireframeLinejoin = json.wireframeLinejoin;
47655
47656		if ( json.rotation !== undefined ) material.rotation = json.rotation;
47657
47658		if ( json.linewidth !== undefined ) material.linewidth = json.linewidth;
47659		if ( json.dashSize !== undefined ) material.dashSize = json.dashSize;
47660		if ( json.gapSize !== undefined ) material.gapSize = json.gapSize;
47661		if ( json.scale !== undefined ) material.scale = json.scale;
47662
47663		if ( json.polygonOffset !== undefined ) material.polygonOffset = json.polygonOffset;
47664		if ( json.polygonOffsetFactor !== undefined ) material.polygonOffsetFactor = json.polygonOffsetFactor;
47665		if ( json.polygonOffsetUnits !== undefined ) material.polygonOffsetUnits = json.polygonOffsetUnits;
47666
47667		if ( json.dithering !== undefined ) material.dithering = json.dithering;
47668
47669		if ( json.alphaToCoverage !== undefined ) material.alphaToCoverage = json.alphaToCoverage;
47670		if ( json.premultipliedAlpha !== undefined ) material.premultipliedAlpha = json.premultipliedAlpha;
47671		if ( json.forceSinglePass !== undefined ) material.forceSinglePass = json.forceSinglePass;
47672		if ( json.allowOverride !== undefined ) material.allowOverride = json.allowOverride;
47673
47674		if ( json.visible !== undefined ) material.visible = json.visible;
47675
47676		if ( json.toneMapped !== undefined ) material.toneMapped = json.toneMapped;
47677
47678		if ( json.userData !== undefined ) material.userData = json.userData;
47679
47680		if ( json.vertexColors !== undefined ) {
47681
47682			if ( typeof json.vertexColors === 'number' ) {
47683
47684				material.vertexColors = json.vertexColors > 0;
47685
47686			} else {
47687
47688				material.vertexColors = json.vertexColors;
47689
47690			}
47691
47692		}
47693
47694		// Shader Material
47695
47696		if ( json.uniforms !== undefined ) {
47697
47698			for ( const name in json.uniforms ) {
47699
47700				const uniform = json.uniforms[ name ];
47701
47702				material.uniforms[ name ] = {};
47703
47704				switch ( uniform.type ) {
47705
47706					case 't':
47707						material.uniforms[ name ].value = getTexture( uniform.value );
47708						break;
47709
47710					case 'c':
47711						material.uniforms[ name ].value = new Color().setHex( uniform.value );
47712						break;
47713
47714					case 'v2':
47715						material.uniforms[ name ].value = new Vector2().fromArray( uniform.value );
47716						break;
47717
47718					case 'v3':
47719						material.uniforms[ name ].value = new Vector3().fromArray( uniform.value );
47720						break;
47721
47722					case 'v4':
47723						material.uniforms[ name ].value = new Vector4().fromArray( uniform.value );
47724						break;
47725
47726					case 'm3':
47727						material.uniforms[ name ].value = new Matrix3().fromArray( uniform.value );
47728						break;
47729
47730					case 'm4':
47731						material.uniforms[ name ].value = new Matrix4().fromArray( uniform.value );
47732						break;
47733
47734					default:
47735						material.uniforms[ name ].value = uniform.value;
47736
47737				}
47738
47739			}
47740
47741		}
47742
47743		if ( json.defines !== undefined ) material.defines = json.defines;
47744		if ( json.vertexShader !== undefined ) material.vertexShader = json.vertexShader;
47745		if ( json.fragmentShader !== undefined ) material.fragmentShader = json.fragmentShader;
47746		if ( json.glslVersion !== undefined ) material.glslVersion = json.glslVersion;
47747
47748		if ( json.extensions !== undefined ) {
47749
47750			for ( const key in json.extensions ) {
47751
47752				material.extensions[ key ] = json.extensions[ key ];
47753
47754			}
47755
47756		}
47757
47758		if ( json.lights !== undefined ) material.lights = json.lights;
47759		if ( json.clipping !== undefined ) material.clipping = json.clipping;
47760
47761		// for PointsMaterial
47762
47763		if ( json.size !== undefined ) material.size = json.size;
47764		if ( json.sizeAttenuation !== undefined ) material.sizeAttenuation = json.sizeAttenuation;
47765
47766		// maps
47767
47768		if ( json.map !== undefined ) material.map = getTexture( json.map );
47769		if ( json.matcap !== undefined ) material.matcap = getTexture( json.matcap );
47770
47771		if ( json.alphaMap !== undefined ) material.alphaMap = getTexture( json.alphaMap );
47772
47773		if ( json.bumpMap !== undefined ) material.bumpMap = getTexture( json.bumpMap );
47774		if ( json.bumpScale !== undefined ) material.bumpScale = json.bumpScale;
47775
47776		if ( json.normalMap !== undefined ) material.normalMap = getTexture( json.normalMap );
47777		if ( json.normalMapType !== undefined ) material.normalMapType = json.normalMapType;
47778		if ( json.normalScale !== undefined ) {
47779
47780			let normalScale = json.normalScale;
47781
47782			if ( Array.isArray( normalScale ) === false ) {
47783
47784				// Blender exporter used to export a scalar. See #7459
47785
47786				normalScale = [ normalScale, normalScale ];
47787
47788			}
47789
47790			material.normalScale = new Vector2().fromArray( normalScale );
47791
47792		}
47793
47794		if ( json.displacementMap !== undefined ) material.displacementMap = getTexture( json.displacementMap );
47795		if ( json.displacementScale !== undefined ) material.displacementScale = json.displacementScale;
47796		if ( json.displacementBias !== undefined ) material.displacementBias = json.displacementBias;
47797
47798		if ( json.roughnessMap !== undefined ) material.roughnessMap = getTexture( json.roughnessMap );
47799		if ( json.metalnessMap !== undefined ) material.metalnessMap = getTexture( json.metalnessMap );
47800
47801		if ( json.emissiveMap !== undefined ) material.emissiveMap = getTexture( json.emissiveMap );
47802		if ( json.emissiveIntensity !== undefined ) material.emissiveIntensity = json.emissiveIntensity;
47803
47804		if ( json.specularMap !== undefined ) material.specularMap = getTexture( json.specularMap );
47805		if ( json.specularIntensityMap !== undefined ) material.specularIntensityMap = getTexture( json.specularIntensityMap );
47806		if ( json.specularColorMap !== undefined ) material.specularColorMap = getTexture( json.specularColorMap );
47807
47808		if ( json.envMap !== undefined ) material.envMap = getTexture( json.envMap );
47809		if ( json.envMapRotation !== undefined ) material.envMapRotation.fromArray( json.envMapRotation );
47810		if ( json.envMapIntensity !== undefined ) material.envMapIntensity = json.envMapIntensity;
47811
47812		if ( json.reflectivity !== undefined ) material.reflectivity = json.reflectivity;
47813		if ( json.refractionRatio !== undefined ) material.refractionRatio = json.refractionRatio;
47814
47815		if ( json.lightMap !== undefined ) material.lightMap = getTexture( json.lightMap );
47816		if ( json.lightMapIntensity !== undefined ) material.lightMapIntensity = json.lightMapIntensity;
47817
47818		if ( json.aoMap !== undefined ) material.aoMap = getTexture( json.aoMap );
47819		if ( json.aoMapIntensity !== undefined ) material.aoMapIntensity = json.aoMapIntensity;
47820
47821		if ( json.gradientMap !== undefined ) material.gradientMap = getTexture( json.gradientMap );
47822
47823		if ( json.clearcoatMap !== undefined ) material.clearcoatMap = getTexture( json.clearcoatMap );
47824		if ( json.clearcoatRoughnessMap !== undefined ) material.clearcoatRoughnessMap = getTexture( json.clearcoatRoughnessMap );
47825		if ( json.clearcoatNormalMap !== undefined ) material.clearcoatNormalMap = getTexture( json.clearcoatNormalMap );
47826		if ( json.clearcoatNormalScale !== undefined ) material.clearcoatNormalScale = new Vector2().fromArray( json.clearcoatNormalScale );
47827
47828		if ( json.iridescenceMap !== undefined ) material.iridescenceMap = getTexture( json.iridescenceMap );
47829		if ( json.iridescenceThicknessMap !== undefined ) material.iridescenceThicknessMap = getTexture( json.iridescenceThicknessMap );
47830
47831		if ( json.transmissionMap !== undefined ) material.transmissionMap = getTexture( json.transmissionMap );
47832		if ( json.thicknessMap !== undefined ) material.thicknessMap = getTexture( json.thicknessMap );
47833
47834		if ( json.anisotropyMap !== undefined ) material.anisotropyMap = getTexture( json.anisotropyMap );
47835
47836		if ( json.sheenColorMap !== undefined ) material.sheenColorMap = getTexture( json.sheenColorMap );
47837		if ( json.sheenRoughnessMap !== undefined ) material.sheenRoughnessMap = getTexture( json.sheenRoughnessMap );
47838
47839		return material;
47840
47841	}
47842
47843	/**
47844	 * Textures are not embedded in the material JSON so they have
47845	 * to be injected before the loading process starts.
47846	 *
47847	 * @param {Object} value - A dictionary holding textures for material properties.
47848	 * @return {MaterialLoader} A reference to this material loader.
47849	 */
47850	setTextures( value ) {
47851
47852		this.textures = value;
47853		return this;
47854
47855	}
47856
47857	/**
47858	 * Creates a material for the given type.
47859	 *
47860	 * @param {string} type - The material type.
47861	 * @return {Material} The new material.
47862	 */
47863	createMaterialFromType( type ) {
47864
47865		return MaterialLoader.createMaterialFromType( type );
47866
47867	}
47868
47869	/**
47870	 * Creates a material for the given type.
47871	 *
47872	 * @static
47873	 * @param {string} type - The material type.
47874	 * @return {Material} The new material.
47875	 */
47876	static createMaterialFromType( type ) {
47877
47878		const materialLib = {
47879			ShadowMaterial,
47880			SpriteMaterial,
47881			RawShaderMaterial,
47882			ShaderMaterial,
47883			PointsMaterial,
47884			MeshPhysicalMaterial,
47885			MeshStandardMaterial,
47886			MeshPhongMaterial,
47887			MeshToonMaterial,
47888			MeshNormalMaterial,
47889			MeshLambertMaterial,
47890			MeshDepthMaterial,
47891			MeshDistanceMaterial,
47892			MeshBasicMaterial,
47893			MeshMatcapMaterial,
47894			LineDashedMaterial,
47895			LineBasicMaterial,
47896			Material
47897		};
47898
47899		return new materialLib[ type ]();
47900
47901	}
47902
47903}
47904
47905/**
47906 * A class with loader utility functions.
47907 */
47908class LoaderUtils {
47909
47910	/**
47911	 * Extracts the base URL from the given URL.
47912	 *
47913	 * @param {string} url -The URL to extract the base URL from.
47914	 * @return {string} The extracted base URL.
47915	 */
47916	static extractUrlBase( url ) {
47917
47918		const index = url.lastIndexOf( '/' );
47919
47920		if ( index === -1 ) return './';
47921
47922		return url.slice( 0, index + 1 );
47923
47924	}
47925
47926	/**
47927	 * Resolves relative URLs against the given path. Absolute paths, data urls,
47928	 * and blob URLs will be returned as is. Invalid URLs will return an empty
47929	 * string.
47930	 *
47931	 * @param {string} url -The URL to resolve.
47932	 * @param {string} path - The base path for relative URLs to be resolved against.
47933	 * @return {string} The resolved URL.
47934	 */
47935	static resolveURL( url, path ) {
47936
47937		// Invalid URL
47938		if ( typeof url !== 'string' || url === '' ) return '';
47939
47940		// Host Relative URL
47941		if ( /^https?:\/\//i.test( path ) && /^\//.test( url ) ) {
47942
47943			path = path.replace( /(^https?:\/\/[^\/]+).*/i, '$1' );
47944
47945		}
47946
47947		// Absolute URL http://,https://,//
47948		if ( /^(https?:)?\/\//i.test( url ) ) return url;
47949
47950		// Data URI
47951		if ( /^data:.*,.*$/i.test( url ) ) return url;
47952
47953		// Blob URL
47954		if ( /^blob:.*$/i.test( url ) ) return url;
47955
47956		// Relative URL
47957		return path + url;
47958
47959	}
47960
47961}
47962
47963/**
47964 * An instanced version of a geometry.
47965 */
47966class InstancedBufferGeometry extends BufferGeometry {
47967
47968	/**
47969	 * Constructs a new instanced buffer geometry.
47970	 */
47971	constructor() {
47972
47973		super();
47974
47975		/**
47976		 * This flag can be used for type testing.
47977		 *
47978		 * @type {boolean}
47979		 * @readonly
47980		 * @default true
47981		 */
47982		this.isInstancedBufferGeometry = true;
47983
47984		this.type = 'InstancedBufferGeometry';
47985
47986		/**
47987		 * The instance count.
47988		 *
47989		 * @type {number}
47990		 * @default Infinity
47991		 */
47992		this.instanceCount = Infinity;
47993
47994	}
47995
47996	copy( source ) {
47997
47998		super.copy( source );
47999
48000		this.instanceCount = source.instanceCount;
48001
48002		return this;
48003
48004	}
48005
48006	toJSON() {
48007
48008		const data = super.toJSON();
48009
48010		data.instanceCount = this.instanceCount;
48011
48012		data.isInstancedBufferGeometry = true;
48013
48014		return data;
48015
48016	}
48017
48018}
48019
48020/**
48021 * Class for loading geometries. The files are internally
48022 * loaded via {@link FileLoader}.
48023 *
48024 * ```js
48025 * const loader = new THREE.BufferGeometryLoader();
48026 * const geometry = await loader.loadAsync( 'models/json/pressure.json' );
48027 *
48028 * const material = new THREE.MeshBasicMaterial( { color: 0xF5F5F5 } );
48029 * const object = new THREE.Mesh( geometry, material );
48030 * scene.add( object );
48031 * ```
48032 *
48033 * @augments Loader
48034 */
48035class BufferGeometryLoader extends Loader {
48036
48037	/**
48038	 * Constructs a new geometry loader.
48039	 *
48040	 * @param {LoadingManager} [manager] - The loading manager.
48041	 */
48042	constructor( manager ) {
48043
48044		super( manager );
48045
48046	}
48047
48048	/**
48049	 * Starts loading from the given URL and pass the loaded geometry to the `onLoad()` callback.
48050	 *
48051	 * @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
48052	 * @param {function(BufferGeometry)} onLoad - Executed when the loading process has been finished.
48053	 * @param {onProgressCallback} onProgress - Executed while the loading is in progress.
48054	 * @param {onErrorCallback} onError - Executed when errors occur.
48055	 */
48056	load( url, onLoad, onProgress, onError ) {
48057
48058		const scope = this;
48059
48060		const loader = new FileLoader( scope.manager );
48061		loader.setPath( scope.path );
48062		loader.setRequestHeader( scope.requestHeader );
48063		loader.setWithCredentials( scope.withCredentials );
48064		loader.load( url, function ( text ) {
48065
48066			try {
48067
48068				onLoad( scope.parse( JSON.parse( text ) ) );
48069
48070			} catch ( e ) {
48071
48072				if ( onError ) {
48073
48074					onError( e );
48075
48076				} else {
48077
48078					error( e );
48079
48080				}
48081
48082				scope.manager.itemError( url );
48083
48084			}
48085
48086		}, onProgress, onError );
48087
48088	}
48089
48090	/**
48091	 * Parses the given JSON object and returns a geometry.
48092	 *
48093	 * @param {Object} json - The serialized geometry.
48094	 * @return {BufferGeometry} The parsed geometry.
48095	 */
48096	parse( json ) {
48097
48098		const interleavedBufferMap = {};
48099		const arrayBufferMap = {};
48100
48101		function getInterleavedBuffer( json, uuid ) {
48102
48103			if ( interleavedBufferMap[ uuid ] !== undefined ) return interleavedBufferMap[ uuid ];
48104
48105			const interleavedBuffers = json.interleavedBuffers;
48106			const interleavedBuffer = interleavedBuffers[ uuid ];
48107
48108			const buffer = getArrayBuffer( json, interleavedBuffer.buffer );
48109
48110			const array = getTypedArray( interleavedBuffer.type, buffer );
48111			const ib = new InterleavedBuffer( array, interleavedBuffer.stride );
48112			ib.uuid = interleavedBuffer.uuid;
48113
48114			interleavedBufferMap[ uuid ] = ib;
48115
48116			return ib;
48117
48118		}
48119
48120		function getArrayBuffer( json, uuid ) {
48121
48122			if ( arrayBufferMap[ uuid ] !== undefined ) return arrayBufferMap[ uuid ];
48123
48124			const arrayBuffers = json.arrayBuffers;
48125			const arrayBuffer = arrayBuffers[ uuid ];
48126
48127			const ab = new Uint32Array( arrayBuffer ).buffer;
48128
48129			arrayBufferMap[ uuid ] = ab;
48130
48131			return ab;
48132
48133		}
48134
48135		const geometry = json.isInstancedBufferGeometry ? new InstancedBufferGeometry() : new BufferGeometry();
48136
48137		const index = json.data.index;
48138
48139		if ( index !== undefined ) {
48140
48141			const typedArray = getTypedArray( index.type, index.array );
48142			geometry.setIndex( new BufferAttribute( typedArray, 1 ) );
48143
48144		}
48145
48146		const attributes = json.data.attributes;
48147
48148		for ( const key in attributes ) {
48149
48150			const attribute = attributes[ key ];
48151			let bufferAttribute;
48152
48153			if ( attribute.isInterleavedBufferAttribute ) {
48154
48155				const interleavedBuffer = getInterleavedBuffer( json.data, attribute.data );
48156				bufferAttribute = new InterleavedBufferAttribute( interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized );
48157
48158			} else {
48159
48160				const typedArray = getTypedArray( attribute.type, attribute.array );
48161				const bufferAttributeConstr = attribute.isInstancedBufferAttribute ? InstancedBufferAttribute : BufferAttribute;
48162				bufferAttribute = new bufferAttributeConstr( typedArray, attribute.itemSize, attribute.normalized );
48163
48164			}
48165
48166			if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name;
48167			if ( attribute.usage !== undefined ) bufferAttribute.setUsage( attribute.usage );
48168
48169			geometry.setAttribute( key, bufferAttribute );
48170
48171		}
48172
48173		const morphAttributes = json.data.morphAttributes;
48174
48175		if ( morphAttributes ) {
48176
48177			for ( const key in morphAttributes ) {
48178
48179				const attributeArray = morphAttributes[ key ];
48180
48181				const array = [];
48182
48183				for ( let i = 0, il = attributeArray.length; i < il; i ++ ) {
48184
48185					const attribute = attributeArray[ i ];
48186					let bufferAttribute;
48187
48188					if ( attribute.isInterleavedBufferAttribute ) {
48189
48190						const interleavedBuffer = getInterleavedBuffer( json.data, attribute.data );
48191						bufferAttribute = new InterleavedBufferAttribute( interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized );
48192
48193					} else {
48194
48195						const typedArray = getTypedArray( attribute.type, attribute.array );
48196						bufferAttribute = new BufferAttribute( typedArray, attribute.itemSize, attribute.normalized );
48197
48198					}
48199
48200					if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name;
48201					array.push( bufferAttribute );
48202
48203				}
48204
48205				geometry.morphAttributes[ key ] = array;
48206
48207			}
48208
48209		}
48210
48211		const morphTargetsRelative = json.data.morphTargetsRelative;
48212
48213		if ( morphTargetsRelative ) {
48214
48215			geometry.morphTargetsRelative = true;
48216
48217		}
48218
48219		const groups = json.data.groups || json.data.drawcalls || json.data.offsets;
48220
48221		if ( groups !== undefined ) {
48222
48223			for ( let i = 0, n = groups.length; i !== n; ++ i ) {
48224
48225				const group = groups[ i ];
48226
48227				geometry.addGroup( group.start, group.count, group.materialIndex );
48228
48229			}
48230
48231		}
48232
48233		const boundingSphere = json.data.boundingSphere;
48234
48235		if ( boundingSphere !== undefined ) {
48236
48237			geometry.boundingSphere = new Sphere().fromJSON( boundingSphere );
48238
48239		}
48240
48241		if ( json.name ) geometry.name = json.name;
48242		if ( json.userData ) geometry.userData = json.userData;
48243
48244		return geometry;
48245
48246	}
48247
48248}
48249
48250const _customGeometries = {};
48251
48252/**
48253 * 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).
48254 * The files are internally loaded via {@link FileLoader}.
48255 *
48256 * ```js
48257 * const loader = new THREE.ObjectLoader();
48258 * const obj = await loader.loadAsync( 'models/json/example.json' );
48259 * scene.add( obj );
48260 *
48261 * // Alternatively, to parse a previously loaded JSON structure
48262 * const object = await loader.parseAsync( a_json_object );
48263 * scene.add( object );
48264 * ```
48265 *
48266 * @augments Loader
48267 */
48268class ObjectLoader extends Loader {
48269
48270	/**
48271	 * Constructs a new object loader.
48272	 *
48273	 * @param {LoadingManager} [manager] - The loading manager.
48274	 */
48275	constructor( manager ) {
48276
48277		super( manager );
48278
48279	}
48280
vendor: 4,038 bytes, lines 48281-48434
48281	/**
48282	 * Starts loading from the given URL and pass the loaded 3D object to the `onLoad()` callback.
48283	 *
48284	 * @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
48285	 * @param {function(Object3D)} onLoad - Executed when the loading process has been finished.
48286	 * @param {onProgressCallback} onProgress - Executed while the loading is in progress.
48287	 * @param {onErrorCallback} onError - Executed when errors occur.
48288	 */
48289	load( url, onLoad, onProgress, onError ) {
48290
48291		const scope = this;
48292
48293		const path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path;
48294		this.resourcePath = this.resourcePath || path;
48295
48296		const loader = new FileLoader( this.manager );
48297		loader.setPath( this.path );
48298		loader.setRequestHeader( this.requestHeader );
48299		loader.setWithCredentials( this.withCredentials );
48300		loader.load( url, function ( text ) {
48301
48302			let json = null;
48303
48304			try {
48305
48306				json = JSON.parse( text );
48307
48308			} catch ( e ) {
48309
48310				if ( onError !== undefined ) onError( e );
48311
48312				error( 'ObjectLoader: Can\'t parse ' + url + '.', e.message );
48313
48314				return;
48315
48316			}
48317
48318			const metadata = json.metadata;
48319
48320			if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) {
48321
48322				if ( onError !== undefined ) onError( new Error( 'THREE.ObjectLoader: Can\'t load ' + url ) );
48323
48324				error( 'ObjectLoader: Can\'t load ' + url );
48325				return;
48326
48327			}
48328
48329			scope.parse( json, onLoad );
48330
48331		}, onProgress, onError );
48332
48333	}
48334
48335	/**
48336	 * Async version of {@link ObjectLoader#load}.
48337	 *
48338	 * @async
48339	 * @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
48340	 * @param {onProgressCallback} onProgress - Executed while the loading is in progress.
48341	 * @return {Promise<Object3D>} A Promise that resolves with the loaded 3D object.
48342	 */
48343	async loadAsync( url, onProgress ) {
48344
48345		const scope = this;
48346
48347		const path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path;
48348		this.resourcePath = this.resourcePath || path;
48349
48350		const loader = new FileLoader( this.manager );
48351		loader.setPath( this.path );
48352		loader.setRequestHeader( this.requestHeader );
48353		loader.setWithCredentials( this.withCredentials );
48354
48355		const text = await loader.loadAsync( url, onProgress );
48356
48357		let json;
48358
48359		try {
48360
48361			json = JSON.parse( text );
48362
48363		} catch ( e ) {
48364
48365			throw new Error( 'ObjectLoader: Can\'t parse ' + url + '. ' + e.message );
48366
48367		}
48368
48369		const metadata = json.metadata;
48370
48371		if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) {
48372
48373			throw new Error( 'THREE.ObjectLoader: Can\'t load ' + url );
48374
48375		}
48376
48377		return await scope.parseAsync( json );
48378
48379	}
48380
48381	/**
48382	 * Parses the given JSON. This is used internally by {@link ObjectLoader#load}
48383	 * but can also be used directly to parse a previously loaded JSON structure.
48384	 *
48385	 * @param {Object} json - The serialized 3D object.
48386	 * @param {onLoad} onLoad - Executed when all resources (e.g. textures) have been fully loaded.
48387	 * @return {Object3D} The parsed 3D object.
48388	 */
48389	parse( json, onLoad ) {
48390
48391		const animations = this.parseAnimations( json.animations );
48392		const shapes = this.parseShapes( json.shapes );
48393		const geometries = this.parseGeometries( json.geometries, shapes );
48394
48395		const images = this.parseImages( json.images, function () {
48396
48397			if ( onLoad !== undefined ) onLoad( object );
48398
48399		} );
48400
48401		const textures = this.parseTextures( json.textures, images );
48402		const materials = this.parseMaterials( json.materials, textures );
48403
48404		const object = this.parseObject( json.object, geometries, materials, textures, animations );
48405		const skeletons = this.parseSkeletons( json.skeletons, object );
48406
48407		this.bindSkeletons( object, skeletons );
48408		this.bindLightTargets( object );
48409
48410		//
48411
48412		if ( onLoad !== undefined ) {
48413
48414			let hasImages = false;
48415
48416			for ( const uuid in images ) {
48417
48418				if ( images[ uuid ].data instanceof HTMLImageElement ) {
48419
48420					hasImages = true;
48421					break;
48422
48423				}
48424
48425			}
48426
48427			if ( hasImages === false ) onLoad( object );
48428
48429		}
48430
48431		return object;
48432
48433	}
48434
vendor: 7,474 bytes, lines 48435-48835
48435	/**
48436	 * Async version of {@link ObjectLoader#parse}.
48437	 *
48438	 * @param {Object} json - The serialized 3D object.
48439	 * @return {Promise<Object3D>} A Promise that resolves with the parsed 3D object.
48440	 */
48441	async parseAsync( json ) {
48442
48443		const animations = this.parseAnimations( json.animations );
48444		const shapes = this.parseShapes( json.shapes );
48445		const geometries = this.parseGeometries( json.geometries, shapes );
48446
48447		const images = await this.parseImagesAsync( json.images );
48448
48449		const textures = this.parseTextures( json.textures, images );
48450		const materials = this.parseMaterials( json.materials, textures );
48451
48452		const object = this.parseObject( json.object, geometries, materials, textures, animations );
48453		const skeletons = this.parseSkeletons( json.skeletons, object );
48454
48455		this.bindSkeletons( object, skeletons );
48456		this.bindLightTargets( object );
48457
48458		return object;
48459
48460	}
48461
48462	/**
48463	 * Registers the given geometry at the internal
48464	 * geometry library.
48465	 *
48466	 * @static
48467	 * @param {string} type - The geometry type.
48468	 * @param {BufferGeometry.constructor} geometryClass - The geometry class.
48469	 */
48470	static registerGeometry( type, geometryClass ) {
48471
48472		_customGeometries[ type ] = geometryClass;
48473
48474	}
48475
48476	// internals
48477
48478	parseShapes( json ) {
48479
48480		const shapes = {};
48481
48482		if ( json !== undefined ) {
48483
48484			for ( let i = 0, l = json.length; i < l; i ++ ) {
48485
48486				const shape = new Shape().fromJSON( json[ i ] );
48487
48488				shapes[ shape.uuid ] = shape;
48489
48490			}
48491
48492		}
48493
48494		return shapes;
48495
48496	}
48497
48498	parseSkeletons( json, object ) {
48499
48500		const skeletons = {};
48501		const bones = {};
48502
48503		// generate bone lookup table
48504
48505		object.traverse( function ( child ) {
48506
48507			if ( child.isBone ) bones[ child.uuid ] = child;
48508
48509		} );
48510
48511		// create skeletons
48512
48513		if ( json !== undefined ) {
48514
48515			for ( let i = 0, l = json.length; i < l; i ++ ) {
48516
48517				const skeleton = new Skeleton().fromJSON( json[ i ], bones );
48518
48519				skeletons[ skeleton.uuid ] = skeleton;
48520
48521			}
48522
48523		}
48524
48525		return skeletons;
48526
48527	}
48528
48529	parseGeometries( json, shapes ) {
48530
48531		const geometries = {};
48532
48533		if ( json !== undefined ) {
48534
48535			const bufferGeometryLoader = new BufferGeometryLoader();
48536
48537			for ( let i = 0, l = json.length; i < l; i ++ ) {
48538
48539				let geometry;
48540				const data = json[ i ];
48541
48542				switch ( data.type ) {
48543
48544					case 'BufferGeometry':
48545					case 'InstancedBufferGeometry':
48546
48547						geometry = bufferGeometryLoader.parse( data );
48548						break;
48549
48550					default:
48551
48552						if ( data.type in Geometries ) {
48553
48554							geometry = Geometries[ data.type ].fromJSON( data, shapes );
48555
48556						} else if ( data.type in _customGeometries ) {
48557
48558							geometry = _customGeometries[ data.type ].fromJSON( data, shapes );
48559
48560						} else {
48561
48562							warn( `ObjectLoader: Unknown geometry type "${ data.type }". Use .registerGeometry() before starting the deserialization process.` );
48563
48564						}
48565
48566				}
48567
48568				geometry.uuid = data.uuid;
48569
48570				if ( data.name !== undefined ) geometry.name = data.name;
48571				if ( data.userData !== undefined ) geometry.userData = data.userData;
48572
48573				geometries[ data.uuid ] = geometry;
48574
48575			}
48576
48577		}
48578
48579		return geometries;
48580
48581	}
48582
48583	parseMaterials( json, textures ) {
48584
48585		const cache = {}; // MultiMaterial
48586		const materials = {};
48587
48588		if ( json !== undefined ) {
48589
48590			const loader = new MaterialLoader();
48591			loader.setTextures( textures );
48592
48593			for ( let i = 0, l = json.length; i < l; i ++ ) {
48594
48595				const data = json[ i ];
48596
48597				if ( cache[ data.uuid ] === undefined ) {
48598
48599					cache[ data.uuid ] = loader.parse( data );
48600
48601				}
48602
48603				materials[ data.uuid ] = cache[ data.uuid ];
48604
48605			}
48606
48607		}
48608
48609		return materials;
48610
48611	}
48612
48613	parseAnimations( json ) {
48614
48615		const animations = {};
48616
48617		if ( json !== undefined ) {
48618
48619			for ( let i = 0; i < json.length; i ++ ) {
48620
48621				const data = json[ i ];
48622
48623				const clip = AnimationClip.parse( data );
48624
48625				animations[ clip.uuid ] = clip;
48626
48627			}
48628
48629		}
48630
48631		return animations;
48632
48633	}
48634
48635	parseImages( json, onLoad ) {
48636
48637		const scope = this;
48638		const images = {};
48639
48640		let loader;
48641
48642		function loadImage( url ) {
48643
48644			scope.manager.itemStart( url );
48645
48646			return loader.load( url, function () {
48647
48648				scope.manager.itemEnd( url );
48649
48650			}, undefined, function () {
48651
48652				scope.manager.itemError( url );
48653				scope.manager.itemEnd( url );
48654
48655			} );
48656
48657		}
48658
48659		function deserializeImage( image ) {
48660
48661			if ( typeof image === 'string' ) {
48662
48663				const url = image;
48664
48665				const path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( url ) ? url : scope.resourcePath + url;
48666
48667				return loadImage( path );
48668
48669			} else {
48670
48671				if ( image.data ) {
48672
48673					return {
48674						data: getTypedArray( image.type, image.data ),
48675						width: image.width,
48676						height: image.height
48677					};
48678
48679				} else {
48680
48681					return null;
48682
48683				}
48684
48685			}
48686
48687		}
48688
48689		if ( json !== undefined && json.length > 0 ) {
48690
48691			const manager = new LoadingManager( onLoad );
48692
48693			loader = new ImageLoader( manager );
48694			loader.setCrossOrigin( this.crossOrigin );
48695
48696			for ( let i = 0, il = json.length; i < il; i ++ ) {
48697
48698				const image = json[ i ];
48699				const url = image.url;
48700
48701				if ( Array.isArray( url ) ) {
48702
48703					// load array of images e.g CubeTexture
48704
48705					const imageArray = [];
48706
48707					for ( let j = 0, jl = url.length; j < jl; j ++ ) {
48708
48709						const currentUrl = url[ j ];
48710
48711						const deserializedImage = deserializeImage( currentUrl );
48712
48713						if ( deserializedImage !== null ) {
48714
48715							if ( deserializedImage instanceof HTMLImageElement ) {
48716
48717								imageArray.push( deserializedImage );
48718
48719							} else {
48720
48721								// special case: handle array of data textures for cube textures
48722
48723								imageArray.push( new DataTexture( deserializedImage.data, deserializedImage.width, deserializedImage.height ) );
48724
48725							}
48726
48727						}
48728
48729					}
48730
48731					images[ image.uuid ] = new Source( imageArray );
48732
48733				} else {
48734
48735					// load single image
48736
48737					const deserializedImage = deserializeImage( image.url );
48738					images[ image.uuid ] = new Source( deserializedImage );
48739
48740
48741				}
48742
48743			}
48744
48745		}
48746
48747		return images;
48748
48749	}
48750
48751	async parseImagesAsync( json ) {
48752
48753		const scope = this;
48754		const images = {};
48755
48756		let loader;
48757
48758		async function deserializeImage( image ) {
48759
48760			if ( typeof image === 'string' ) {
48761
48762				const url = image;
48763
48764				const path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( url ) ? url : scope.resourcePath + url;
48765
48766				return await loader.loadAsync( path );
48767
48768			} else {
48769
48770				if ( image.data ) {
48771
48772					return {
48773						data: getTypedArray( image.type, image.data ),
48774						width: image.width,
48775						height: image.height
48776					};
48777
48778				} else {
48779
48780					return null;
48781
48782				}
48783
48784			}
48785
48786		}
48787
48788		if ( json !== undefined && json.length > 0 ) {
48789
48790			loader = new ImageLoader( this.manager );
48791			loader.setCrossOrigin( this.crossOrigin );
48792
48793			for ( let i = 0, il = json.length; i < il; i ++ ) {
48794
48795				const image = json[ i ];
48796				const url = image.url;
48797
48798				if ( Array.isArray( url ) ) {
48799
48800					// load array of images e.g CubeTexture
48801
48802					const imageArray = [];
48803
48804					for ( let j = 0, jl = url.length; j < jl; j ++ ) {
48805
48806						const currentUrl = url[ j ];
48807
48808						const deserializedImage = await deserializeImage( currentUrl );
48809
48810						if ( deserializedImage !== null ) {
48811
48812							if ( deserializedImage instanceof HTMLImageElement ) {
48813
48814								imageArray.push( deserializedImage );
48815
48816							} else {
48817
48818								// special case: handle array of data textures for cube textures
48819
48820								imageArray.push( new DataTexture( deserializedImage.data, deserializedImage.width, deserializedImage.height ) );
48821
48822							}
48823
48824						}
48825
48826					}
48827
48828					images[ image.uuid ] = new Source( imageArray );
48829
48830				} else {
48831
48832					// load single image
48833
48834					const deserializedImage = await deserializeImage( image.url );
48835					images[ image.uuid ] = new 
vendor: 12,909 bytes, lines 48835-49345
48835Source( deserializedImage );
48836
48837				}
48838
48839			}
48840
48841		}
48842
48843		return images;
48844
48845	}
48846
48847	parseTextures( json, images ) {
48848
48849		function parseConstant( value, type ) {
48850
48851			if ( typeof value === 'number' ) return value;
48852
48853			warn( 'ObjectLoader.parseTexture: Constant should be in numeric form.', value );
48854
48855			return type[ value ];
48856
48857		}
48858
48859		const textures = {};
48860
48861		if ( json !== undefined ) {
48862
48863			for ( let i = 0, l = json.length; i < l; i ++ ) {
48864
48865				const data = json[ i ];
48866
48867				if ( data.image === undefined ) {
48868
48869					warn( 'ObjectLoader: No "image" specified for', data.uuid );
48870
48871				}
48872
48873				if ( images[ data.image ] === undefined ) {
48874
48875					warn( 'ObjectLoader: Undefined image', data.image );
48876
48877				}
48878
48879				const source = images[ data.image ];
48880				const image = source.data;
48881
48882				let texture;
48883
48884				if ( Array.isArray( image ) ) {
48885
48886					texture = new CubeTexture();
48887
48888					if ( image.length === 6 ) texture.needsUpdate = true;
48889
48890				} else {
48891
48892					if ( image && image.data ) {
48893
48894						texture = new DataTexture();
48895
48896					} else {
48897
48898						texture = new Texture();
48899
48900					}
48901
48902					if ( image ) texture.needsUpdate = true; // textures can have undefined image data
48903
48904				}
48905
48906				texture.source = source;
48907
48908				texture.uuid = data.uuid;
48909
48910				if ( data.name !== undefined ) texture.name = data.name;
48911
48912				if ( data.mapping !== undefined ) texture.mapping = parseConstant( data.mapping, TEXTURE_MAPPING );
48913				if ( data.channel !== undefined ) texture.channel = data.channel;
48914
48915				if ( data.offset !== undefined ) texture.offset.fromArray( data.offset );
48916				if ( data.repeat !== undefined ) texture.repeat.fromArray( data.repeat );
48917				if ( data.center !== undefined ) texture.center.fromArray( data.center );
48918				if ( data.rotation !== undefined ) texture.rotation = data.rotation;
48919
48920				if ( data.wrap !== undefined ) {
48921
48922					texture.wrapS = parseConstant( data.wrap[ 0 ], TEXTURE_WRAPPING );
48923					texture.wrapT = parseConstant( data.wrap[ 1 ], TEXTURE_WRAPPING );
48924
48925				}
48926
48927				if ( data.format !== undefined ) texture.format = data.format;
48928				if ( data.internalFormat !== undefined ) texture.internalFormat = data.internalFormat;
48929				if ( data.type !== undefined ) texture.type = data.type;
48930				if ( data.colorSpace !== undefined ) texture.colorSpace = data.colorSpace;
48931
48932				if ( data.minFilter !== undefined ) texture.minFilter = parseConstant( data.minFilter, TEXTURE_FILTER );
48933				if ( data.magFilter !== undefined ) texture.magFilter = parseConstant( data.magFilter, TEXTURE_FILTER );
48934				if ( data.anisotropy !== undefined ) texture.anisotropy = data.anisotropy;
48935
48936				if ( data.flipY !== undefined ) texture.flipY = data.flipY;
48937
48938				if ( data.generateMipmaps !== undefined ) texture.generateMipmaps = data.generateMipmaps;
48939				if ( data.premultiplyAlpha !== undefined ) texture.premultiplyAlpha = data.premultiplyAlpha;
48940				if ( data.unpackAlignment !== undefined ) texture.unpackAlignment = data.unpackAlignment;
48941				if ( data.compareFunction !== undefined ) texture.compareFunction = data.compareFunction;
48942				if ( data.normalized !== undefined ) texture.normalized = data.normalized;
48943
48944				if ( data.userData !== undefined ) texture.userData = data.userData;
48945
48946				textures[ data.uuid ] = texture;
48947
48948			}
48949
48950		}
48951
48952		return textures;
48953
48954	}
48955
48956	parseObject( data, geometries, materials, textures, animations ) {
48957
48958		let object;
48959
48960		function getGeometry( name ) {
48961
48962			if ( geometries[ name ] === undefined ) {
48963
48964				warn( 'ObjectLoader: Undefined geometry', name );
48965
48966			}
48967
48968			return geometries[ name ];
48969
48970		}
48971
48972		function getMaterial( name ) {
48973
48974			if ( name === undefined ) return undefined;
48975
48976			if ( Array.isArray( name ) ) {
48977
48978				const array = [];
48979
48980				for ( let i = 0, l = name.length; i < l; i ++ ) {
48981
48982					const uuid = name[ i ];
48983
48984					if ( materials[ uuid ] === undefined ) {
48985
48986						warn( 'ObjectLoader: Undefined material', uuid );
48987
48988					}
48989
48990					array.push( materials[ uuid ] );
48991
48992				}
48993
48994				return array;
48995
48996			}
48997
48998			if ( materials[ name ] === undefined ) {
48999
49000				warn( 'ObjectLoader: Undefined material', name );
49001
49002			}
49003
49004			return materials[ name ];
49005
49006		}
49007
49008		function getTexture( uuid ) {
49009
49010			if ( textures[ uuid ] === undefined ) {
49011
49012				warn( 'ObjectLoader: Undefined texture', uuid );
49013
49014			}
49015
49016			return textures[ uuid ];
49017
49018		}
49019
49020		let geometry, material;
49021
49022		switch ( data.type ) {
49023
49024			case 'Scene':
49025
49026				object = new Scene();
49027
49028				if ( data.background !== undefined ) {
49029
49030					if ( Number.isInteger( data.background ) ) {
49031
49032						object.background = new Color( data.background );
49033
49034					} else {
49035
49036						object.background = getTexture( data.background );
49037
49038					}
49039
49040				}
49041
49042				if ( data.environment !== undefined ) {
49043
49044					object.environment = getTexture( data.environment );
49045
49046				}
49047
49048				if ( data.fog !== undefined ) {
49049
49050					if ( data.fog.type === 'Fog' ) {
49051
49052						object.fog = new Fog( data.fog.color, data.fog.near, data.fog.far );
49053
49054					} else if ( data.fog.type === 'FogExp2' ) {
49055
49056						object.fog = new FogExp2( data.fog.color, data.fog.density );
49057
49058					}
49059
49060					if ( data.fog.name !== '' ) {
49061
49062						object.fog.name = data.fog.name;
49063
49064					}
49065
49066				}
49067
49068				if ( data.backgroundBlurriness !== undefined ) object.backgroundBlurriness = data.backgroundBlurriness;
49069				if ( data.backgroundIntensity !== undefined ) object.backgroundIntensity = data.backgroundIntensity;
49070				if ( data.backgroundRotation !== undefined ) object.backgroundRotation.fromArray( data.backgroundRotation );
49071
49072				if ( data.environmentIntensity !== undefined ) object.environmentIntensity = data.environmentIntensity;
49073				if ( data.environmentRotation !== undefined ) object.environmentRotation.fromArray( data.environmentRotation );
49074
49075				break;
49076
49077			case 'PerspectiveCamera':
49078
49079				object = new PerspectiveCamera( data.fov, data.aspect, data.near, data.far );
49080
49081				if ( data.focus !== undefined ) object.focus = data.focus;
49082				if ( data.zoom !== undefined ) object.zoom = data.zoom;
49083				if ( data.filmGauge !== undefined ) object.filmGauge = data.filmGauge;
49084				if ( data.filmOffset !== undefined ) object.filmOffset = data.filmOffset;
49085				if ( data.view !== undefined ) object.view = Object.assign( {}, data.view );
49086
49087				break;
49088
49089			case 'OrthographicCamera':
49090
49091				object = new OrthographicCamera( data.left, data.right, data.top, data.bottom, data.near, data.far );
49092
49093				if ( data.zoom !== undefined ) object.zoom = data.zoom;
49094				if ( data.view !== undefined ) object.view = Object.assign( {}, data.view );
49095
49096				break;
49097
49098			case 'AmbientLight':
49099
49100				object = new AmbientLight( data.color, data.intensity );
49101
49102				break;
49103
49104			case 'DirectionalLight':
49105
49106				object = new DirectionalLight( data.color, data.intensity );
49107				object.target = data.target || '';
49108
49109				break;
49110
49111			case 'PointLight':
49112
49113				object = new PointLight( data.color, data.intensity, data.distance, data.decay );
49114
49115				break;
49116
49117			case 'RectAreaLight':
49118
49119				object = new RectAreaLight( data.color, data.intensity, data.width, data.height );
49120
49121				break;
49122
49123			case 'SpotLight':
49124
49125				object = new SpotLight( data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay );
49126				object.target = data.target || '';
49127
49128				break;
49129
49130			case 'HemisphereLight':
49131
49132				object = new HemisphereLight( data.color, data.groundColor, data.intensity );
49133
49134				break;
49135
49136			case 'LightProbe':
49137
49138				const sh = new SphericalHarmonics3().fromArray( data.sh );
49139				object = new LightProbe( sh, data.intensity );
49140
49141				break;
49142
49143			case 'SkinnedMesh':
49144
49145				geometry = getGeometry( data.geometry );
49146			 	material = getMaterial( data.material );
49147
49148				object = new SkinnedMesh( geometry, material );
49149
49150				if ( data.bindMode !== undefined ) object.bindMode = data.bindMode;
49151				if ( data.bindMatrix !== undefined ) object.bindMatrix.fromArray( data.bindMatrix );
49152				if ( data.skeleton !== undefined ) object.skeleton = data.skeleton;
49153
49154				break;
49155
49156			case 'Mesh':
49157
49158				geometry = getGeometry( data.geometry );
49159				material = getMaterial( data.material );
49160
49161				object = new Mesh( geometry, material );
49162
49163				break;
49164
49165			case 'InstancedMesh':
49166
49167				geometry = getGeometry( data.geometry );
49168				material = getMaterial( data.material );
49169				const count = data.count;
49170				const instanceMatrix = data.instanceMatrix;
49171				const instanceColor = data.instanceColor;
49172
49173				object = new InstancedMesh( geometry, material, count );
49174				object.instanceMatrix = new InstancedBufferAttribute( new Float32Array( instanceMatrix.array ), 16 );
49175				if ( instanceColor !== undefined ) object.instanceColor = new InstancedBufferAttribute( new Float32Array( instanceColor.array ), instanceColor.itemSize );
49176
49177				break;
49178
49179			case 'BatchedMesh':
49180
49181				geometry = getGeometry( data.geometry );
49182				material = getMaterial( data.material );
49183
49184				object = new BatchedMesh( data.maxInstanceCount, data.maxVertexCount, data.maxIndexCount, material );
49185				object.geometry = geometry;
49186				object.perObjectFrustumCulled = data.perObjectFrustumCulled;
49187				object.sortObjects = data.sortObjects;
49188
49189				object._drawRanges = data.drawRanges;
49190				object._reservedRanges = data.reservedRanges;
49191
49192				object._geometryInfo = data.geometryInfo.map( info => {
49193
49194					let box = null;
49195					let sphere = null;
49196					if ( info.boundingBox !== undefined ) {
49197
49198						box = new Box3().fromJSON( info.boundingBox );
49199
49200					}
49201
49202					if ( info.boundingSphere !== undefined ) {
49203
49204						sphere = new Sphere().fromJSON( info.boundingSphere );
49205
49206					}
49207
49208					return {
49209						...info,
49210						boundingBox: box,
49211						boundingSphere: sphere
49212					};
49213
49214				} );
49215				object._instanceInfo = data.instanceInfo;
49216
49217				object._availableInstanceIds = data._availableInstanceIds;
49218				object._availableGeometryIds = data._availableGeometryIds;
49219
49220				object._nextIndexStart = data.nextIndexStart;
49221				object._nextVertexStart = data.nextVertexStart;
49222				object._geometryCount = data.geometryCount;
49223
49224				object._maxInstanceCount = data.maxInstanceCount;
49225				object._maxVertexCount = data.maxVertexCount;
49226				object._maxIndexCount = data.maxIndexCount;
49227
49228				object._geometryInitialized = data.geometryInitialized;
49229
49230				object._matricesTexture = getTexture( data.matricesTexture.uuid );
49231
49232				object._indirectTexture = getTexture( data.indirectTexture.uuid );
49233
49234				if ( data.colorsTexture !== undefined ) {
49235
49236					object._colorsTexture = getTexture( data.colorsTexture.uuid );
49237
49238				}
49239
49240				if ( data.boundingSphere !== undefined ) {
49241
49242					object.boundingSphere = new Sphere().fromJSON( data.boundingSphere );
49243
49244				}
49245
49246				if ( data.boundingBox !== undefined ) {
49247
49248					object.boundingBox = new Box3().fromJSON( data.boundingBox );
49249
49250				}
49251
49252				break;
49253
49254			case 'LOD':
49255
49256				object = new LOD();
49257
49258				break;
49259
49260			case 'Line':
49261
49262				object = new Line( getGeometry( data.geometry ), getMaterial( data.material ) );
49263
49264				break;
49265
49266			case 'LineLoop':
49267
49268				object = new LineLoop( getGeometry( data.geometry ), getMaterial( data.material ) );
49269
49270				break;
49271
49272			case 'LineSegments':
49273
49274				object = new LineSegments( getGeometry( data.geometry ), getMaterial( data.material ) );
49275
49276				break;
49277
49278			case 'PointCloud':
49279			case 'Points':
49280
49281				object = new Points( getGeometry( data.geometry ), getMaterial( data.material ) );
49282
49283				break;
49284
49285			case 'Sprite':
49286
49287				object = new Sprite( getMaterial( data.material ) );
49288
49289				break;
49290
49291			case 'Group':
49292
49293				object = new Group();
49294
49295				break;
49296
49297			case 'Bone':
49298
49299				object = new Bone();
49300
49301				break;
49302
49303			default:
49304
49305				object = new Object3D();
49306
49307		}
49308
49309		object.uuid = data.uuid;
49310
49311		if ( data.name !== undefined ) object.name = data.name;
49312
49313		if ( data.matrix !== undefined ) {
49314
49315			object.matrix.fromArray( data.matrix );
49316
49317			if ( data.matrixAutoUpdate !== undefined ) object.matrixAutoUpdate = data.matrixAutoUpdate;
49318			if ( object.matrixAutoUpdate ) object.matrix.decompose( object.position, object.quaternion, object.scale );
49319
49320		} else {
49321
49322			if ( data.position !== undefined ) object.position.fromArray( data.position );
49323			if ( data.rotation !== undefined ) object.rotation.fromArray( data.rotation );
49324			if ( data.quaternion !== undefined ) object.quaternion.fromArray( data.quaternion );
49325			if ( data.scale !== undefined ) object.scale.fromArray( data.scale );
49326
49327		}
49328
49329		if ( data.up !== undefined ) object.up.fromArray( data.up );
49330
49331		if ( data.pivot !== undefined ) object.pivot = new Vector3().fromArray( data.pivot );
49332
49333		if ( data.morphTargetDictionary !== undefined ) object.morphTargetDictionary = Object.assign( {}, data.morphTargetDictionary );
49334		if ( data.morphTargetInfluences !== undefined ) object.morphTargetInfluences = data.morphTargetInfluences.slice();
49335
49336		if ( data.castShadow !== undefined ) object.castShadow = data.castShadow;
49337		if ( data.receiveShadow !== undefined ) object.receiveShadow = data.receiveShadow;
49338
49339		if ( data.shadow ) {
49340
49341			if ( data.shadow.intensity !== undefined ) object.shadow.intensity = data.shadow.intensity;
49342			if ( data.shadow.bias !== undefined ) object.shadow.bias = data.shadow.bias;
49343			if ( data.shadow.normalBias !== undefined ) object.shadow.normalBias = data.shadow.normalBias;
49344			if ( data.shadow.radius !== undefined ) object.shadow.radius = data.shadow.radius;
49345			if ( data.shadow.
vendor: 3,445 bytes, lines 49345-49492
49345mapSize !== undefined ) object.shadow.mapSize.fromArray( data.shadow.mapSize );
49346			if ( data.shadow.camera !== undefined ) object.shadow.camera = this.parseObject( data.shadow.camera );
49347
49348		}
49349
49350		if ( data.visible !== undefined ) object.visible = data.visible;
49351		if ( data.frustumCulled !== undefined ) object.frustumCulled = data.frustumCulled;
49352		if ( data.renderOrder !== undefined ) object.renderOrder = data.renderOrder;
49353		if ( data.static !== undefined ) object.static = data.static;
49354		if ( data.userData !== undefined ) object.userData = data.userData;
49355		if ( data.layers !== undefined ) object.layers.mask = data.layers;
49356
49357		if ( data.children !== undefined ) {
49358
49359			const children = data.children;
49360
49361			for ( let i = 0; i < children.length; i ++ ) {
49362
49363				object.add( this.parseObject( children[ i ], geometries, materials, textures, animations ) );
49364
49365			}
49366
49367		}
49368
49369		if ( data.animations !== undefined ) {
49370
49371			const objectAnimations = data.animations;
49372
49373			for ( let i = 0; i < objectAnimations.length; i ++ ) {
49374
49375				const uuid = objectAnimations[ i ];
49376
49377				object.animations.push( animations[ uuid ] );
49378
49379			}
49380
49381		}
49382
49383		if ( data.type === 'LOD' ) {
49384
49385			if ( data.autoUpdate !== undefined ) object.autoUpdate = data.autoUpdate;
49386
49387			const levels = data.levels;
49388
49389			for ( let l = 0; l < levels.length; l ++ ) {
49390
49391				const level = levels[ l ];
49392				const child = object.getObjectByProperty( 'uuid', level.object );
49393
49394				if ( child !== undefined ) {
49395
49396					object.addLevel( child, level.distance, level.hysteresis );
49397
49398				}
49399
49400			}
49401
49402		}
49403
49404		return object;
49405
49406	}
49407
49408	bindSkeletons( object, skeletons ) {
49409
49410		if ( Object.keys( skeletons ).length === 0 ) return;
49411
49412		object.traverse( function ( child ) {
49413
49414			if ( child.isSkinnedMesh === true && child.skeleton !== undefined ) {
49415
49416				const skeleton = skeletons[ child.skeleton ];
49417
49418				if ( skeleton === undefined ) {
49419
49420					warn( 'ObjectLoader: No skeleton found with UUID:', child.skeleton );
49421
49422				} else {
49423
49424					child.bind( skeleton, child.bindMatrix );
49425
49426				}
49427
49428			}
49429
49430		} );
49431
49432	}
49433
49434	bindLightTargets( object ) {
49435
49436		object.traverse( function ( child ) {
49437
49438			if ( child.isDirectionalLight || child.isSpotLight ) {
49439
49440				const uuid = child.target;
49441
49442				const target = object.getObjectByProperty( 'uuid', uuid );
49443
49444				if ( target !== undefined ) {
49445
49446					child.target = target;
49447
49448				} else {
49449
49450					child.target = new Object3D();
49451
49452				}
49453
49454			}
49455
49456		} );
49457
49458	}
49459
49460}
49461
49462const TEXTURE_MAPPING = {
49463	UVMapping: UVMapping,
49464	CubeReflectionMapping: CubeReflectionMapping,
49465	CubeRefractionMapping: CubeRefractionMapping,
49466	EquirectangularReflectionMapping: EquirectangularReflectionMapping,
49467	EquirectangularRefractionMapping: EquirectangularRefractionMapping,
49468	CubeUVReflectionMapping: CubeUVReflectionMapping
49469};
49470
49471const TEXTURE_WRAPPING = {
49472	RepeatWrapping: RepeatWrapping,
49473	ClampToEdgeWrapping: ClampToEdgeWrapping,
49474	MirroredRepeatWrapping: MirroredRepeatWrapping
49475};
49476
49477const TEXTURE_FILTER = {
49478	NearestFilter: NearestFilter,
49479	NearestMipmapNearestFilter: NearestMipmapNearestFilter,
49480	NearestMipmapLinearFilter: NearestMipmapLinearFilter,
49481	LinearFilter: LinearFilter,
49482	LinearMipmapNearestFilter: LinearMipmapNearestFilter,
49483	LinearMipmapLinearFilter: LinearMipmapLinearFilter
49484};
49485
49486const _errorMap = new WeakMap();
49487
49488/**
49489 * A loader for loading images as an [ImageBitmap](https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap).
49490 * An `ImageBitmap` provides an asynchronous and resource efficient pathway to prepare
49491 * textures for rendering.
49492 *
49493 * Note that {@link Texture#flipY} and {@link Texture#premultiplyAlpha} are ignored with image bitmaps.
49494 * These options need to be configured via {@link ImageBitmapLoader#setOptions} prior to loading,
49495 * unlike regular images which can be configured on the Texture to set these options on GPU upload instead.
49496 *
49497 * To match the default behaviour of {@link Texture}, the following options are needed:
49498 *
49499 * ```js
49500 * { imageOrientation: 'flipY', premultiplyAlpha: 'none' }
49501 * ```
49502 *
49503 * Also note that unlike {@link FileLoader}, this loader will only avoid multiple concurrent requests to the same URL if {@link Cache} is enabled.
49504 *
49505 * ```js
49506 * const loader = new THREE.ImageBitmapLoader();
49507 * loader.setOptions( { imageOrientation: 'flipY' } ); // set options if needed
49508 * const imageBitmap = await loader.loadAsync( 'image.png' );
49509 *
49510 * const texture = new THREE.Texture( imageBitmap );
49511 * texture.needsUpdate = true;
49512 * ```
49513 *
49514 * @augments Loader
49515 */
49516class ImageBitmapLoader extends Loader {
49517
49518	/**
49519	 * Constructs a new image bitmap loader.
49520	 *
49521	 * @param {LoadingManager} [manager] - The loading manager.
49522	 */
49523	constructor( manager ) {
49524
49525		super( manager );
49526
49527		/**
49528		 * This flag can be used for type testing.
49529		 *
49530		 * @type {boolean}
49531		 * @readonly
49532		 * @default true
49533		 */
49534		this.isImageBitmapLoader = true;
49535
49536		if ( typeof createImageBitmap === 'undefined' ) {
49537
49538			warn( 'ImageBitmapLoader: createImageBitmap() not supported.' );
49539
49540		}
49541
49542		if ( typeof fetch === 'undefined' ) {
49543
49544			warn( 'ImageBitmapLoader: fetch() not supported.' );
49545
49546		}
49547
49548		/**
49549		 * Represents the loader options.
49550		 *
49551		 * @type {Object}
49552		 * @default {premultiplyAlpha:'none'}
49553		 */
49554		this.options = { premultiplyAlpha: 'none' };
49555
49556		/**
49557		 * Used for aborting requests.
49558		 *
49559		 * @private
49560		 * @type {AbortController}
49561		 */
49562		this._abortController = new AbortController();
49563
49564	}
49565
49566	/**
49567	 * Sets the given loader options. The structure of the object must match the `options` parameter of
49568	 * [createImageBitmap](https://developer.mozilla.org/en-US/docs/Web/API/Window/createImageBitmap).
49569	 *
49570	 * Note: When caching is enabled, the cache key is based on the URL only. Loading the same URL with
49571	 * different options will return the cached result of the first request.
49572	 *
49573	 * @param {Object} options - The loader options to set.
49574	 * @return {ImageBitmapLoader} A reference to this image bitmap loader.
49575	 */
49576	setOptions( options ) {
49577
49578		this.options = options;
49579
49580		return this;
49581
49582	}
49583
49584	/**
49585	 * Starts loading from the given URL and pass the loaded image bitmap to the `onLoad()` callback.
49586	 *
49587	 * @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
49588	 * @param {function(ImageBitmap)} onLoad - Executed when the loading process has been finished.
49589	 * @param {onProgressCallback} onProgress - Unsupported in this loader.
49590	 * @param {onErrorCallback} onError - Executed when errors occur.
49591	 */
49592	load( url, onLoad, onProgress, onError ) {
49593
49594		if ( url === undefined ) url = '';
49595
49596		if ( this.path !== undefined ) url = this.path + url;
49597
49598		url = this.manager.resolveURL( url );
49599
49600		const scope = this;
49601
49602		const cached = Cache.get( `image-bitmap:${url}` );
49603
49604		if ( cached !== undefined ) {
49605
49606			scope.manager.itemStart( url );
49607
49608			// If cached is a promise, wait for it to resolve
49609			if ( cached.then ) {
49610
49611				cached.then( imageBitmap => {
49612
49613					// check if there is an error for the cached promise
49614
49615					if ( _errorMap.has( cached ) === true ) {
49616
49617						if ( onError ) onError( _errorMap.get( cached ) );
49618
49619						scope.manager.itemError( url );
49620						scope.manager.itemEnd( url );
49621
49622					} else {
49623
49624						if ( onLoad ) onLoad( imageBitmap );
49625
49626						scope.manager.itemEnd( url );
49627
49628					}
49629
49630				} );
49631
49632				return;
49633
49634			}
49635
49636			// If cached is not a promise (i.e., it's already an imageBitmap)
49637			setTimeout( function () {
49638
49639				if ( onLoad ) onLoad( cached );
49640
49641				scope.manager.itemEnd( url );
49642
49643			}, 0 );
49644
49645			return;
49646
49647		}
49648
49649		const fetchOptions = {};
49650		fetchOptions.credentials = ( this.crossOrigin === 'anonymous' ) ? 'same-origin' : 'include';
49651		fetchOptions.headers = this.requestHeader;
49652		fetchOptions.signal = ( typeof AbortSignal.any === 'function' ) ? AbortSignal.any( [ this._abortController.signal, this.manager.abortController.signal ] ) : this._abortController.signal;
49653
49654		const promise = fetch( url, fetchOptions ).then( function ( res ) {
49655
49656			return res.blob();
49657
49658		} ).then( function ( blob ) {
49659
49660			return createImageBitmap( blob, Object.assign( scope.options, { colorSpaceConversion: 'none' } ) );
49661
49662		} ).then( function ( imageBitmap ) {
49663
49664			Cache.add( `image-bitmap:${url}`, imageBitmap );
49665
49666			if ( onLoad ) onLoad( imageBitmap );
49667
49668			scope.manager.itemEnd( url );
vendor: 7,062 bytes, lines 49668-49978
49668
49669
49670		} ).catch( function ( e ) {
49671
49672			if ( onError ) onError( e );
49673
49674			_errorMap.set( promise, e );
49675
49676			Cache.remove( `image-bitmap:${url}` );
49677
49678			scope.manager.itemError( url );
49679			scope.manager.itemEnd( url );
49680
49681		} );
49682
49683		Cache.add( `image-bitmap:${url}`, promise );
49684		scope.manager.itemStart( url );
49685
49686	}
49687
49688	/**
49689	 * Aborts ongoing fetch requests.
49690	 *
49691	 * @return {ImageBitmapLoader} A reference to this instance.
49692	 */
49693	abort() {
49694
49695		this._abortController.abort();
49696		this._abortController = new AbortController();
49697
49698		return this;
49699
49700	}
49701
49702}
49703
49704let _context;
49705
49706/**
49707 * Manages the global audio context in the engine.
49708 *
49709 * @hideconstructor
49710 */
49711class AudioContext {
49712
49713	/**
49714	 * Returns the global native audio context.
49715	 *
49716	 * @return {Window.AudioContext} The native audio context.
49717	 */
49718	static getContext() {
49719
49720		if ( _context === undefined ) {
49721
49722			_context = new ( window.AudioContext || window.webkitAudioContext )();
49723
49724		}
49725
49726		return _context;
49727
49728	}
49729
49730	/**
49731	 * Allows to set the global native audio context from outside.
49732	 *
49733	 * @param {Window.AudioContext} value - The native context to set.
49734	 */
49735	static setContext( value ) {
49736
49737		_context = value;
49738
49739	}
49740
49741}
49742
49743/**
49744 * Class for loading audio buffers. Audios are internally
49745 * loaded via {@link FileLoader}.
49746 *
49747 * ```js
49748 * const audioListener = new THREE.AudioListener();
49749 * const ambientSound = new THREE.Audio( audioListener );
49750 *
49751 * const loader = new THREE.AudioLoader();
49752 * const audioBuffer = await loader.loadAsync( 'audio/ambient_ocean.ogg' );
49753 *
49754 * ambientSound.setBuffer( audioBuffer );
49755 * ambientSound.play();
49756 * ```
49757 *
49758 * @augments Loader
49759 */
49760class AudioLoader extends Loader {
49761
49762	/**
49763	 * Constructs a new audio loader.
49764	 *
49765	 * @param {LoadingManager} [manager] - The loading manager.
49766	 */
49767	constructor( manager ) {
49768
49769		super( manager );
49770
49771	}
49772
49773	/**
49774	 * Starts loading from the given URL and passes the loaded audio buffer
49775	 * to the `onLoad()` callback.
49776	 *
49777	 * @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
49778	 * @param {function(AudioBuffer)} onLoad - Executed when the loading process has been finished.
49779	 * @param {onProgressCallback} onProgress - Executed while the loading is in progress.
49780	 * @param {onErrorCallback} onError - Executed when errors occur.
49781	 */
49782	load( url, onLoad, onProgress, onError ) {
49783
49784		const scope = this;
49785
49786		const loader = new FileLoader( this.manager );
49787		loader.setResponseType( 'arraybuffer' );
49788		loader.setPath( this.path );
49789		loader.setRequestHeader( this.requestHeader );
49790		loader.setWithCredentials( this.withCredentials );
49791		loader.load( url, function ( buffer ) {
49792
49793			try {
49794
49795				// Create a copy of the buffer. The `decodeAudioData` method
49796				// detaches the buffer when complete, preventing reuse.
49797				const bufferCopy = buffer.slice( 0 );
49798
49799				const context = AudioContext.getContext();
49800
49801				const decodeUrl = url + '#decode';
49802				scope.manager.itemStart( decodeUrl ); // prevent loading manager from completing too early, see #33378
49803
49804				context.decodeAudioData( bufferCopy, function ( audioBuffer ) {
49805
49806					onLoad( audioBuffer );
49807					scope.manager.itemEnd( decodeUrl );
49808
49809				} ).catch( function ( e ) {
49810
49811					handleError( e );
49812					scope.manager.itemEnd( decodeUrl );
49813
49814				} );
49815
49816			} catch ( e ) {
49817
49818				handleError( e );
49819
49820			}
49821
49822		}, onProgress, onError );
49823
49824		function handleError( e ) {
49825
49826			if ( onError ) {
49827
49828				onError( e );
49829
49830			} else {
49831
49832				error( e );
49833
49834			}
49835
49836			scope.manager.itemError( url );
49837
49838		}
49839
49840	}
49841
49842}
49843
49844const _eyeRight = /*@__PURE__*/ new Matrix4();
49845const _eyeLeft = /*@__PURE__*/ new Matrix4();
49846const _projectionMatrix = /*@__PURE__*/ new Matrix4();
49847
49848/**
49849 * A special type of camera that uses two perspective cameras with
49850 * stereoscopic projection. Can be used for rendering stereo effects
49851 * like [3D Anaglyph](https://en.wikipedia.org/wiki/Anaglyph_3D) or
49852 * [Parallax Barrier](https://en.wikipedia.org/wiki/parallax_barrier).
49853 */
49854class StereoCamera {
49855
49856	/**
49857	 * Constructs a new stereo camera.
49858	 */
49859	constructor() {
49860
49861		/**
49862		 * The type property is used for detecting the object type
49863		 * in context of serialization/deserialization.
49864		 *
49865		 * @type {string}
49866		 * @readonly
49867		 */
49868		this.type = 'StereoCamera';
49869
49870		/**
49871		 * The aspect.
49872		 *
49873		 * @type {number}
49874		 * @default 1
49875		 */
49876		this.aspect = 1;
49877
49878		/**
49879		 * The eye separation which represents the distance
49880		 * between the left and right camera.
49881		 *
49882		 * @type {number}
49883		 * @default 0.064
49884		 */
49885		this.eyeSep = 0.064;
49886
49887		/**
49888		 * The camera representing the left eye. This is added to layer `1` so objects to be
49889		 * rendered by the left camera must also be added to this layer.
49890		 *
49891		 * @type {PerspectiveCamera}
49892		 */
49893		this.cameraL = new PerspectiveCamera();
49894		this.cameraL.layers.enable( 1 );
49895		this.cameraL.matrixAutoUpdate = false;
49896
49897		/**
49898		 * The camera representing the right eye. This is added to layer `2` so objects to be
49899		 * rendered by the right camera must also be added to this layer.
49900		 *
49901		 * @type {PerspectiveCamera}
49902		 */
49903		this.cameraR = new PerspectiveCamera();
49904		this.cameraR.layers.enable( 2 );
49905		this.cameraR.matrixAutoUpdate = false;
49906
49907		this._cache = {
49908			focus: null,
49909			fov: null,
49910			aspect: null,
49911			near: null,
49912			far: null,
49913			zoom: null,
49914			eyeSep: null
49915		};
49916
49917	}
49918
49919	/**
49920	 * Updates the stereo camera based on the given perspective camera.
49921	 *
49922	 * @param {PerspectiveCamera} camera - The perspective camera.
49923	 */
49924	update( camera ) {
49925
49926		const cache = this._cache;
49927
49928		const needsUpdate = cache.focus !== camera.focus || cache.fov !== camera.fov ||
49929			cache.aspect !== camera.aspect * this.aspect || cache.near !== camera.near ||
49930			cache.far !== camera.far || cache.zoom !== camera.zoom || cache.eyeSep !== this.eyeSep;
49931
49932		if ( needsUpdate ) {
49933
49934			cache.focus = camera.focus;
49935			cache.fov = camera.fov;
49936			cache.aspect = camera.aspect * this.aspect;
49937			cache.near = camera.near;
49938			cache.far = camera.far;
49939			cache.zoom = camera.zoom;
49940			cache.eyeSep = this.eyeSep;
49941
49942			// Off-axis stereoscopic effect based on
49943			// http://paulbourke.net/stereographics/stereorender/
49944
49945			_projectionMatrix.copy( camera.projectionMatrix );
49946			const eyeSepHalf = cache.eyeSep / 2;
49947			const eyeSepOnProjection = eyeSepHalf * cache.near / cache.focus;
49948			const ymax = ( cache.near * Math.tan( DEG2RAD * cache.fov * 0.5 ) ) / cache.zoom;
49949			let xmin, xmax;
49950
49951			// translate xOffset
49952
49953			_eyeLeft.elements[ 12 ] = - eyeSepHalf;
49954			_eyeRight.elements[ 12 ] = eyeSepHalf;
49955
49956			// for left eye
49957
49958			xmin = - ymax * cache.aspect + eyeSepOnProjection;
49959			xmax = ymax * cache.aspect + eyeSepOnProjection;
49960
49961			_projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin );
49962			_projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
49963
49964			this.cameraL.projectionMatrix.copy( _projectionMatrix );
49965
49966			// for right eye
49967
49968			xmin = - ymax * cache.aspect - eyeSepOnProjection;
49969			xmax = ymax * cache.aspect - eyeSepOnProjection;
49970
49971			_projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin );
49972			_projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
49973
49974			this.cameraR.projectionMatrix.copy( _projectionMatrix );
49975
49976		}
49977
49978		this.cameraL.matrix
49978World.copy( camera.matrixWorld ).multiply( _eyeLeft );
49979		this.cameraR.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeRight )
vendor: 51,290 bytes, lines 49979-52296
49979;
49980
49981	}
49982
49983}
49984
49985const fov = -90; // negative fov is not an error
49986const aspect = 1;
49987
49988/**
49989 * A special type of camera that is positioned in 3D space to render its surroundings into a
49990 * cube render target. The render target can then be used as an environment map for rendering
49991 * realtime reflections in your scene.
49992 *
49993 * ```js
49994 * // Create cube render target
49995 * const cubeRenderTarget = new THREE.WebGLCubeRenderTarget( 256, { generateMipmaps: true, minFilter: THREE.LinearMipmapLinearFilter } );
49996 *
49997 * // Create cube camera
49998 * const cubeCamera = new THREE.CubeCamera( 1, 100000, cubeRenderTarget );
49999 * scene.add( cubeCamera );
50000 *
50001 * // Create car
50002 * const chromeMaterial = new THREE.MeshLambertMaterial( { color: 0xffffff, envMap: cubeRenderTarget.texture } );
50003 * const car = new THREE.Mesh( carGeometry, chromeMaterial );
50004 * scene.add( car );
50005 *
50006 * // Update the render target cube
50007 * car.visible = false;
50008 * cubeCamera.position.copy( car.position );
50009 * cubeCamera.update( renderer, scene );
50010 *
50011 * // Render the scene
50012 * car.visible = true;
50013 * renderer.render( scene, camera );
50014 * ```
50015 *
50016 * @augments Object3D
50017 */
50018class CubeCamera extends Object3D {
50019
50020	/**
50021	 * Constructs a new cube camera.
50022	 *
50023	 * @param {number} near - The camera's near plane.
50024	 * @param {number} far - The camera's far plane.
50025	 * @param {WebGLCubeRenderTarget} renderTarget - The cube render target.
50026	 */
50027	constructor( near, far, renderTarget ) {
50028
50029		super();
50030
50031		this.type = 'CubeCamera';
50032
50033		/**
50034		 * A reference to the cube render target.
50035		 *
50036		 * @type {WebGLCubeRenderTarget}
50037		 */
50038		this.renderTarget = renderTarget;
50039
50040		/**
50041		 * The current active coordinate system.
50042		 *
50043		 * @type {?(WebGLCoordinateSystem|WebGPUCoordinateSystem)}
50044		 * @default null
50045		 */
50046		this.coordinateSystem = null;
50047
50048		/**
50049		 * The current active mipmap level
50050		 *
50051		 * @type {number}
50052		 * @default 0
50053		 */
50054		this.activeMipmapLevel = 0;
50055
50056		const cameraPX = new PerspectiveCamera( fov, aspect, near, far );
50057		cameraPX.layers = this.layers;
50058		this.add( cameraPX );
50059
50060		const cameraNX = new PerspectiveCamera( fov, aspect, near, far );
50061		cameraNX.layers = this.layers;
50062		this.add( cameraNX );
50063
50064		const cameraPY = new PerspectiveCamera( fov, aspect, near, far );
50065		cameraPY.layers = this.layers;
50066		this.add( cameraPY );
50067
50068		const cameraNY = new PerspectiveCamera( fov, aspect, near, far );
50069		cameraNY.layers = this.layers;
50070		this.add( cameraNY );
50071
50072		const cameraPZ = new PerspectiveCamera( fov, aspect, near, far );
50073		cameraPZ.layers = this.layers;
50074		this.add( cameraPZ );
50075
50076		const cameraNZ = new PerspectiveCamera( fov, aspect, near, far );
50077		cameraNZ.layers = this.layers;
50078		this.add( cameraNZ );
50079
50080	}
50081
50082	/**
50083	 * Must be called when the coordinate system of the cube camera is changed.
50084	 */
50085	updateCoordinateSystem() {
50086
50087		const coordinateSystem = this.coordinateSystem;
50088
50089		const cameras = this.children.concat();
50090
50091		const [ cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ ] = cameras;
50092
50093		for ( const camera of cameras ) this.remove( camera );
50094
50095		if ( coordinateSystem === WebGLCoordinateSystem ) {
50096
50097			cameraPX.up.set( 0, 1, 0 );
50098			cameraPX.lookAt( 1, 0, 0 );
50099
50100			cameraNX.up.set( 0, 1, 0 );
50101			cameraNX.lookAt( -1, 0, 0 );
50102
50103			cameraPY.up.set( 0, 0, -1 );
50104			cameraPY.lookAt( 0, 1, 0 );
50105
50106			cameraNY.up.set( 0, 0, 1 );
50107			cameraNY.lookAt( 0, -1, 0 );
50108
50109			cameraPZ.up.set( 0, 1, 0 );
50110			cameraPZ.lookAt( 0, 0, 1 );
50111
50112			cameraNZ.up.set( 0, 1, 0 );
50113			cameraNZ.lookAt( 0, 0, -1 );
50114
50115		} else if ( coordinateSystem === WebGPUCoordinateSystem ) {
50116
50117			cameraPX.up.set( 0, -1, 0 );
50118			cameraPX.lookAt( -1, 0, 0 );
50119
50120			cameraNX.up.set( 0, -1, 0 );
50121			cameraNX.lookAt( 1, 0, 0 );
50122
50123			cameraPY.up.set( 0, 0, 1 );
50124			cameraPY.lookAt( 0, 1, 0 );
50125
50126			cameraNY.up.set( 0, 0, -1 );
50127			cameraNY.lookAt( 0, -1, 0 );
50128
50129			cameraPZ.up.set( 0, -1, 0 );
50130			cameraPZ.lookAt( 0, 0, 1 );
50131
50132			cameraNZ.up.set( 0, -1, 0 );
50133			cameraNZ.lookAt( 0, 0, -1 );
50134
50135		} else {
50136
50137			throw new Error( 'THREE.CubeCamera.updateCoordinateSystem(): Invalid coordinate system: ' + coordinateSystem );
50138
50139		}
50140
50141		for ( const camera of cameras ) {
50142
50143			this.add( camera );
50144
50145			camera.updateMatrixWorld();
50146
50147		}
50148
50149	}
50150
50151	/**
50152	 * Calling this method will render the given scene with the given renderer
50153	 * into the cube render target of the camera.
50154	 *
50155	 * @param {(Renderer|WebGLRenderer)} renderer - The renderer.
50156	 * @param {Scene} scene - The scene to render.
50157	 */
50158	update( renderer, scene ) {
50159
50160		if ( this.parent === null ) this.updateMatrixWorld();
50161
50162		const { renderTarget, activeMipmapLevel } = this;
50163
50164		if ( this.coordinateSystem !== renderer.coordinateSystem ) {
50165
50166			this.coordinateSystem = renderer.coordinateSystem;
50167
50168			this.updateCoordinateSystem();
50169
50170		}
50171
50172		const [ cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ ] = this.children;
50173
50174		const currentRenderTarget = renderer.getRenderTarget();
50175		const currentActiveCubeFace = renderer.getActiveCubeFace();
50176		const currentActiveMipmapLevel = renderer.getActiveMipmapLevel();
50177
50178		const currentXrEnabled = renderer.xr.enabled;
50179
50180		renderer.xr.enabled = false;
50181
50182		const generateMipmaps = renderTarget.texture.generateMipmaps;
50183
50184		renderTarget.texture.generateMipmaps = false;
50185
50186		// https://github.com/mrdoob/three.js/issues/31413#issuecomment-3095966812
50187
50188		let reversedDepthBuffer = false;
50189
50190		if ( renderer.isWebGLRenderer === true ) {
50191
50192			reversedDepthBuffer = renderer.state.buffers.depth.getReversed();
50193
50194		} else {
50195
50196			reversedDepthBuffer = renderer.reversedDepthBuffer;
50197
50198		}
50199
50200		renderer.setRenderTarget( renderTarget, 0, activeMipmapLevel );
50201		if ( reversedDepthBuffer && renderer.autoClear === false ) renderer.clearDepth();
50202		renderer.render( scene, cameraPX );
50203
50204		renderer.setRenderTarget( renderTarget, 1, activeMipmapLevel );
50205		if ( reversedDepthBuffer && renderer.autoClear === false ) renderer.clearDepth();
50206		renderer.render( scene, cameraNX );
50207
50208		renderer.setRenderTarget( renderTarget, 2, activeMipmapLevel );
50209		if ( reversedDepthBuffer && renderer.autoClear === false ) renderer.clearDepth();
50210		renderer.render( scene, cameraPY );
50211
50212		renderer.setRenderTarget( renderTarget, 3, activeMipmapLevel );
50213		if ( reversedDepthBuffer && renderer.autoClear === false ) renderer.clearDepth();
50214		renderer.render( scene, cameraNY );
50215
50216		renderer.setRenderTarget( renderTarget, 4, activeMipmapLevel );
50217		if ( reversedDepthBuffer && renderer.autoClear === false ) renderer.clearDepth();
50218		renderer.render( scene, cameraPZ );
50219
50220		// mipmaps are generated during the last call of render()
50221		// at this point, all sides of the cube render target are defined
50222
50223		renderTarget.texture.generateMipmaps = generateMipmaps;
50224
50225		renderer.setRenderTarget( renderTarget, 5, activeMipmapLevel );
50226		if ( reversedDepthBuffer && renderer.autoClear === false ) renderer.clearDepth();
50227		renderer.render( scene, cameraNZ );
50228
50229		renderer.setRenderTarget( currentRenderTarget, currentActiveCubeFace, currentActiveMipmapLevel );
50230
50231		renderer.xr.enabled = currentXrEnabled;
50232
50233		renderTarget.texture.needsPMREMUpdate = true;
50234
50235	}
50236
50237}
50238
50239/**
50240 * This type of camera can be used in order to efficiently render a scene with a
50241 * predefined set of cameras. This is an important performance aspect for
50242 * rendering VR scenes.
50243 *
50244 * An instance of `ArrayCamera` always has an array of sub cameras. It's mandatory
50245 * to define for each sub camera the `viewport` property which determines the
50246 * part of the viewport that is rendered with this camera.
50247 *
50248 * @augments PerspectiveCamera
50249 */
50250class ArrayCamera extends PerspectiveCamera {
50251
50252	/**
50253	 * Constructs a new array camera.
50254	 *
50255	 * @param {Array<PerspectiveCamera>} [array=[]] - An array of perspective sub cameras.
50256	 */
50257	constructor( array = [] ) {
50258
50259		super();
50260
50261		/**
50262		 * This flag can be used for type testing.
50263		 *
50264		 * @type {boolean}
50265		 * @readonly
50266		 * @default true
50267		 */
50268		this.isArrayCamera = true;
50269
50270		/**
50271		 * Whether this camera is used with multiview rendering or not.
50272		 *
50273		 * @type {boolean}
50274		 * @readonly
50275		 * @default false
50276		 */
50277		this.isMultiViewCamera = false;
50278
50279		/**
50280		 * An array of perspective sub cameras.
50281		 *
50282		 * @type {Array<PerspectiveCamera>}
50283		 */
50284		this.cameras = array;
50285
50286	}
50287
50288}
50289
50290/**
50291 * This class is an alternative to {@link Clock} with a different API design and behavior.
50292 * The goal is to avoid the conceptual flaws that became apparent in `Clock` over time.
50293 *
50294 * - `Timer` has an `update()` method that updates its internal state. That makes it possible to
50295 * call `getDelta()` and `getElapsed()` multiple times per simulation step without getting different values.
50296 * - The class can make use of the Page Visibility API to avoid large time delta values when the app
50297 * is inactive (e.g. tab switched or browser hidden).
50298 *
50299 * ```js
50300 * const timer = new Timer();
50301 * timer.connect( document ); // use Page Visibility API
50302 * ```
50303 */
50304class Timer {
50305
50306	/**
50307	 * Constructs a new timer.
50308	 */
50309	constructor() {
50310
50311		this._previousTime = 0;
50312		this._currentTime = 0;
50313		this._startTime = performance.now();
50314
50315		this._delta = 0;
50316		this._elapsed = 0;
50317
50318		this._timescale = 1;
50319
50320		this._document = null;
50321		this._pageVisibilityHandler = null;
50322
50323	}
50324
50325	/**
50326	 * Connect the timer to the given document.Calling this method is not mandatory to
50327	 * use the timer but enables the usage of the Page Visibility API to avoid large time
50328	 * delta values.
50329	 *
50330	 * @param {Document} document - The document.
50331	 */
50332	connect( document ) {
50333
50334		this._document = document;
50335
50336		// use Page Visibility API to avoid large time delta values
50337
50338		if ( document.hidden !== undefined ) {
50339
50340			this._pageVisibilityHandler = handleVisibilityChange.bind( this );
50341
50342			document.addEventListener( 'visibilitychange', this._pageVisibilityHandler, false );
50343
50344		}
50345
50346	}
50347
50348	/**
50349	 * Disconnects the timer from the DOM and also disables the usage of the Page Visibility API.
50350	 */
50351	disconnect() {
50352
50353		if ( this._pageVisibilityHandler !== null ) {
50354
50355			this._document.removeEventListener( 'visibilitychange', this._pageVisibilityHandler );
50356			this._pageVisibilityHandler = null;
50357
50358		}
50359
50360		this._document = null;
50361
50362	}
50363
50364	/**
50365	 * Returns the time delta in seconds.
50366	 *
50367	 * @return {number} The time delta in second.
50368	 */
50369	getDelta() {
50370
50371		return this._delta / 1000;
50372
50373	}
50374
50375	/**
50376	 * Returns the elapsed time in seconds.
50377	 *
50378	 * @return {number} The elapsed time in second.
50379	 */
50380	getElapsed() {
50381
50382		return this._elapsed / 1000;
50383
50384	}
50385
50386	/**
50387	 * Returns the timescale.
50388	 *
50389	 * @return {number} The timescale.
50390	 */
50391	getTimescale() {
50392
50393		return this._timescale;
50394
50395	}
50396
50397	/**
50398	 * Sets the given timescale which scale the time delta computation
50399	 * in `update()`.
50400	 *
50401	 * @param {number} timescale - The timescale to set.
50402	 * @return {Timer} A reference to this timer.
50403	 */
50404	setTimescale( timescale ) {
50405
50406		this._timescale = timescale;
50407
50408		return this;
50409
50410	}
50411
50412	/**
50413	 * Resets the time computation for the current simulation step.
50414	 *
50415	 * @return {Timer} A reference to this timer.
50416	 */
50417	reset() {
50418
50419		this._currentTime = performance.now() - this._startTime;
50420
50421		return this;
50422
50423	}
50424
50425	/**
50426	 * Can be used to free all internal resources. Usually called when
50427	 * the timer instance isn't required anymore.
50428	 */
50429	dispose() {
50430
50431		this.disconnect();
50432
50433	}
50434
50435	/**
50436	 * Updates the internal state of the timer. This method should be called
50437	 * once per simulation step and before you perform queries against the timer
50438	 * (e.g. via `getDelta()`).
50439	 *
50440	 * @param {number} timestamp - The current time in milliseconds. Can be obtained
50441	 * from the `requestAnimationFrame` callback argument. If not provided, the current
50442	 * time will be determined with `performance.now`.
50443	 * @return {Timer} A reference to this timer.
50444	 */
50445	update( timestamp ) {
50446
50447		if ( this._pageVisibilityHandler !== null && this._document.hidden === true ) {
50448
50449			this._delta = 0;
50450
50451		} else {
50452
50453			this._previousTime = this._currentTime;
50454			this._currentTime = ( timestamp !== undefined ? timestamp : performance.now() ) - this._startTime;
50455
50456			this._delta = ( this._currentTime - this._previousTime ) * this._timescale;
50457			this._elapsed += this._delta; // _elapsed is the accumulation of all previous deltas
50458
50459		}
50460
50461		return this;
50462
50463	}
50464
50465}
50466
50467function handleVisibilityChange() {
50468
50469	if ( this._document.hidden === false ) this.reset();
50470
50471}
50472
50473const _position$1 = /*@__PURE__*/ new Vector3();
50474const _quaternion$1 = /*@__PURE__*/ new Quaternion();
50475const _scale$1 = /*@__PURE__*/ new Vector3();
50476
50477const _forward = /*@__PURE__*/ new Vector3();
50478const _up = /*@__PURE__*/ new Vector3();
50479
50480/**
50481 * The class represents a virtual listener of the all positional and non-positional audio effects
50482 * in the scene. A three.js application usually creates a single listener. It is a mandatory
50483 * constructor parameter for audios entities like {@link Audio} and {@link PositionalAudio}.
50484 *
50485 * In most cases, the listener object is a child of the camera. So the 3D transformation of the
50486 * camera represents the 3D transformation of the listener.
50487 *
50488 * @augments Object3D
50489 */
50490class AudioListener extends Object3D {
50491
50492	/**
50493	 * Constructs a new audio listener.
50494	 */
50495	constructor() {
50496
50497		super();
50498
50499		this.type = 'AudioListener';
50500
50501		/**
50502		 * The native audio context.
50503		 *
50504		 * @type {AudioContext}
50505		 * @readonly
50506		 */
50507		this.context = AudioContext.getContext();
50508
50509		/**
50510		 * The gain node used for volume control.
50511		 *
50512		 * @type {GainNode}
50513		 * @readonly
50514		 */
50515		this.gain = this.context.createGain();
50516		this.gain.connect( this.context.destination );
50517
50518		/**
50519		 * An optional filter.
50520		 *
50521		 * Defined via {@link AudioListener#setFilter}.
50522		 *
50523		 * @type {?AudioNode}
50524		 * @default null
50525		 * @readonly
50526		 */
50527		this.filter = null;
50528
50529		/**
50530		 * Time delta values required for `linearRampToValueAtTime()` usage.
50531		 *
50532		 * @type {number}
50533		 * @default 0
50534		 * @readonly
50535		 */
50536		this.timeDelta = 0;
50537
50538		// private
50539
50540		this._timer = new Timer();
50541
50542	}
50543
50544	/**
50545	 * Returns the listener's input node.
50546	 *
50547	 * This method is used by other audio nodes to connect to this listener.
50548	 *
50549	 * @return {GainNode} The input node.
50550	 */
50551	getInput() {
50552
50553		return this.gain;
50554
50555	}
50556
50557	/**
50558	 * Removes the current filter from this listener.
50559	 *
50560	 * @return {AudioListener} A reference to this listener.
50561	 */
50562	removeFilter() {
50563
50564		if ( this.filter !== null ) {
50565
50566			this.gain.disconnect( this.filter );
50567			this.filter.disconnect( this.context.destination );
50568			this.gain.connect( this.context.destination );
50569			this.filter = null;
50570
50571		}
50572
50573		return this;
50574
50575	}
50576
50577	/**
50578	 * Returns the current set filter.
50579	 *
50580	 * @return {?AudioNode} The filter.
50581	 */
50582	getFilter() {
50583
50584		return this.filter;
50585
50586	}
50587
50588	/**
50589	 * Sets the given filter to this listener.
50590	 *
50591	 * @param {AudioNode} value - The filter to set.
50592	 * @return {AudioListener} A reference to this listener.
50593	 */
50594	setFilter( value ) {
50595
50596		if ( this.filter !== null ) {
50597
50598			this.gain.disconnect( this.filter );
50599			this.filter.disconnect( this.context.destination );
50600
50601		} else {
50602
50603			this.gain.disconnect( this.context.destination );
50604
50605		}
50606
50607		this.filter = value;
50608		this.gain.connect( this.filter );
50609		this.filter.connect( this.context.destination );
50610
50611		return this;
50612
50613	}
50614
50615	/**
50616	 * Returns the applications master volume.
50617	 *
50618	 * @return {number} The master volume.
50619	 */
50620	getMasterVolume() {
50621
50622		return this.gain.gain.value;
50623
50624	}
50625
50626	/**
50627	 * Sets the applications master volume. This volume setting affects
50628	 * all audio nodes in the scene.
50629	 *
50630	 * @param {number} value - The master volume to set.
50631	 * @return {AudioListener} A reference to this listener.
50632	 */
50633	setMasterVolume( value ) {
50634
50635		this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 );
50636
50637		return this;
50638
50639	}
50640
50641	updateMatrixWorld( force ) {
50642
50643		super.updateMatrixWorld( force );
50644
50645		this._timer.update();
50646
50647		const listener = this.context.listener;
50648
50649		this.timeDelta = this._timer.getDelta();
50650
50651		this.matrixWorld.decompose( _position$1, _quaternion$1, _scale$1 );
50652
50653		// the initial forward and up directions must be orthogonal
50654		_forward.set( 0, 0, -1 ).applyQuaternion( _quaternion$1 );
50655		_up.set( 0, 1, 0 ).applyQuaternion( _quaternion$1 );
50656
50657		if ( listener.positionX ) {
50658
50659			// code path for Chrome (see #14393)
50660
50661			const endTime = this.context.currentTime + this.timeDelta;
50662
50663			listener.positionX.linearRampToValueAtTime( _position$1.x, endTime );
50664			listener.positionY.linearRampToValueAtTime( _position$1.y, endTime );
50665			listener.positionZ.linearRampToValueAtTime( _position$1.z, endTime );
50666			listener.forwardX.linearRampToValueAtTime( _forward.x, endTime );
50667			listener.forwardY.linearRampToValueAtTime( _forward.y, endTime );
50668			listener.forwardZ.linearRampToValueAtTime( _forward.z, endTime );
50669			listener.upX.linearRampToValueAtTime( _up.x, endTime );
50670			listener.upY.linearRampToValueAtTime( _up.y, endTime );
50671			listener.upZ.linearRampToValueAtTime( _up.z, endTime );
50672
50673		} else {
50674
50675			listener.setPosition( _position$1.x, _position$1.y, _position$1.z );
50676			listener.setOrientation( _forward.x, _forward.y, _forward.z, _up.x, _up.y, _up.z );
50677
50678		}
50679
50680	}
50681
50682}
50683
50684/**
50685 * Represents a non-positional ( global ) audio object.
50686 *
50687 * This and related audio modules make use of the [Web Audio API](https://www.w3.org/TR/webaudio-1.1/).
50688 *
50689 * ```js
50690 * // create an AudioListener and add it to the camera
50691 * const listener = new THREE.AudioListener();
50692 * camera.add( listener );
50693 *
50694 * // create a global audio source
50695 * const sound = new THREE.Audio( listener );
50696 *
50697 * // load a sound and set it as the Audio object's buffer
50698 * const audioLoader = new THREE.AudioLoader();
50699 * audioLoader.load( 'sounds/ambient.ogg', function( buffer ) {
50700 * 	sound.setBuffer( buffer );
50701 * 	sound.setLoop( true );
50702 * 	sound.setVolume( 0.5 );
50703 * 	sound.play();
50704 * });
50705 * ```
50706 *
50707 * @augments Object3D
50708 */
50709class Audio extends Object3D {
50710
50711	/**
50712	 * Constructs a new audio.
50713	 *
50714	 * @param {AudioListener} listener - The global audio listener.
50715	 */
50716	constructor( listener ) {
50717
50718		super();
50719
50720		this.type = 'Audio';
50721
50722		/**
50723		 * The global audio listener.
50724		 *
50725		 * @type {AudioListener}
50726		 * @readonly
50727		 */
50728		this.listener = listener;
50729
50730		/**
50731		 * The audio context.
50732		 *
50733		 * @type {AudioContext}
50734		 * @readonly
50735		 */
50736		this.context = listener.context;
50737
50738		/**
50739		 * The gain node used for volume control.
50740		 *
50741		 * @type {GainNode}
50742		 * @readonly
50743		 */
50744		this.gain = this.context.createGain();
50745		this.gain.connect( listener.getInput() );
50746
50747		/**
50748		 * Whether to start playback automatically or not.
50749		 *
50750		 * @type {boolean}
50751		 * @default false
50752		 */
50753		this.autoplay = false;
50754
50755		/**
50756		 * A reference to an audio buffer.
50757		 *
50758		 * Defined via {@link Audio#setBuffer}.
50759		 *
50760		 * @type {?AudioBuffer}
50761		 * @default null
50762		 * @readonly
50763		 */
50764		this.buffer = null;
50765
50766		/**
50767		 * Modify pitch, measured in cents. +/- 100 is a semitone.
50768		 * +/- 1200 is an octave.
50769		 *
50770		 * Defined via {@link Audio#setDetune}.
50771		 *
50772		 * @type {number}
50773		 * @default 0
50774		 * @readonly
50775		 */
50776		this.detune = 0;
50777
50778		/**
50779		 * Whether the audio should loop or not.
50780		 *
50781		 * Defined via {@link Audio#setLoop}.
50782		 *
50783		 * @type {boolean}
50784		 * @default false
50785		 * @readonly
50786		 */
50787		this.loop = false;
50788
50789		/**
50790		 * Defines where in the audio buffer the replay should
50791		 * start, in seconds.
50792		 *
50793		 * @type {number}
50794		 * @default 0
50795		 */
50796		this.loopStart = 0;
50797
50798		/**
50799		 * Defines where in the audio buffer the replay should
50800		 * stop, in seconds.
50801		 *
50802		 * @type {number}
50803		 * @default 0
50804		 */
50805		this.loopEnd = 0;
50806
50807		/**
50808		 * An offset to the time within the audio buffer the playback
50809		 * should begin, in seconds.
50810		 *
50811		 * @type {number}
50812		 * @default 0
50813		 */
50814		this.offset = 0;
50815
50816		/**
50817		 * Overrides the default duration of the audio.
50818		 *
50819		 * @type {undefined|number}
50820		 * @default undefined
50821		 */
50822		this.duration = undefined;
50823
50824		/**
50825		 * The playback speed.
50826		 *
50827		 * Defined via {@link Audio#setPlaybackRate}.
50828		 *
50829		 * @type {number}
50830		 * @readonly
50831		 * @default 1
50832		 */
50833		this.playbackRate = 1;
50834
50835		/**
50836		 * Indicates whether the audio is playing or not.
50837		 *
50838		 * This flag will be automatically set when using {@link Audio#play},
50839		 * {@link Audio#pause}, {@link Audio#stop}.
50840		 *
50841		 * @type {boolean}
50842		 * @readonly
50843		 * @default false
50844		 */
50845		this.isPlaying = false;
50846
50847		/**
50848		 * Indicates whether the audio playback can be controlled
50849		 * with method like {@link Audio#play} or {@link Audio#pause}.
50850		 *
50851		 * This flag will be automatically set when audio sources are
50852		 * defined.
50853		 *
50854		 * @type {boolean}
50855		 * @readonly
50856		 * @default true
50857		 */
50858		this.hasPlaybackControl = true;
50859
50860		/**
50861		 * Holds a reference to the current audio source.
50862		 *
50863		 * The property is automatically by one of the `set*()` methods.
50864		 *
50865		 * @type {?AudioNode}
50866		 * @readonly
50867		 * @default null
50868		 */
50869		this.source = null;
50870
50871		/**
50872		 * Defines the source type.
50873		 *
50874		 * The property is automatically set by one of the `set*()` methods.
50875		 *
50876		 * @type {('empty'|'audioNode'|'mediaNode'|'mediaStreamNode'|'buffer')}
50877		 * @readonly
50878		 * @default 'empty'
50879		 */
50880		this.sourceType = 'empty';
50881
50882		this._startedAt = 0;
50883		this._progress = 0;
50884		this._connected = false;
50885
50886		/**
50887		 * Can be used to apply a variety of low-order filters to create
50888		 * more complex sound effects e.g. via `BiquadFilterNode`.
50889		 *
50890		 * The property is automatically set by {@link Audio#setFilters}.
50891		 *
50892		 * @type {Array<AudioNode>}
50893		 * @readonly
50894		 */
50895		this.filters = [];
50896
50897	}
50898
50899	/**
50900	 * Returns the output audio node.
50901	 *
50902	 * @return {GainNode} The output node.
50903	 */
50904	getOutput() {
50905
50906		return this.gain;
50907
50908	}
50909
50910	/**
50911	 * Sets the given audio node as the source of this instance.
50912	 *
50913	 * {@link Audio#sourceType} is set to `audioNode` and {@link Audio#hasPlaybackControl} to `false`.
50914	 *
50915	 * @param {AudioNode} audioNode - The audio node like an instance of `OscillatorNode`.
50916	 * @return {Audio} A reference to this instance.
50917	 */
50918	setNodeSource( audioNode ) {
50919
50920		this.hasPlaybackControl = false;
50921		this.sourceType = 'audioNode';
50922		this.source = audioNode;
50923		this.connect();
50924
50925		return this;
50926
50927	}
50928
50929	/**
50930	 * Sets the given media element as the source of this instance.
50931	 *
50932	 * {@link Audio#sourceType} is set to `mediaNode` and {@link Audio#hasPlaybackControl} to `false`.
50933	 *
50934	 * @param {HTMLMediaElement} mediaElement - The media element.
50935	 * @return {Audio} A reference to this instance.
50936	 */
50937	setMediaElementSource( mediaElement ) {
50938
50939		this.hasPlaybackControl = false;
50940		this.sourceType = 'mediaNode';
50941		this.source = this.context.createMediaElementSource( mediaElement );
50942		this.connect();
50943
50944		return this;
50945
50946	}
50947
50948	/**
50949	 * Sets the given media stream as the source of this instance.
50950	 *
50951	 * {@link Audio#sourceType} is set to `mediaStreamNode` and {@link Audio#hasPlaybackControl} to `false`.
50952	 *
50953	 * @param {MediaStream} mediaStream - The media stream.
50954	 * @return {Audio} A reference to this instance.
50955	 */
50956	setMediaStreamSource( mediaStream ) {
50957
50958		this.hasPlaybackControl = false;
50959		this.sourceType = 'mediaStreamNode';
50960		this.source = this.context.createMediaStreamSource( mediaStream );
50961		this.connect();
50962
50963		return this;
50964
50965	}
50966
50967	/**
50968	 * Sets the given audio buffer as the source of this instance.
50969	 *
50970	 * {@link Audio#sourceType} is set to `buffer` and {@link Audio#hasPlaybackControl} to `true`.
50971	 *
50972	 * @param {AudioBuffer} audioBuffer - The audio buffer.
50973	 * @return {Audio} A reference to this instance.
50974	 */
50975	setBuffer( audioBuffer ) {
50976
50977		this.buffer = audioBuffer;
50978		this.sourceType = 'buffer';
50979
50980		if ( this.autoplay ) this.play();
50981
50982		return this;
50983
50984	}
50985
50986	/**
50987	 * Starts the playback of the audio.
50988	 *
50989	 * Can only be used with compatible audio sources that allow playback control.
50990	 *
50991	 * @param {number} [delay=0] - The delay, in seconds, at which the audio should start playing.
50992	 * @return {Audio|undefined} A reference to this instance.
50993	 */
50994	play( delay = 0 ) {
50995
50996		if ( this.isPlaying === true ) {
50997
50998			warn( 'Audio: Audio is already playing.' );
50999			return;
51000
51001		}
51002
51003		if ( this.hasPlaybackControl === false ) {
51004
51005			warn( 'Audio: this Audio has no playback control.' );
51006			return;
51007
51008		}
51009
51010		this._startedAt = this.context.currentTime + delay;
51011
51012		const source = this.context.createBufferSource();
51013		source.buffer = this.buffer;
51014		source.loop = this.loop;
51015		source.loopStart = this.loopStart;
51016		source.loopEnd = this.loopEnd;
51017		source.onended = this.onEnded.bind( this );
51018		source.start( this._startedAt, this._progress + this.offset, this.duration );
51019
51020		this.isPlaying = true;
51021
51022		this.source = source;
51023
51024		this.setDetune( this.detune );
51025		this.setPlaybackRate( this.playbackRate );
51026
51027		return this.connect();
51028
51029	}
51030
51031	/**
51032	 * Pauses the playback of the audio.
51033	 *
51034	 * Can only be used with compatible audio sources that allow playback control.
51035	 *
51036	 * @return {Audio|undefined} A reference to this instance.
51037	 */
51038	pause() {
51039
51040		if ( this.hasPlaybackControl === false ) {
51041
51042			warn( 'Audio: this Audio has no playback control.' );
51043			return;
51044
51045		}
51046
51047		if ( this.isPlaying === true ) {
51048
51049			// update current progress
51050
51051			this._progress += Math.max( this.context.currentTime - this._startedAt, 0 ) * this.playbackRate;
51052
51053			if ( this.loop === true ) {
51054
51055				// ensure _progress does not exceed duration with looped audios
51056
51057				this._progress = this._progress % ( this.duration || this.buffer.duration );
51058
51059			}
51060
51061			this.source.stop();
51062			this.source.onended = null;
51063
51064			this.isPlaying = false;
51065
51066		}
51067
51068		return this;
51069
51070	}
51071
51072	/**
51073	 * Stops the playback of the audio.
51074	 *
51075	 * Can only be used with compatible audio sources that allow playback control.
51076	 *
51077	 * @param {number} [delay=0] - The delay, in seconds, at which the audio should stop playing.
51078	 * @return {Audio|undefined} A reference to this instance.
51079	 */
51080	stop( delay = 0 ) {
51081
51082		if ( this.hasPlaybackControl === false ) {
51083
51084			warn( 'Audio: this Audio has no playback control.' );
51085			return;
51086
51087		}
51088
51089		this._progress = 0;
51090
51091		if ( this.source !== null ) {
51092
51093			this.source.stop( this.context.currentTime + delay );
51094			this.source.onended = null;
51095
51096		}
51097
51098		this.isPlaying = false;
51099
51100		return this;
51101
51102	}
51103
51104	/**
51105	 * Connects to the audio source. This is used internally on
51106	 * initialisation and when setting / removing filters.
51107	 *
51108	 * @return {Audio} A reference to this instance.
51109	 */
51110	connect() {
51111
51112		if ( this.filters.length > 0 ) {
51113
51114			this.source.connect( this.filters[ 0 ] );
51115
51116			for ( let i = 1, l = this.filters.length; i < l; i ++ ) {
51117
51118				this.filters[ i - 1 ].connect( this.filters[ i ] );
51119
51120			}
51121
51122			this.filters[ this.filters.length - 1 ].connect( this.getOutput() );
51123
51124		} else {
51125
51126			this.source.connect( this.getOutput() );
51127
51128		}
51129
51130		this._connected = true;
51131
51132		return this;
51133
51134	}
51135
51136	/**
51137	 * Disconnects to the audio source. This is used internally on
51138	 * initialisation and when setting / removing filters.
51139	 *
51140	 * @return {Audio|undefined} A reference to this instance.
51141	 */
51142	disconnect() {
51143
51144		if ( this._connected === false ) {
51145
51146			return;
51147
51148		}
51149
51150		if ( this.filters.length > 0 ) {
51151
51152			this.source.disconnect( this.filters[ 0 ] );
51153
51154			for ( let i = 1, l = this.filters.length; i < l; i ++ ) {
51155
51156				this.filters[ i - 1 ].disconnect( this.filters[ i ] );
51157
51158			}
51159
51160			this.filters[ this.filters.length - 1 ].disconnect( this.getOutput() );
51161
51162		} else {
51163
51164			this.source.disconnect( this.getOutput() );
51165
51166		}
51167
51168		this._connected = false;
51169
51170		return this;
51171
51172	}
51173
51174	/**
51175	 * Returns the current set filters.
51176	 *
51177	 * @return {Array<AudioNode>} The list of filters.
51178	 */
51179	getFilters() {
51180
51181		return this.filters;
51182
51183	}
51184
51185	/**
51186	 * Sets an array of filters and connects them with the audio source.
51187	 *
51188	 * @param {Array<AudioNode>} [value] - A list of filters.
51189	 * @return {Audio} A reference to this instance.
51190	 */
51191	setFilters( value ) {
51192
51193		if ( ! value ) value = [];
51194
51195		if ( this._connected === true ) {
51196
51197			this.disconnect();
51198			this.filters = value.slice();
51199			this.connect();
51200
51201		} else {
51202
51203			this.filters = value.slice();
51204
51205		}
51206
51207		return this;
51208
51209	}
51210
51211	/**
51212	 * Defines the detuning of oscillation in cents.
51213	 *
51214	 * @param {number} value - The detuning of oscillation in cents.
51215	 * @return {Audio} A reference to this instance.
51216	 */
51217	setDetune( value ) {
51218
51219		this.detune = value;
51220
51221		if ( this.isPlaying === true && this.source.detune !== undefined ) {
51222
51223			this.source.detune.setTargetAtTime( this.detune, this.context.currentTime, 0.01 );
51224
51225		}
51226
51227		return this;
51228
51229	}
51230
51231	/**
51232	 * Returns the detuning of oscillation in cents.
51233	 *
51234	 * @return {number} The detuning of oscillation in cents.
51235	 */
51236	getDetune() {
51237
51238		return this.detune;
51239
51240	}
51241
51242	/**
51243	 * Returns the first filter in the list of filters.
51244	 *
51245	 * @return {AudioNode|undefined} The first filter in the list of filters.
51246	 */
51247	getFilter() {
51248
51249		return this.getFilters()[ 0 ];
51250
51251	}
51252
51253	/**
51254	 * Applies a single filter node to the audio.
51255	 *
51256	 * @param {AudioNode} [filter] - The filter to set.
51257	 * @return {Audio} A reference to this instance.
51258	 */
51259	setFilter( filter ) {
51260
51261		return this.setFilters( filter ? [ filter ] : [] );
51262
51263	}
51264
51265	/**
51266	 * Sets the playback rate.
51267	 *
51268	 * Can only be used with compatible audio sources that allow playback control.
51269	 *
51270	 * @param {number} [value] - The playback rate to set.
51271	 * @return {Audio|undefined} A reference to this instance.
51272	 */
51273	setPlaybackRate( value ) {
51274
51275		if ( this.hasPlaybackControl === false ) {
51276
51277			warn( 'Audio: this Audio has no playback control.' );
51278			return;
51279
51280		}
51281
51282		this.playbackRate = value;
51283
51284		if ( this.isPlaying === true ) {
51285
51286			this.source.playbackRate.setTargetAtTime( this.playbackRate, this.context.currentTime, 0.01 );
51287
51288		}
51289
51290		return this;
51291
51292	}
51293
51294	/**
51295	 * Returns the current playback rate.
51296
51297	 * @return {number} The playback rate.
51298	 */
51299	getPlaybackRate() {
51300
51301		return this.playbackRate;
51302
51303	}
51304
51305	/**
51306	 * Automatically called when playback finished.
51307	 */
51308	onEnded() {
51309
51310		this.isPlaying = false;
51311		this._progress = 0;
51312
51313	}
51314
51315	/**
51316	 * Returns the loop flag.
51317	 *
51318	 * Can only be used with compatible audio sources that allow playback control.
51319	 *
51320	 * @return {boolean} Whether the audio should loop or not.
51321	 */
51322	getLoop() {
51323
51324		if ( this.hasPlaybackControl === false ) {
51325
51326			warn( 'Audio: this Audio has no playback control.' );
51327			return false;
51328
51329		}
51330
51331		return this.loop;
51332
51333	}
51334
51335	/**
51336	 * Sets the loop flag.
51337	 *
51338	 * Can only be used with compatible audio sources that allow playback control.
51339	 *
51340	 * @param {boolean} value - Whether the audio should loop or not.
51341	 * @return {Audio|undefined} A reference to this instance.
51342	 */
51343	setLoop( value ) {
51344
51345		if ( this.hasPlaybackControl === false ) {
51346
51347			warn( 'Audio: this Audio has no playback control.' );
51348			return;
51349
51350		}
51351
51352		this.loop = value;
51353
51354		if ( this.isPlaying === true ) {
51355
51356			this.source.loop = this.loop;
51357
51358		}
51359
51360		return this;
51361
51362	}
51363
51364	/**
51365	 * Sets the loop start value which defines where in the audio buffer the replay should
51366	 * start, in seconds.
51367	 *
51368	 * @param {number} value - The loop start value.
51369	 * @return {Audio} A reference to this instance.
51370	 */
51371	setLoopStart( value ) {
51372
51373		this.loopStart = value;
51374
51375		return this;
51376
51377	}
51378
51379	/**
51380	 * Sets the loop end value which defines where in the audio buffer the replay should
51381	 * stop, in seconds.
51382	 *
51383	 * @param {number} value - The loop end value.
51384	 * @return {Audio} A reference to this instance.
51385	 */
51386	setLoopEnd( value ) {
51387
51388		this.loopEnd = value;
51389
51390		return this;
51391
51392	}
51393
51394	/**
51395	 * Returns the volume.
51396	 *
51397	 * @return {number} The volume.
51398	 */
51399	getVolume() {
51400
51401		return this.gain.gain.value;
51402
51403	}
51404
51405	/**
51406	 * Sets the volume.
51407	 *
51408	 * @param {number} value - The volume to set.
51409	 * @return {Audio} A reference to this instance.
51410	 */
51411	setVolume( value ) {
51412
51413		this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 );
51414
51415		return this;
51416
51417	}
51418
51419	copy( source, recursive ) {
51420
51421		super.copy( source, recursive );
51422
51423		if ( source.sourceType !== 'buffer' ) {
51424
51425			warn( 'Audio: Audio source type cannot be copied.' );
51426
51427			return this;
51428
51429		}
51430
51431		this.autoplay = source.autoplay;
51432
51433		this.buffer = source.buffer;
51434		this.detune = source.detune;
51435		this.loop = source.loop;
51436		this.loopStart = source.loopStart;
51437		this.loopEnd = source.loopEnd;
51438		this.offset = source.offset;
51439		this.duration = source.duration;
51440		this.playbackRate = source.playbackRate;
51441		this.hasPlaybackControl = source.hasPlaybackControl;
51442		this.sourceType = source.sourceType;
51443
51444		this.filters = source.filters.slice();
51445
51446		return this;
51447
51448	}
51449
51450	clone( recursive ) {
51451
51452		return new this.constructor( this.listener ).copy( this, recursive );
51453
51454	}
51455
51456}
51457
51458const _position = /*@__PURE__*/ new Vector3();
51459const _quaternion = /*@__PURE__*/ new Quaternion();
51460const _scale = /*@__PURE__*/ new Vector3();
51461const _orientation = /*@__PURE__*/ new Vector3();
51462
51463/**
51464 * Represents a positional audio object.
51465 *
51466 * ```js
51467 * // create an AudioListener and add it to the camera
51468 * const listener = new THREE.AudioListener();
51469 * camera.add( listener );
51470 *
51471 * // create the PositionalAudio object (passing in the listener)
51472 * const sound = new THREE.PositionalAudio( listener );
51473 *
51474 * // load a sound and set it as the PositionalAudio object's buffer
51475 * const audioLoader = new THREE.AudioLoader();
51476 * audioLoader.load( 'sounds/song.ogg', function( buffer ) {
51477 * 	sound.setBuffer( buffer );
51478 * 	sound.setRefDistance( 20 );
51479 * 	sound.play();
51480 * });
51481 *
51482 * // create an object for the sound to play from
51483 * const sphere = new THREE.SphereGeometry( 20, 32, 16 );
51484 * const material = new THREE.MeshPhongMaterial( { color: 0xff2200 } );
51485 * const mesh = new THREE.Mesh( sphere, material );
51486 * scene.add( mesh );
51487 *
51488 * // finally add the sound to the mesh
51489 * mesh.add( sound );
51490 *
51491 * @augments Audio
51492 */
51493class PositionalAudio extends Audio {
51494
51495	/**
51496	 * Constructs a positional audio.
51497	 *
51498	 * @param {AudioListener} listener - The global audio listener.
51499	 */
51500	constructor( listener ) {
51501
51502		super( listener );
51503
51504		/**
51505		 * The panner node represents the location, direction, and behavior of an audio
51506		 * source in 3D space.
51507		 *
51508		 * @type {PannerNode}
51509		 * @readonly
51510		 */
51511		this.panner = this.context.createPanner();
51512		this.panner.panningModel = 'HRTF';
51513		this.panner.connect( this.gain );
51514
51515	}
51516
51517	connect() {
51518
51519		super.connect();
51520
51521		this.panner.connect( this.gain );
51522
51523		return this;
51524
51525	}
51526
51527	disconnect() {
51528
51529		super.disconnect();
51530
51531		this.panner.disconnect( this.gain );
51532
51533		return this;
51534
51535	}
51536
51537	getOutput() {
51538
51539		return this.panner;
51540
51541	}
51542
51543	/**
51544	 * Returns the current reference distance.
51545	 *
51546	 * @return {number} The reference distance.
51547	 */
51548	getRefDistance() {
51549
51550		return this.panner.refDistance;
51551
51552	}
51553
51554	/**
51555	 * Defines the reference distance for reducing volume as the audio source moves
51556	 * further from the listener – i.e. the distance at which the volume reduction
51557	 * starts taking effect.
51558	 *
51559	 * @param {number} value - The reference distance to set.
51560	 * @return {PositionalAudio} A reference to this instance.
51561	 */
51562	setRefDistance( value ) {
51563
51564		this.panner.refDistance = value;
51565
51566		return this;
51567
51568	}
51569
51570	/**
51571	 * Returns the current rolloff factor.
51572	 *
51573	 * @return {number} The rolloff factor.
51574	 */
51575	getRolloffFactor() {
51576
51577		return this.panner.rolloffFactor;
51578
51579	}
51580
51581	/**
51582	 * Defines how quickly the volume is reduced as the source moves away from the listener.
51583	 *
51584	 * @param {number} value - The rolloff factor.
51585	 * @return {PositionalAudio} A reference to this instance.
51586	 */
51587	setRolloffFactor( value ) {
51588
51589		this.panner.rolloffFactor = value;
51590
51591		return this;
51592
51593	}
51594
51595	/**
51596	 * Returns the current distance model.
51597	 *
51598	 * @return {('linear'|'inverse'|'exponential')} The distance model.
51599	 */
51600	getDistanceModel() {
51601
51602		return this.panner.distanceModel;
51603
51604	}
51605
51606	/**
51607	 * Defines which algorithm to use to reduce the volume of the audio source
51608	 * as it moves away from the listener.
51609	 *
51610	 * Read [the spec](https://www.w3.org/TR/webaudio-1.1/#enumdef-distancemodeltype)
51611	 * for more details.
51612	 *
51613	 * @param {('linear'|'inverse'|'exponential')} value - The distance model to set.
51614	 * @return {PositionalAudio} A reference to this instance.
51615	 */
51616	setDistanceModel( value ) {
51617
51618		this.panner.distanceModel = value;
51619
51620		return this;
51621
51622	}
51623
51624	/**
51625	 * Returns the current max distance.
51626	 *
51627	 * @return {number} The max distance.
51628	 */
51629	getMaxDistance() {
51630
51631		return this.panner.maxDistance;
51632
51633	}
51634
51635	/**
51636	 * Defines the maximum distance between the audio source and the listener,
51637	 * after which the volume is not reduced any further.
51638	 *
51639	 * This value is used only by the `linear` distance model.
51640	 *
51641	 * @param {number} value - The max distance.
51642	 * @return {PositionalAudio} A reference to this instance.
51643	 */
51644	setMaxDistance( value ) {
51645
51646		this.panner.maxDistance = value;
51647
51648		return this;
51649
51650	}
51651
51652	/**
51653	 * Sets the directional cone in which the audio can be listened.
51654	 *
51655	 * @param {number} coneInnerAngle - An angle, in degrees, of a cone inside of which there will be no volume reduction.
51656	 * @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.
51657	 * @param {number} coneOuterGain - The amount of volume reduction outside the cone defined by the `coneOuterAngle`. When set to `0`, no sound can be heard.
51658	 * @return {PositionalAudio} A reference to this instance.
51659	 */
51660	setDirectionalCone( coneInnerAngle, coneOuterAngle, coneOuterGain ) {
51661
51662		this.panner.coneInnerAngle = coneInnerAngle;
51663		this.panner.coneOuterAngle = coneOuterAngle;
51664		this.panner.coneOuterGain = coneOuterGain;
51665
51666		return this;
51667
51668	}
51669
51670	updateMatrixWorld( force ) {
51671
51672		super.updateMatrixWorld( force );
51673
51674		if ( this.hasPlaybackControl === true && this.isPlaying === false ) return;
51675
51676		this.matrixWorld.decompose( _position, _quaternion, _scale );
51677
51678		_orientation.set( 0, 0, 1 ).applyQuaternion( _quaternion );
51679
51680		const panner = this.panner;
51681
51682		if ( panner.positionX ) {
51683
51684			// code path for Chrome and Firefox (see #14393)
51685
51686			const endTime = this.context.currentTime + this.listener.timeDelta;
51687
51688			panner.positionX.linearRampToValueAtTime( _position.x, endTime );
51689			panner.positionY.linearRampToValueAtTime( _position.y, endTime );
51690			panner.positionZ.linearRampToValueAtTime( _position.z, endTime );
51691			panner.orientationX.linearRampToValueAtTime( _orientation.x, endTime );
51692			panner.orientationY.linearRampToValueAtTime( _orientation.y, endTime );
51693			panner.orientationZ.linearRampToValueAtTime( _orientation.z, endTime );
51694
51695		} else {
51696
51697			panner.setPosition( _position.x, _position.y, _position.z );
51698			panner.setOrientation( _orientation.x, _orientation.y, _orientation.z );
51699
51700		}
51701
51702	}
51703
51704}
51705
51706/**
51707 * This class can be used to analyse audio data.
51708 *
51709 * ```js
51710 * // create an AudioListener and add it to the camera
51711 * const listener = new THREE.AudioListener();
51712 * camera.add( listener );
51713 *
51714 * // create an Audio source
51715 * const sound = new THREE.Audio( listener );
51716 *
51717 * // load a sound and set it as the Audio object's buffer
51718 * const audioLoader = new THREE.AudioLoader();
51719 * audioLoader.load( 'sounds/ambient.ogg', function( buffer ) {
51720 * 	sound.setBuffer( buffer );
51721 * 	sound.setLoop(true);
51722 * 	sound.setVolume(0.5);
51723 * 	sound.play();
51724 * });
51725 *
51726 * // create an AudioAnalyser, passing in the sound and desired fftSize
51727 * const analyser = new THREE.AudioAnalyser( sound, 32 );
51728 *
51729 * // get the average frequency of the sound
51730 * const data = analyser.getAverageFrequency();
51731 * ```
51732 */
51733class AudioAnalyser {
51734
51735	/**
51736	 * Constructs a new audio analyzer.
51737	 *
51738	 * @param {Audio} audio - The audio to analyze.
51739	 * @param {number} [fftSize=2048] - The window size in samples that is used when performing a Fast Fourier Transform (FFT) to get frequency domain data.
51740	 */
51741	constructor( audio, fftSize = 2048 ) {
51742
51743		/**
51744		 * The global audio listener.
51745		 *
51746		 * @type {AnalyserNode}
51747		 */
51748		this.analyser = audio.context.createAnalyser();
51749		this.analyser.fftSize = fftSize;
51750
51751		/**
51752		 * Holds the analyzed data.
51753		 *
51754		 * @type {Uint8Array}
51755		 */
51756		this.data = new Uint8Array( this.analyser.frequencyBinCount );
51757
51758		audio.getOutput().connect( this.analyser );
51759
51760	}
51761
51762	/**
51763	 * Returns an array with frequency data of the audio.
51764	 *
51765	 * Each item in the array represents the decibel value for a specific frequency.
51766	 * The frequencies are spread linearly from 0 to 1/2 of the sample rate.
51767	 * For example, for 48000 sample rate, the last item of the array will represent
51768	 * the decibel value for 24000 Hz.
51769	 *
51770	 * @return {Uint8Array} The frequency data.
51771	 */
51772	getFrequencyData() {
51773
51774		this.analyser.getByteFrequencyData( this.data );
51775
51776		return this.data;
51777
51778	}
51779
51780	/**
51781	 * Returns the average of the frequencies returned by {@link AudioAnalyser#getFrequencyData}.
51782	 *
51783	 * @return {number} The average frequency.
51784	 */
51785	getAverageFrequency() {
51786
51787		let value = 0;
51788		const data = this.getFrequencyData();
51789
51790		for ( let i = 0; i < data.length; i ++ ) {
51791
51792			value += data[ i ];
51793
51794		}
51795
51796		return value / data.length;
51797
51798	}
51799
51800}
51801
51802/**
51803 * Buffered scene graph property that allows weighted accumulation; used internally.
51804 */
51805class PropertyMixer {
51806
51807	/**
51808	 * Constructs a new property mixer.
51809	 *
51810	 * @param {PropertyBinding} binding - The property binding.
51811	 * @param {string} typeName - The keyframe track type name.
51812	 * @param {number} valueSize - The keyframe track value size.
51813	 */
51814	constructor( binding, typeName, valueSize ) {
51815
51816		/**
51817		 * The property binding.
51818		 *
51819		 * @type {PropertyBinding}
51820		 */
51821		this.binding = binding;
51822
51823		/**
51824		 * The keyframe track value size.
51825		 *
51826		 * @type {number}
51827		 */
51828		this.valueSize = valueSize;
51829
51830		let mixFunction,
51831			mixFunctionAdditive,
51832			setIdentity;
51833
51834		// buffer layout: [ incoming | accu0 | accu1 | orig | addAccu | (optional work) ]
51835		//
51836		// interpolators can use .buffer as their .result
51837		// the data then goes to 'incoming'
51838		//
51839		// 'accu0' and 'accu1' are used frame-interleaved for
51840		// the cumulative result and are compared to detect
51841		// changes
51842		//
51843		// 'orig' stores the original state of the property
51844		//
51845		// 'add' is used for additive cumulative results
51846		//
51847		// 'work' is optional and is only present for quaternion types. It is used
51848		// to store intermediate quaternion multiplication results
51849
51850		switch ( typeName ) {
51851
51852			case 'quaternion':
51853				mixFunction = this._slerp;
51854				mixFunctionAdditive = this._slerpAdditive;
51855				setIdentity = this._setAdditiveIdentityQuaternion;
51856
51857				this.buffer = new Float64Array( valueSize * 6 );
51858				this._workIndex = 5;
51859				break;
51860
51861			case 'string':
51862			case 'bool':
51863				mixFunction = this._select;
51864
51865				// Use the regular mix function and for additive on these types,
51866				// additive is not relevant for non-numeric types
51867				mixFunctionAdditive = this._select;
51868
51869				setIdentity = this._setAdditiveIdentityOther;
51870
51871				this.buffer = new Array( valueSize * 5 );
51872				break;
51873
51874			default:
51875				mixFunction = this._lerp;
51876				mixFunctionAdditive = this._lerpAdditive;
51877				setIdentity = this._setAdditiveIdentityNumeric;
51878
51879				this.buffer = new Float64Array( valueSize * 5 );
51880
51881		}
51882
51883		this._mixBufferRegion = mixFunction;
51884		this._mixBufferRegionAdditive = mixFunctionAdditive;
51885		this._setIdentity = setIdentity;
51886		this._origIndex = 3;
51887		this._addIndex = 4;
51888
51889		/**
51890		 * Accumulated weight of the property binding.
51891		 *
51892		 * @type {number}
51893		 * @default 0
51894		 */
51895		this.cumulativeWeight = 0;
51896
51897		/**
51898		 * Accumulated additive weight of the property binding.
51899		 *
51900		 * @type {number}
51901		 * @default 0
51902		 */
51903		this.cumulativeWeightAdditive = 0;
51904
51905		/**
51906		 * Number of active keyframe tracks currently using this property binding.
51907		 *
51908		 * @type {number}
51909		 * @default 0
51910		 */
51911		this.useCount = 0;
51912
51913		/**
51914		 * Number of keyframe tracks referencing this property binding.
51915		 *
51916		 * @type {number}
51917		 * @default 0
51918		 */
51919		this.referenceCount = 0;
51920
51921	}
51922
51923	/**
51924	 * Accumulates data in the `incoming` region into `accu<i>`.
51925	 *
51926	 * @param {number} accuIndex - The accumulation index.
51927	 * @param {number} weight - The weight.
51928	 */
51929	accumulate( accuIndex, weight ) {
51930
51931		// note: happily accumulating nothing when weight = 0, the caller knows
51932		// the weight and shouldn't have made the call in the first place
51933
51934		const buffer = this.buffer,
51935			stride = this.valueSize,
51936			offset = accuIndex * stride + stride;
51937
51938		let currentWeight = this.cumulativeWeight;
51939
51940		if ( currentWeight === 0 ) {
51941
51942			// accuN := incoming * weight
51943
51944			for ( let i = 0; i !== stride; ++ i ) {
51945
51946				buffer[ offset + i ] = buffer[ i ];
51947
51948			}
51949
51950			currentWeight = weight;
51951
51952		} else {
51953
51954			// accuN := accuN + incoming * weight
51955
51956			currentWeight += weight;
51957			const mix = weight / currentWeight;
51958			this._mixBufferRegion( buffer, offset, 0, mix, stride );
51959
51960		}
51961
51962		this.cumulativeWeight = currentWeight;
51963
51964	}
51965
51966	/**
51967	 * Accumulates data in the `incoming` region into `add`.
51968	 *
51969	 * @param {number} weight - The weight.
51970	 */
51971	accumulateAdditive( weight ) {
51972
51973		const buffer = this.buffer,
51974			stride = this.valueSize,
51975			offset = stride * this._addIndex;
51976
51977		if ( this.cumulativeWeightAdditive === 0 ) {
51978
51979			// add = identity
51980
51981			this._setIdentity();
51982
51983		}
51984
51985		// add := add + incoming * weight
51986
51987		this._mixBufferRegionAdditive( buffer, offset, 0, weight, stride );
51988		this.cumulativeWeightAdditive += weight;
51989
51990	}
51991
51992	/**
51993	 * Applies the state of `accu<i>` to the binding when accus differ.
51994	 *
51995	 * @param {number} accuIndex - The accumulation index.
51996	 */
51997	apply( accuIndex ) {
51998
51999		const stride = this.valueSize,
52000			buffer = this.buffer,
52001			offset = accuIndex * stride + stride,
52002
52003			weight = this.cumulativeWeight,
52004			weightAdditive = this.cumulativeWeightAdditive,
52005
52006			binding = this.binding;
52007
52008		this.cumulativeWeight = 0;
52009		this.cumulativeWeightAdditive = 0;
52010
52011		if ( weight < 1 ) {
52012
52013			// accuN := accuN + original * ( 1 - cumulativeWeight )
52014
52015			const originalValueOffset = stride * this._origIndex;
52016
52017			this._mixBufferRegion(
52018				buffer, offset, originalValueOffset, 1 - weight, stride );
52019
52020		}
52021
52022		if ( weightAdditive > 0 ) {
52023
52024			// accuN := accuN + additive accuN
52025
52026			this._mixBufferRegionAdditive( buffer, offset, this._addIndex * stride, 1, stride );
52027
52028		}
52029
52030		for ( let i = stride, e = stride + stride; i !== e; ++ i ) {
52031
52032			if ( buffer[ i ] !== buffer[ i + stride ] ) {
52033
52034				// value has changed -> update scene graph
52035
52036				binding.setValue( buffer, offset );
52037				break;
52038
52039			}
52040
52041		}
52042
52043	}
52044
52045
52046	/**
52047	 * Remembers the state of the bound property and copy it to both accus.
52048	 */
52049	saveOriginalState() {
52050
52051		const binding = this.binding;
52052
52053		const buffer = this.buffer,
52054			stride = this.valueSize,
52055
52056			originalValueOffset = stride * this._origIndex;
52057
52058		binding.getValue( buffer, originalValueOffset );
52059
52060		// accu[0..1] := orig -- initially detect changes against the original
52061		for ( let i = stride, e = originalValueOffset; i !== e; ++ i ) {
52062
52063			buffer[ i ] = buffer[ originalValueOffset + ( i % stride ) ];
52064
52065		}
52066
52067		// Add to identity for additive
52068		this._setIdentity();
52069
52070		this.cumulativeWeight = 0;
52071		this.cumulativeWeightAdditive = 0;
52072
52073	}
52074
52075	/**
52076	 * Applies the state previously taken via {@link PropertyMixer#saveOriginalState} to the binding.
52077	 */
52078	restoreOriginalState() {
52079
52080		const originalValueOffset = this.valueSize * 3;
52081		this.binding.setValue( this.buffer, originalValueOffset );
52082
52083	}
52084
52085	// internals
52086
52087	_setAdditiveIdentityNumeric() {
52088
52089		const startIndex = this._addIndex * this.valueSize;
52090		const endIndex = startIndex + this.valueSize;
52091
52092		for ( let i = startIndex; i < endIndex; i ++ ) {
52093
52094			this.buffer[ i ] = 0;
52095
52096		}
52097
52098	}
52099
52100	_setAdditiveIdentityQuaternion() {
52101
52102		this._setAdditiveIdentityNumeric();
52103		this.buffer[ this._addIndex * this.valueSize + 3 ] = 1;
52104
52105	}
52106
52107	_setAdditiveIdentityOther() {
52108
52109		const startIndex = this._origIndex * this.valueSize;
52110		const targetIndex = this._addIndex * this.valueSize;
52111
52112		for ( let i = 0; i < this.valueSize; i ++ ) {
52113
52114			this.buffer[ targetIndex + i ] = this.buffer[ startIndex + i ];
52115
52116		}
52117
52118	}
52119
52120
52121	// mix functions
52122
52123	_select( buffer, dstOffset, srcOffset, t, stride ) {
52124
52125		if ( t >= 0.5 ) {
52126
52127			for ( let i = 0; i !== stride; ++ i ) {
52128
52129				buffer[ dstOffset + i ] = buffer[ srcOffset + i ];
52130
52131			}
52132
52133		}
52134
52135	}
52136
52137	_slerp( buffer, dstOffset, srcOffset, t ) {
52138
52139		Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, srcOffset, t );
52140
52141	}
52142
52143	_slerpAdditive( buffer, dstOffset, srcOffset, t, stride ) {
52144
52145		const workOffset = this._workIndex * stride;
52146
52147		// Store result in intermediate buffer offset
52148		Quaternion.multiplyQuaternionsFlat( buffer, workOffset, buffer, dstOffset, buffer, srcOffset );
52149
52150		// Slerp to the intermediate result
52151		Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, workOffset, t );
52152
52153	}
52154
52155	_lerp( buffer, dstOffset, srcOffset, t, stride ) {
52156
52157		const s = 1 - t;
52158
52159		for ( let i = 0; i !== stride; ++ i ) {
52160
52161			const j = dstOffset + i;
52162
52163			buffer[ j ] = buffer[ j ] * s + buffer[ srcOffset + i ] * t;
52164
52165		}
52166
52167	}
52168
52169	_lerpAdditive( buffer, dstOffset, srcOffset, t, stride ) {
52170
52171		for ( let i = 0; i !== stride; ++ i ) {
52172
52173			const j = dstOffset + i;
52174
52175			buffer[ j ] = buffer[ j ] + buffer[ srcOffset + i ] * t;
52176
52177		}
52178
52179	}
52180
52181}
52182
52183// Characters [].:/ are reserved for track binding syntax.
52184const _RESERVED_CHARS_RE = '\\[\\]\\.:\\/';
52185const _reservedRe = new RegExp( '[' + _RESERVED_CHARS_RE + ']', 'g' );
52186
52187// Attempts to allow node names from any language. ES5's `\w` regexp matches
52188// only latin characters, and the unicode \p{L} is not yet supported. So
52189// instead, we exclude reserved characters and match everything else.
52190const _wordChar = '[^' + _RESERVED_CHARS_RE + ']';
52191const _wordCharOrDot = '[^' + _RESERVED_CHARS_RE.replace( '\\.', '' ) + ']';
52192
52193// Parent directories, delimited by '/' or ':'. Currently unused, but must
52194// be matched to parse the rest of the track name.
52195const _directoryRe = /*@__PURE__*/ /((?:WC+[\/:])*)/.source.replace( 'WC', _wordChar );
52196
52197// Target node. May contain word characters (a-zA-Z0-9_) and '.' or '-'.
52198const _nodeRe = /*@__PURE__*/ /(WCOD+)?/.source.replace( 'WCOD', _wordCharOrDot );
52199
52200// Object on target node, and accessor. May not contain reserved
52201// characters. Accessor may contain any character except closing bracket.
52202const _objectRe = /*@__PURE__*/ /(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace( 'WC', _wordChar );
52203
52204// Property and accessor. May not contain reserved characters. Accessor may
52205// contain any non-bracket characters.
52206const _propertyRe = /*@__PURE__*/ /\.(WC+)(?:\[(.+)\])?/.source.replace( 'WC', _wordChar );
52207
52208const _trackRe = new RegExp( ''
52209	+ '^'
52210	+ _directoryRe
52211	+ _nodeRe
52212	+ _objectRe
52213	+ _propertyRe
52214	+ '$'
52215);
52216
52217const _supportedObjectNames = [ 'material', 'materials', 'bones', 'map' ];
52218
52219class Composite {
52220
52221	constructor( targetGroup, path, optionalParsedPath ) {
52222
52223		const parsedPath = optionalParsedPath || PropertyBinding.parseTrackName( path );
52224
52225		this._targetGroup = targetGroup;
52226		this._bindings = targetGroup.subscribe_( path, parsedPath );
52227
52228	}
52229
52230	getValue( array, offset ) {
52231
52232		this.bind(); // bind all binding
52233
52234		const firstValidIndex = this._targetGroup.nCachedObjects_,
52235			binding = this._bindings[ firstValidIndex ];
52236
52237		// and only call .getValue on the first
52238		if ( binding !== undefined ) binding.getValue( array, offset );
52239
52240	}
52241
52242	setValue( array, offset ) {
52243
52244		const bindings = this._bindings;
52245
52246		for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {
52247
52248			bindings[ i ].setValue( array, offset );
52249
52250		}
52251
52252	}
52253
52254	bind() {
52255
52256		const bindings = this._bindings;
52257
52258		for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {
52259
52260			bindings[ i ].bind();
52261
52262		}
52263
52264	}
52265
52266	unbind() {
52267
52268		const bindings = this._bindings;
52269
52270		for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {
52271
52272			bindings[ i ].unbind();
52273
52274		}
52275
52276	}
52277
52278}
52279
52280// Note: This class uses a State pattern on a per-method basis:
52281// 'bind' sets 'this.getValue' / 'setValue' and shadows the
52282// prototype version of these methods with one that represents
52283// the bound state. When the property is not found, the methods
52284// become no-ops.
52285
52286
52287/**
52288 * This holds a reference to a real property in the scene graph; used internally.
52289 */
52290class PropertyBinding {
52291
52292	/**
52293	 * Constructs a new property binding.
52294	 *
52295	 * @param {Object} rootNode - The root node.
52296	 * @param {string} path - The path.
vendor: 6,443 bytes, lines 52297-52592
52297	 * @param {?Object} [parsedPath] - The parsed path.
52298	 */
52299	constructor( rootNode, path, parsedPath ) {
52300
52301		/**
52302		 * The object path to the animated property.
52303		 *
52304		 * @type {string}
52305		 */
52306		this.path = path;
52307
52308		/**
52309		 * An object holding information about the path.
52310		 *
52311		 * @type {Object}
52312		 */
52313		this.parsedPath = parsedPath || PropertyBinding.parseTrackName( path );
52314
52315		/**
52316		 * The object owns the animated property.
52317		 *
52318		 * @type {?Object}
52319		 */
52320		this.node = PropertyBinding.findNode( rootNode, this.parsedPath.nodeName );
52321
52322		/**
52323		 * The root node.
52324		 *
52325		 * @type {Object3D|Skeleton}
52326		 */
52327		this.rootNode = rootNode;
52328
52329		// initial state of these methods that calls 'bind'
52330		this.getValue = this._getValue_unbound;
52331		this.setValue = this._setValue_unbound;
52332
52333	}
52334
52335
52336	/**
52337	 * Factory method for creating a property binding from the given parameters.
52338	 *
52339	 * @static
52340	 * @param {Object} root - The root node.
52341	 * @param {string} path - The path.
52342	 * @param {?Object} [parsedPath] - The parsed path.
52343	 * @return {PropertyBinding|Composite} The created property binding or composite.
52344	 */
52345	static create( root, path, parsedPath ) {
52346
52347		if ( ! ( root && root.isAnimationObjectGroup ) ) {
52348
52349			return new PropertyBinding( root, path, parsedPath );
52350
52351		} else {
52352
52353			return new PropertyBinding.Composite( root, path, parsedPath );
52354
52355		}
52356
52357	}
52358
52359	/**
52360	 * Replaces spaces with underscores and removes unsupported characters from
52361	 * node names, to ensure compatibility with parseTrackName().
52362	 *
52363	 * @param {string} name - Node name to be sanitized.
52364	 * @return {string} The sanitized node name.
52365	 */
52366	static sanitizeNodeName( name ) {
52367
52368		return name.replace( /\s/g, '_' ).replace( _reservedRe, '' );
52369
52370	}
52371
52372	/**
52373	 * Parses the given track name (an object path to an animated property) and
52374	 * returns an object with information about the path. Matches strings in the following forms:
52375	 *
52376	 * - nodeName.property
52377	 * - nodeName.property[accessor]
52378	 * - nodeName.material.property[accessor]
52379	 * - uuid.property[accessor]
52380	 * - uuid.objectName[objectIndex].propertyName[propertyIndex]
52381	 * - parentName/nodeName.property
52382	 * - parentName/parentName/nodeName.property[index]
52383	 * - .bone[Armature.DEF_cog].position
52384	 * - scene:helium_balloon_model:helium_balloon_model.position
52385	 *
52386	 * @static
52387	 * @param {string} trackName - The track name to parse.
52388	 * @return {Object} The parsed track name as an object.
52389	 */
52390	static parseTrackName( trackName ) {
52391
52392		const matches = _trackRe.exec( trackName );
52393
52394		if ( matches === null ) {
52395
52396			throw new Error( 'PropertyBinding: Cannot parse trackName: ' + trackName );
52397
52398		}
52399
52400		const results = {
52401			// directoryName: matches[ 1 ], // (tschw) currently unused
52402			nodeName: matches[ 2 ],
52403			objectName: matches[ 3 ],
52404			objectIndex: matches[ 4 ],
52405			propertyName: matches[ 5 ], // required
52406			propertyIndex: matches[ 6 ]
52407		};
52408
52409		const lastDot = results.nodeName && results.nodeName.lastIndexOf( '.' );
52410
52411		if ( lastDot !== undefined && lastDot !== -1 ) {
52412
52413			const objectName = results.nodeName.substring( lastDot + 1 );
52414
52415			// Object names must be checked against an allowlist. Otherwise, there
52416			// is no way to parse 'foo.bar.baz': 'baz' must be a property, but
52417			// 'bar' could be the objectName, or part of a nodeName (which can
52418			// include '.' characters).
52419			if ( _supportedObjectNames.indexOf( objectName ) !== -1 ) {
52420
52421				results.nodeName = results.nodeName.substring( 0, lastDot );
52422				results.objectName = objectName;
52423
52424			}
52425
52426		}
52427
52428		if ( results.propertyName === null || results.propertyName.length === 0 ) {
52429
52430			throw new Error( 'PropertyBinding: can not parse propertyName from trackName: ' + trackName );
52431
52432		}
52433
52434		return results;
52435
52436	}
52437
52438	/**
52439	 * Searches for a node in the hierarchy of the given root object by the given
52440	 * node name.
52441	 *
52442	 * @static
52443	 * @param {Object} root - The root object.
52444	 * @param {string|number} nodeName - The name of the node.
52445	 * @return {?Object} The found node. Returns `null` if no object was found.
52446	 */
52447	static findNode( root, nodeName ) {
52448
52449		if ( nodeName === undefined || nodeName === '' || nodeName === '.' || nodeName === -1 || nodeName === root.name || nodeName === root.uuid ) {
52450
52451			return root;
52452
52453		}
52454
52455		// search into skeleton bones.
52456		if ( root.skeleton ) {
52457
52458			const bone = root.skeleton.getBoneByName( nodeName );
52459
52460			if ( bone !== undefined ) {
52461
52462				return bone;
52463
52464			}
52465
52466		}
52467
52468		// search into node subtree.
52469		if ( root.children ) {
52470
52471			const searchNodeSubtree = function ( children ) {
52472
52473				for ( let i = 0; i < children.length; i ++ ) {
52474
52475					const childNode = children[ i ];
52476
52477					if ( childNode.name === nodeName || childNode.uuid === nodeName ) {
52478
52479						return childNode;
52480
52481					}
52482
52483					const result = searchNodeSubtree( childNode.children );
52484
52485					if ( result ) return result;
52486
52487				}
52488
52489				return null;
52490
52491			};
52492
52493			const subTreeNode = searchNodeSubtree( root.children );
52494
52495			if ( subTreeNode ) {
52496
52497				return subTreeNode;
52498
52499			}
52500
52501		}
52502
52503		return null;
52504
52505	}
52506
52507	// these are used to "bind" a nonexistent property
52508	_getValue_unavailable() {}
52509	_setValue_unavailable() {}
52510
52511	// Getters
52512
52513	_getValue_direct( buffer, offset ) {
52514
52515		buffer[ offset ] = this.targetObject[ this.propertyName ];
52516
52517	}
52518
52519	_getValue_array( buffer, offset ) {
52520
52521		const source = this.resolvedProperty;
52522
52523		for ( let i = 0, n = source.length; i !== n; ++ i ) {
52524
52525			buffer[ offset ++ ] = source[ i ];
52526
52527		}
52528
52529	}
52530
52531	_getValue_arrayElement( buffer, offset ) {
52532
52533		buffer[ offset ] = this.resolvedProperty[ this.propertyIndex ];
52534
52535	}
52536
52537	_getValue_toArray( buffer, offset ) {
52538
52539		this.resolvedProperty.toArray( buffer, offset );
52540
52541	}
52542
52543	// Direct
52544
52545	_setValue_direct( buffer, offset ) {
52546
52547		this.targetObject[ this.propertyName ] = buffer[ offset ];
52548
52549	}
52550
52551	_setValue_direct_setNeedsUpdate( buffer, offset ) {
52552
52553		this.targetObject[ this.propertyName ] = buffer[ offset ];
52554		this.targetObject.needsUpdate = true;
52555
52556	}
52557
52558	_setValue_direct_setMatrixWorldNeedsUpdate( buffer, offset ) {
52559
52560		this.targetObject[ this.propertyName ] = buffer[ offset ];
52561		this.targetObject.matrixWorldNeedsUpdate = true;
52562
52563	}
52564
52565	// EntireArray
52566
52567	_setValue_array( buffer, offset ) {
52568
52569		const dest = this.resolvedProperty;
52570
52571		for ( let i = 0, n = dest.length; i !== n; ++ i ) {
52572
52573			dest[ i ] = buffer[ offset ++ ];
52574
52575		}
52576
52577	}
52578
52579	_setValue_array_setNeedsUpdate( buffer, offset ) {
52580
52581		const dest = this.resolvedProperty;
52582
52583		for ( let i = 0, n = dest.length; i !== n; ++ i ) {
52584
52585			dest[ i ] = buffer[ offset ++ ];
52586
52587		}
52588
52589		this.targetObject.needsUpdate = true;
52590
52591	}
52592
vendor: 15,184 bytes, lines 52593-53247
52593	_setValue_array_setMatrixWorldNeedsUpdate( buffer, offset ) {
52594
52595		const dest = this.resolvedProperty;
52596
52597		for ( let i = 0, n = dest.length; i !== n; ++ i ) {
52598
52599			dest[ i ] = buffer[ offset ++ ];
52600
52601		}
52602
52603		this.targetObject.matrixWorldNeedsUpdate = true;
52604
52605	}
52606
52607	// ArrayElement
52608
52609	_setValue_arrayElement( buffer, offset ) {
52610
52611		this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
52612
52613	}
52614
52615	_setValue_arrayElement_setNeedsUpdate( buffer, offset ) {
52616
52617		this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
52618		this.targetObject.needsUpdate = true;
52619
52620	}
52621
52622	_setValue_arrayElement_setMatrixWorldNeedsUpdate( buffer, offset ) {
52623
52624		this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
52625		this.targetObject.matrixWorldNeedsUpdate = true;
52626
52627	}
52628
52629	// HasToFromArray
52630
52631	_setValue_fromArray( buffer, offset ) {
52632
52633		this.resolvedProperty.fromArray( buffer, offset );
52634
52635	}
52636
52637	_setValue_fromArray_setNeedsUpdate( buffer, offset ) {
52638
52639		this.resolvedProperty.fromArray( buffer, offset );
52640		this.targetObject.needsUpdate = true;
52641
52642	}
52643
52644	_setValue_fromArray_setMatrixWorldNeedsUpdate( buffer, offset ) {
52645
52646		this.resolvedProperty.fromArray( buffer, offset );
52647		this.targetObject.matrixWorldNeedsUpdate = true;
52648
52649	}
52650
52651	_getValue_unbound( targetArray, offset ) {
52652
52653		this.bind();
52654		this.getValue( targetArray, offset );
52655
52656	}
52657
52658	_setValue_unbound( sourceArray, offset ) {
52659
52660		this.bind();
52661		this.setValue( sourceArray, offset );
52662
52663	}
52664
52665	/**
52666	 * Creates a getter / setter pair for the property tracked by this binding.
52667	 */
52668	bind() {
52669
52670		let targetObject = this.node;
52671		const parsedPath = this.parsedPath;
52672
52673		const objectName = parsedPath.objectName;
52674		const propertyName = parsedPath.propertyName;
52675		let propertyIndex = parsedPath.propertyIndex;
52676
52677		if ( ! targetObject ) {
52678
52679			targetObject = PropertyBinding.findNode( this.rootNode, parsedPath.nodeName );
52680
52681			this.node = targetObject;
52682
52683		}
52684
52685		// set fail state so we can just 'return' on error
52686		this.getValue = this._getValue_unavailable;
52687		this.setValue = this._setValue_unavailable;
52688
52689		// ensure there is a value node
52690		if ( ! targetObject ) {
52691
52692			warn( 'PropertyBinding: No target node found for track: ' + this.path + '.' );
52693			return;
52694
52695		}
52696
52697		if ( objectName ) {
52698
52699			let objectIndex = parsedPath.objectIndex;
52700
52701			// special cases were we need to reach deeper into the hierarchy to get the face materials....
52702			switch ( objectName ) {
52703
52704				case 'materials':
52705
52706					if ( ! targetObject.material ) {
52707
52708						error( 'PropertyBinding: Can not bind to material as node does not have a material.', this );
52709						return;
52710
52711					}
52712
52713					if ( ! targetObject.material.materials ) {
52714
52715						error( 'PropertyBinding: Can not bind to material.materials as node.material does not have a materials array.', this );
52716						return;
52717
52718					}
52719
52720					targetObject = targetObject.material.materials;
52721
52722					break;
52723
52724				case 'bones':
52725
52726					if ( ! targetObject.skeleton ) {
52727
52728						error( 'PropertyBinding: Can not bind to bones as node does not have a skeleton.', this );
52729						return;
52730
52731					}
52732
52733					// potential future optimization: skip this if propertyIndex is already an integer
52734					// and convert the integer string to a true integer.
52735
52736					targetObject = targetObject.skeleton.bones;
52737
52738					// support resolving morphTarget names into indices.
52739					for ( let i = 0; i < targetObject.length; i ++ ) {
52740
52741						if ( targetObject[ i ].name === objectIndex ) {
52742
52743							objectIndex = i;
52744							break;
52745
52746						}
52747
52748					}
52749
52750					break;
52751
52752				case 'map':
52753
52754					if ( 'map' in targetObject ) {
52755
52756						targetObject = targetObject.map;
52757						break;
52758
52759					}
52760
52761					if ( ! targetObject.material ) {
52762
52763						error( 'PropertyBinding: Can not bind to material as node does not have a material.', this );
52764						return;
52765
52766					}
52767
52768					if ( ! targetObject.material.map ) {
52769
52770						error( 'PropertyBinding: Can not bind to material.map as node.material does not have a map.', this );
52771						return;
52772
52773					}
52774
52775					targetObject = targetObject.material.map;
52776					break;
52777
52778				default:
52779
52780					if ( targetObject[ objectName ] === undefined ) {
52781
52782						error( 'PropertyBinding: Can not bind to objectName of node undefined.', this );
52783						return;
52784
52785					}
52786
52787					targetObject = targetObject[ objectName ];
52788
52789			}
52790
52791
52792			if ( objectIndex !== undefined ) {
52793
52794				if ( targetObject[ objectIndex ] === undefined ) {
52795
52796					error( 'PropertyBinding: Trying to bind to objectIndex of objectName, but is undefined.', this, targetObject );
52797					return;
52798
52799				}
52800
52801				targetObject = targetObject[ objectIndex ];
52802
52803			}
52804
52805		}
52806
52807		// resolve property
52808		const nodeProperty = targetObject[ propertyName ];
52809
52810		if ( nodeProperty === undefined ) {
52811
52812			const nodeName = parsedPath.nodeName;
52813
52814			error( 'PropertyBinding: Trying to update property for track: ' + nodeName +
52815				'.' + propertyName + ' but it wasn\'t found.', targetObject );
52816			return;
52817
52818		}
52819
52820		// determine versioning scheme
52821		let versioning = this.Versioning.None;
52822
52823		this.targetObject = targetObject;
52824
52825		if ( targetObject.isMaterial === true ) {
52826
52827			versioning = this.Versioning.NeedsUpdate;
52828
52829		} else if ( targetObject.isObject3D === true ) {
52830
52831			versioning = this.Versioning.MatrixWorldNeedsUpdate;
52832
52833		}
52834
52835		// determine how the property gets bound
52836		let bindingType = this.BindingType.Direct;
52837
52838		if ( propertyIndex !== undefined ) {
52839
52840			// access a sub element of the property array (only primitives are supported right now)
52841
52842			if ( propertyName === 'morphTargetInfluences' ) {
52843
52844				// potential optimization, skip this if propertyIndex is already an integer, and convert the integer string to a true integer.
52845
52846				// support resolving morphTarget names into indices.
52847				if ( ! targetObject.geometry ) {
52848
52849					error( 'PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.', this );
52850					return;
52851
52852				}
52853
52854				if ( ! targetObject.geometry.morphAttributes ) {
52855
52856					error( 'PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphAttributes.', this );
52857					return;
52858
52859				}
52860
52861				if ( targetObject.morphTargetDictionary[ propertyIndex ] !== undefined ) {
52862
52863					propertyIndex = targetObject.morphTargetDictionary[ propertyIndex ];
52864
52865				}
52866
52867			}
52868
52869			bindingType = this.BindingType.ArrayElement;
52870
52871			this.resolvedProperty = nodeProperty;
52872			this.propertyIndex = propertyIndex;
52873
52874		} else if ( nodeProperty.fromArray !== undefined && nodeProperty.toArray !== undefined ) {
52875
52876			// must use copy for Object3D.Euler/Quaternion
52877
52878			bindingType = this.BindingType.HasFromToArray;
52879
52880			this.resolvedProperty = nodeProperty;
52881
52882		} else if ( Array.isArray( nodeProperty ) ) {
52883
52884			bindingType = this.BindingType.EntireArray;
52885
52886			this.resolvedProperty = nodeProperty;
52887
52888		} else {
52889
52890			this.propertyName = propertyName;
52891
52892		}
52893
52894		// select getter / setter
52895		this.getValue = this.GetterByBindingType[ bindingType ];
52896		this.setValue = this.SetterByBindingTypeAndVersioning[ bindingType ][ versioning ];
52897
52898	}
52899
52900	/**
52901	 * Unbinds the property.
52902	 */
52903	unbind() {
52904
52905		this.node = null;
52906
52907		// back to the prototype version of getValue / setValue
52908		// note: avoiding to mutate the shape of 'this' via 'delete'
52909		this.getValue = this._getValue_unbound;
52910		this.setValue = this._setValue_unbound;
52911
52912	}
52913
52914}
52915
52916PropertyBinding.Composite = Composite;
52917
52918PropertyBinding.prototype.BindingType = {
52919	Direct: 0,
52920	EntireArray: 1,
52921	ArrayElement: 2,
52922	HasFromToArray: 3
52923};
52924
52925PropertyBinding.prototype.Versioning = {
52926	None: 0,
52927	NeedsUpdate: 1,
52928	MatrixWorldNeedsUpdate: 2
52929};
52930
52931PropertyBinding.prototype.GetterByBindingType = [
52932
52933	PropertyBinding.prototype._getValue_direct,
52934	PropertyBinding.prototype._getValue_array,
52935	PropertyBinding.prototype._getValue_arrayElement,
52936	PropertyBinding.prototype._getValue_toArray,
52937
52938];
52939
52940PropertyBinding.prototype.SetterByBindingTypeAndVersioning = [
52941
52942	[
52943		// Direct
52944		PropertyBinding.prototype._setValue_direct,
52945		PropertyBinding.prototype._setValue_direct_setNeedsUpdate,
52946		PropertyBinding.prototype._setValue_direct_setMatrixWorldNeedsUpdate,
52947
52948	], [
52949
52950		// EntireArray
52951
52952		PropertyBinding.prototype._setValue_array,
52953		PropertyBinding.prototype._setValue_array_setNeedsUpdate,
52954		PropertyBinding.prototype._setValue_array_setMatrixWorldNeedsUpdate,
52955
52956	], [
52957
52958		// ArrayElement
52959		PropertyBinding.prototype._setValue_arrayElement,
52960		PropertyBinding.prototype._setValue_arrayElement_setNeedsUpdate,
52961		PropertyBinding.prototype._setValue_arrayElement_setMatrixWorldNeedsUpdate,
52962
52963	], [
52964
52965		// HasToFromArray
52966		PropertyBinding.prototype._setValue_fromArray,
52967		PropertyBinding.prototype._setValue_fromArray_setNeedsUpdate,
52968		PropertyBinding.prototype._setValue_fromArray_setMatrixWorldNeedsUpdate,
52969
52970	]
52971
52972];
52973
52974/**
52975 * A group of objects that receives a shared animation state.
52976 *
52977 * Usage:
52978 *
52979 * - Add objects you would otherwise pass as 'root' to the
52980 * constructor or the .clipAction method of AnimationMixer.
52981 * - Instead pass this object as 'root'.
52982 * - You can also add and remove objects later when the mixer is running.
52983 *
52984 * Note:
52985 *
52986 * - Objects of this class appear as one object to the mixer,
52987 * so cache control of the individual objects must be done on the group.
52988 *
52989 * Limitation:
52990 *
52991 * - The animated properties must be compatible among the all objects in the group.
52992 * - A single property can either be controlled through a target group or directly, but not both.
52993 */
52994class AnimationObjectGroup {
52995
52996	/**
52997	 * Constructs a new animation group.
52998	 *
52999	 * @param {...Object3D} arguments - An arbitrary number of 3D objects that share the same animation state.
53000	 */
53001	constructor() {
53002
53003		/**
53004		 * This flag can be used for type testing.
53005		 *
53006		 * @type {boolean}
53007		 * @readonly
53008		 * @default true
53009		 */
53010		this.isAnimationObjectGroup = true;
53011
53012		/**
53013		 * The UUID of the 3D object.
53014		 *
53015		 * @type {string}
53016		 * @readonly
53017		 */
53018		this.uuid = generateUUID();
53019
53020		// cached objects followed by the active ones
53021		this._objects = Array.prototype.slice.call( arguments );
53022
53023		this.nCachedObjects_ = 0; // threshold
53024		// note: read by PropertyBinding.Composite
53025
53026		const indices = {};
53027		this._indicesByUUID = indices; // for bookkeeping
53028
53029		for ( let i = 0, n = arguments.length; i !== n; ++ i ) {
53030
53031			indices[ arguments[ i ].uuid ] = i;
53032
53033		}
53034
53035		this._paths = []; // inside: string
53036		this._parsedPaths = []; // inside: { we don't care, here }
53037		this._bindings = []; // inside: Array< PropertyBinding >
53038		this._bindingsIndicesByPath = {}; // inside: indices in these arrays
53039
53040		const scope = this;
53041
53042		this.stats = {
53043
53044			objects: {
53045				get total() {
53046
53047					return scope._objects.length;
53048
53049				},
53050				get inUse() {
53051
53052					return this.total - scope.nCachedObjects_;
53053
53054				}
53055			},
53056			get bindingsPerObject() {
53057
53058				return scope._bindings.length;
53059
53060			}
53061
53062		};
53063
53064	}
53065
53066	/**
53067	 * Adds an arbitrary number of objects to this animation group.
53068	 *
53069	 * @param {...Object3D} arguments - The 3D objects to add.
53070	 */
53071	add() {
53072
53073		const objects = this._objects,
53074			indicesByUUID = this._indicesByUUID,
53075			paths = this._paths,
53076			parsedPaths = this._parsedPaths,
53077			bindings = this._bindings,
53078			nBindings = bindings.length;
53079
53080		let knownObject = undefined,
53081			nObjects = objects.length,
53082			nCachedObjects = this.nCachedObjects_;
53083
53084		for ( let i = 0, n = arguments.length; i !== n; ++ i ) {
53085
53086			const object = arguments[ i ],
53087				uuid = object.uuid;
53088			let index = indicesByUUID[ uuid ];
53089
53090			if ( index === undefined ) {
53091
53092				// unknown object -> add it to the ACTIVE region
53093
53094				index = nObjects ++;
53095				indicesByUUID[ uuid ] = index;
53096				objects.push( object );
53097
53098				// accounting is done, now do the same for all bindings
53099
53100				for ( let j = 0, m = nBindings; j !== m; ++ j ) {
53101
53102					bindings[ j ].push( new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ) );
53103
53104				}
53105
53106			} else if ( index < nCachedObjects ) {
53107
53108				knownObject = objects[ index ];
53109
53110				// move existing object to the ACTIVE region
53111
53112				const firstActiveIndex = -- nCachedObjects,
53113					lastCachedObject = objects[ firstActiveIndex ];
53114
53115				indicesByUUID[ lastCachedObject.uuid ] = index;
53116				objects[ index ] = lastCachedObject;
53117
53118				indicesByUUID[ uuid ] = firstActiveIndex;
53119				objects[ firstActiveIndex ] = object;
53120
53121				// accounting is done, now do the same for all bindings
53122
53123				for ( let j = 0, m = nBindings; j !== m; ++ j ) {
53124
53125					const bindingsForPath = bindings[ j ],
53126						lastCached = bindingsForPath[ firstActiveIndex ];
53127
53128					let binding = bindingsForPath[ index ];
53129
53130					bindingsForPath[ index ] = lastCached;
53131
53132					if ( binding === undefined ) {
53133
53134						// since we do not bother to create new bindings
53135						// for objects that are cached, the binding may
53136						// or may not exist
53137
53138						binding = new PropertyBinding( object, paths[ j ], parsedPaths[ j ] );
53139
53140					}
53141
53142					bindingsForPath[ firstActiveIndex ] = binding;
53143
53144				}
53145
53146			} else if ( objects[ index ] !== knownObject ) {
53147
53148				error( 'AnimationObjectGroup: Different objects with the same UUID ' +
53149					'detected. Clean the caches or recreate your infrastructure when reloading scenes.' );
53150
53151			} // else the object is already where we want it to be
53152
53153		} // for arguments
53154
53155		this.nCachedObjects_ = nCachedObjects;
53156
53157	}
53158
53159	/**
53160	 * Removes an arbitrary number of objects to this animation group
53161	 *
53162	 * @param {...Object3D} arguments - The 3D objects to remove.
53163	 */
53164	remove() {
53165
53166		const objects = this._objects,
53167			indicesByUUID = this._indicesByUUID,
53168			bindings = this._bindings,
53169			nBindings = bindings.length;
53170
53171		let nCachedObjects = this.nCachedObjects_;
53172
53173		for ( let i = 0, n = arguments.length; i !== n; ++ i ) {
53174
53175			const object = arguments[ i ],
53176				uuid = object.uuid,
53177				index = indicesByUUID[ uuid ];
53178
53179			if ( index !== undefined && index >= nCachedObjects ) {
53180
53181				// move existing object into the CACHED region
53182
53183				const lastCachedIndex = nCachedObjects ++,
53184					firstActiveObject = objects[ lastCachedIndex ];
53185
53186				indicesByUUID[ firstActiveObject.uuid ] = index;
53187				objects[ index ] = firstActiveObject;
53188
53189				indicesByUUID[ uuid ] = lastCachedIndex;
53190				objects[ lastCachedIndex ] = object;
53191
53192				// accounting is done, now do the same for all bindings
53193
53194				for ( let j = 0, m = nBindings; j !== m; ++ j ) {
53195
53196					const bindingsForPath = bindings[ j ],
53197						firstActive = bindingsForPath[ lastCachedIndex ],
53198						binding = bindingsForPath[ index ];
53199
53200					bindingsForPath[ index ] = firstActive;
53201					bindingsForPath[ lastCachedIndex ] = binding;
53202
53203				}
53204
53205			}
53206
53207		} // for arguments
53208
53209		this.nCachedObjects_ = nCachedObjects;
53210
53211	}
53212
53213	/**
53214	 * Deallocates all memory resources for the passed 3D objects of this animation group.
53215	 *
53216	 * @param {...Object3D} arguments - The 3D objects to uncache.
53217	 */
53218	uncache() {
53219
53220		const objects = this._objects,
53221			indicesByUUID = this._indicesByUUID,
53222			bindings = this._bindings,
53223			nBindings = bindings.length;
53224
53225		let nCachedObjects = this.nCachedObjects_,
53226			nObjects = objects.length;
53227
53228		for ( let i = 0, n = arguments.length; i !== n; ++ i ) {
53229
53230			const object = arguments[ i ],
53231				uuid = object.uuid,
53232				index = indicesByUUID[ uuid ];
53233
53234			if ( index !== undefined ) {
53235
53236				delete indicesByUUID[ uuid ];
53237
53238				if ( index < nCachedObjects ) {
53239
53240					// object is cached, shrink the CACHED region
53241
53242					const firstActiveIndex = -- nCachedObjects,
53243						lastCachedObject = objects[ firstActiveIndex ],
53244						lastIndex = -- nObjects,
53245						lastObject = objects[ lastIndex ];
53246
53247					
53247// last cached object takes this object's place
53248					indicesByUUID[ lastCachedObject.uuid ] = index;
53249					objects[ index ] = lastCachedObject;
53250
53251					// last object goes to the activated slot and pop
53252					indicesByUUID[ lastObject.uuid ] = firstActiveIndex;
53253					objects[ firstActiveIndex ] = lastObject;
53254					objects.pop();
53255
53256					// accounting is done, now do the same for all bindings
53257
53258					for ( let j = 0, m = nBindings; j !== m; ++ j ) {
53259
53260						const bindingsForPath = bindings[ j ],
53261							lastCached = bindingsForPath[ firstActiveIndex ],
53262							last = bindingsForPath[ lastIndex ];
53263
53264						bindingsForPath[ index ] = lastCached;
53265						bindingsForPath[ firstActiveIndex ] = last;
53266						bindingsForPath.pop();
53267
53268					}
53269
53270				} else {
53271
53272					// object is active, just swap with the last and pop
53273
53274					const lastIndex = -- nObjects,
53275						lastObject = objects[ lastIndex ];
53276
53277					if ( lastIndex > 0 ) {
53278
53279						indicesByUUID[ lastObject.uuid ] = index;
53280
53281					}
53282
53283					objects[ index ] = lastObject;
53284					objects.pop();
53285
53286					// accounting is done, now do the same for all bindings
53287
53288					for ( let j = 0, m = nBindings; j !== m; ++ j ) {
53289
vendor: 3,925 bytes, lines 53290-53444
53290						const bindingsForPath = bindings[ j ];
53291
53292						bindingsForPath[ index ] = bindingsForPath[ lastIndex ];
53293						bindingsForPath.pop();
53294
53295					}
53296
53297				} // cached or active
53298
53299			} // if object is known
53300
53301		} // for arguments
53302
53303		this.nCachedObjects_ = nCachedObjects;
53304
53305	}
53306
53307	// Internal interface used by befriended PropertyBinding.Composite:
53308
53309	subscribe_( path, parsedPath ) {
53310
53311		// returns an array of bindings for the given path that is changed
53312		// according to the contained objects in the group
53313
53314		const indicesByPath = this._bindingsIndicesByPath;
53315		let index = indicesByPath[ path ];
53316		const bindings = this._bindings;
53317
53318		if ( index !== undefined ) return bindings[ index ];
53319
53320		const paths = this._paths,
53321			parsedPaths = this._parsedPaths,
53322			objects = this._objects,
53323			nObjects = objects.length,
53324			nCachedObjects = this.nCachedObjects_,
53325			bindingsForPath = new Array( nObjects );
53326
53327		index = bindings.length;
53328
53329		indicesByPath[ path ] = index;
53330
53331		paths.push( path );
53332		parsedPaths.push( parsedPath );
53333		bindings.push( bindingsForPath );
53334
53335		for ( let i = nCachedObjects, n = objects.length; i !== n; ++ i ) {
53336
53337			const object = objects[ i ];
53338			bindingsForPath[ i ] = new PropertyBinding( object, path, parsedPath );
53339
53340		}
53341
53342		return bindingsForPath;
53343
53344	}
53345
53346	unsubscribe_( path ) {
53347
53348		// tells the group to forget about a property path and no longer
53349		// update the array previously obtained with 'subscribe_'
53350
53351		const indicesByPath = this._bindingsIndicesByPath,
53352			index = indicesByPath[ path ];
53353
53354		if ( index !== undefined ) {
53355
53356			const paths = this._paths,
53357				parsedPaths = this._parsedPaths,
53358				bindings = this._bindings,
53359				lastBindingsIndex = bindings.length - 1,
53360				lastBindings = bindings[ lastBindingsIndex ],
53361				lastBindingsPath = path[ lastBindingsIndex ];
53362
53363			indicesByPath[ lastBindingsPath ] = index;
53364
53365			bindings[ index ] = lastBindings;
53366			bindings.pop();
53367
53368			parsedPaths[ index ] = parsedPaths[ lastBindingsIndex ];
53369			parsedPaths.pop();
53370
53371			paths[ index ] = paths[ lastBindingsIndex ];
53372			paths.pop();
53373
53374		}
53375
53376	}
53377
53378}
53379
53380/**
53381 * An instance of `AnimationAction` schedules the playback of an animation which is
53382 * stored in {@link AnimationClip}.
53383 */
53384class AnimationAction {
53385
53386	/**
53387	 * Constructs a new animation action.
53388	 *
53389	 * @param {AnimationMixer} mixer - The mixer that is controlled by this action.
53390	 * @param {AnimationClip} clip - The animation clip that holds the actual keyframes.
53391	 * @param {?Object3D} [localRoot=null] - The root object on which this action is performed.
53392	 * @param {(NormalAnimationBlendMode|AdditiveAnimationBlendMode)} [blendMode] - The blend mode.
53393	 */
53394	constructor( mixer, clip, localRoot = null, blendMode = clip.blendMode ) {
53395
53396		this._mixer = mixer;
53397		this._clip = clip;
53398		this._localRoot = localRoot;
53399
53400		/**
53401		 * Defines how the animation is blended/combined when two or more animations
53402		 * are simultaneously played.
53403		 *
53404		 * @type {(NormalAnimationBlendMode|AdditiveAnimationBlendMode)}
53405		 */
53406		this.blendMode = blendMode;
53407
53408		const tracks = clip.tracks,
53409			nTracks = tracks.length,
53410			interpolants = new Array( nTracks );
53411
53412		const interpolantSettings = {
53413			endingStart: ZeroCurvatureEnding,
53414			endingEnd: ZeroCurvatureEnding
53415		};
53416
53417		for ( let i = 0; i !== nTracks; ++ i ) {
53418
53419			const interpolant = tracks[ i ].createInterpolant( null );
53420			interpolants[ i ] = interpolant;
53421
53422			// preserve interpolant settings (like tangent data from BezierInterpolant)
53423
53424			if ( interpolant.settings ) {
53425
53426				Object.assign( interpolantSettings, interpolant.settings );
53427
53428			}
53429
53430			interpolant.settings = interpolantSettings;
53431
53432		}
53433
53434		this._interpolantSettings = interpolantSettings;
53435
53436		this._interpolants = interpolants; // bound by the mixer
53437
53438		// inside: PropertyMixer (managed by the mixer)
53439		this._propertyBindings = new Array( nTracks );
53440
53441		this._cacheIndex = null; // for the memory manager
53442		this._byClipCacheIndex = null; // for the memory manager
53443
53444		this._timeScaleInterpolant
vendor: 6,016 bytes, lines 53444-53709
53444 = null;
53445		this._weightInterpolant = null;
53446
53447		/**
53448		 * The loop mode, set via {@link AnimationAction#setLoop}.
53449		 *
53450		 * @type {(LoopRepeat|LoopOnce|LoopPingPong)}
53451		 * @default LoopRepeat
53452		 */
53453		this.loop = LoopRepeat;
53454		this._loopCount = -1;
53455
53456		// global mixer time when the action is to be started
53457		// it's set back to 'null' upon start of the action
53458		this._startTime = null;
53459
53460		/**
53461		 * The local time of this action (in seconds, starting with `0`).
53462		 *
53463		 * The value gets clamped or wrapped to `[0,clip.duration]` (according to the
53464		 * loop state).
53465		 *
53466		 * @type {number}
53467		 * @default Infinity
53468		 */
53469		this.time = 0;
53470
53471		/**
53472		 * Scaling factor for the {@link AnimationAction#time}. A value of `0` causes the
53473		 * animation to pause. Negative values cause the animation to play backwards.
53474		 *
53475		 * @type {number}
53476		 * @default 1
53477		 */
53478		this.timeScale = 1;
53479		this._effectiveTimeScale = 1;
53480
53481		/**
53482		 * The degree of influence of this action (in the interval `[0, 1]`). Values
53483		 * between `0` (no impact) and `1` (full impact) can be used to blend between
53484		 * several actions.
53485		 *
53486		 * @type {number}
53487		 * @default 1
53488		 */
53489		this.weight = 1;
53490		this._effectiveWeight = 1;
53491
53492		/**
53493		 * The number of repetitions of the performed clip over the course of this action.
53494		 * Can be set via {@link AnimationAction#setLoop}.
53495		 *
53496		 * Setting this number has no effect if {@link AnimationAction#loop} is set to
53497		 * `THREE:LoopOnce`.
53498		 *
53499		 * @type {number}
53500		 * @default Infinity
53501		 */
53502		this.repetitions = Infinity;
53503
53504		/**
53505		 * If set to `true`, the playback of the action is paused.
53506		 *
53507		 * @type {boolean}
53508		 * @default false
53509		 */
53510		this.paused = false;
53511
53512		/**
53513		 * If set to `false`, the action is disabled so it has no impact.
53514		 *
53515		 * When the action is re-enabled, the animation continues from its current
53516		 * time (setting `enabled` to `false` doesn't reset the action).
53517		 *
53518		 * @type {boolean}
53519		 * @default true
53520		 */
53521		this.enabled = true;
53522
53523		/**
53524		 * If set to true the animation will automatically be paused on its last frame.
53525		 *
53526		 * If set to false, {@link AnimationAction#enabled} will automatically be switched
53527		 * to `false` when the last loop of the action has finished, so that this action has
53528		 * no further impact.
53529		 *
53530		 * Note: This member has no impact if the action is interrupted (it
53531		 * has only an effect if its last loop has really finished).
53532		 *
53533		 * @type {boolean}
53534		 * @default false
53535		 */
53536		this.clampWhenFinished = false;
53537
53538		/**
53539		 * Enables smooth interpolation without separate clips for start, loop and end.
53540		 *
53541		 * @type {boolean}
53542		 * @default true
53543		 */
53544		this.zeroSlopeAtStart = true;
53545
53546		/**
53547		 * Enables smooth interpolation without separate clips for start, loop and end.
53548		 *
53549		 * @type {boolean}
53550		 * @default true
53551		 */
53552		this.zeroSlopeAtEnd = true;
53553
53554	}
53555
53556	/**
53557	 * Starts the playback of the animation.
53558	 *
53559	 * @return {AnimationAction} A reference to this animation action.
53560	 */
53561	play() {
53562
53563		this._mixer._activateAction( this );
53564
53565		return this;
53566
53567	}
53568
53569	/**
53570	 * Stops the playback of the animation.
53571	 *
53572	 * @return {AnimationAction} A reference to this animation action.
53573	 */
53574	stop() {
53575
53576		this._mixer._deactivateAction( this );
53577
53578		return this.reset();
53579
53580	}
53581
53582	/**
53583	 * Resets the playback of the animation.
53584	 *
53585	 * @return {AnimationAction} A reference to this animation action.
53586	 */
53587	reset() {
53588
53589		this.paused = false;
53590		this.enabled = true;
53591
53592		this.time = 0; // restart clip
53593		this._loopCount = -1;// forget previous loops
53594		this._startTime = null;// forget scheduling
53595
53596		return this.stopFading().stopWarping();
53597
53598	}
53599
53600	/**
53601	 * Returns `true` if the animation is running.
53602	 *
53603	 * @return {boolean} Whether the animation is running or not.
53604	 */
53605	isRunning() {
53606
53607		return this.enabled && ! this.paused && this.timeScale !== 0 &&
53608			this._startTime === null && this._mixer._isActiveAction( this );
53609
53610	}
53611
53612	/**
53613	 * Returns `true` when {@link AnimationAction#play} has been called.
53614	 *
53615	 * @return {boolean} Whether the animation is scheduled or not.
53616	 */
53617	isScheduled() {
53618
53619		return this._mixer._isActiveAction( this );
53620
53621	}
53622
53623	/**
53624	 * Defines the time when the animation should start.
53625	 *
53626	 * @param {number} time - The start time in seconds.
53627	 * @return {AnimationAction} A reference to this animation action.
53628	 */
53629	startAt( time ) {
53630
53631		this._startTime = time;
53632
53633		return this;
53634
53635	}
53636
53637	/**
53638	 * Configures the loop settings for this action.
53639	 *
53640	 * @param {(LoopRepeat|LoopOnce|LoopPingPong)} mode - The loop mode.
53641	 * @param {number} repetitions - The number of repetitions.
53642	 * @return {AnimationAction} A reference to this animation action.
53643	 */
53644	setLoop( mode, repetitions ) {
53645
53646		this.loop = mode;
53647		this.repetitions = repetitions;
53648
53649		return this;
53650
53651	}
53652
53653	/**
53654	 * Sets the effective weight of this action.
53655	 *
53656	 * An action has no effect and thus an effective weight of zero when the
53657	 * action is disabled.
53658	 *
53659	 * @param {number} weight - The weight to set.
53660	 * @return {AnimationAction} A reference to this animation action.
53661	 */
53662	setEffectiveWeight( weight ) {
53663
53664		this.weight = weight;
53665
53666		// note: same logic as when updated at runtime
53667		this._effectiveWeight = this.enabled ? weight : 0;
53668
53669		return this.stopFading();
53670
53671	}
53672
53673	/**
53674	 * Returns the effective weight of this action.
53675	 *
53676	 * @return {number} The effective weight.
53677	 */
53678	getEffectiveWeight() {
53679
53680		return this._effectiveWeight;
53681
53682	}
53683
53684	/**
53685	 * Fades the animation in by increasing its weight gradually from `0` to `1`,
53686	 * within the passed time interval.
53687	 *
53688	 * @param {number} duration - The duration of the fade.
53689	 * @return {AnimationAction} A reference to this animation action.
53690	 */
53691	fadeIn( duration ) {
53692
53693		return this._scheduleFading( duration, 0, 1 );
53694
53695	}
53696
53697	/**
53698	 * Fades the animation out by decreasing its weight gradually from `1` to `0`,
53699	 * within the passed time interval.
53700	 *
53701	 * @param {number} duration - The duration of the fade.
53702	 * @return {AnimationAction} A reference to this animation action.
53703	 */
53704	fadeOut( duration ) {
53705
53706		return this._scheduleFading( duration, 1, 0 );
53707
53708	}
53709
vendor: 10,343 bytes, lines 53710-54236
53710	/**
53711	 * Causes this action to fade in and the given action to fade out,
53712	 * within the passed time interval.
53713	 *
53714	 * @param {AnimationAction} fadeOutAction - The animation action to fade out.
53715	 * @param {number} duration - The duration of the fade.
53716	 * @param {boolean} [warp=false] - Whether warping should be used or not.
53717	 * @return {AnimationAction} A reference to this animation action.
53718	 */
53719	crossFadeFrom( fadeOutAction, duration, warp = false ) {
53720
53721		fadeOutAction.fadeOut( duration );
53722		this.fadeIn( duration );
53723
53724		if ( warp === true ) {
53725
53726			const fadeInDuration = this._clip.duration,
53727				fadeOutDuration = fadeOutAction._clip.duration,
53728
53729				startEndRatio = fadeOutDuration / fadeInDuration,
53730				endStartRatio = fadeInDuration / fadeOutDuration;
53731
53732			fadeOutAction.warp( 1.0, startEndRatio, duration );
53733			this.warp( endStartRatio, 1.0, duration );
53734
53735		}
53736
53737		return this;
53738
53739	}
53740
53741	/**
53742	 * Causes this action to fade out and the given action to fade in,
53743	 * within the passed time interval.
53744	 *
53745	 * @param {AnimationAction} fadeInAction - The animation action to fade in.
53746	 * @param {number} duration - The duration of the fade.
53747	 * @param {boolean} [warp=false] - Whether warping should be used or not.
53748	 * @return {AnimationAction} A reference to this animation action.
53749	 */
53750	crossFadeTo( fadeInAction, duration, warp = false ) {
53751
53752		return fadeInAction.crossFadeFrom( this, duration, warp );
53753
53754	}
53755
53756	/**
53757	 * Stops any fading which is applied to this action.
53758	 *
53759	 * @return {AnimationAction} A reference to this animation action.
53760	 */
53761	stopFading() {
53762
53763		const weightInterpolant = this._weightInterpolant;
53764
53765		if ( weightInterpolant !== null ) {
53766
53767			this._weightInterpolant = null;
53768			this._mixer._takeBackControlInterpolant( weightInterpolant );
53769
53770		}
53771
53772		return this;
53773
53774	}
53775
53776	/**
53777	 * Sets the effective time scale of this action.
53778	 *
53779	 * An action has no effect and thus an effective time scale of zero when the
53780	 * action is paused.
53781	 *
53782	 * @param {number} timeScale - The time scale to set.
53783	 * @return {AnimationAction} A reference to this animation action.
53784	 */
53785	setEffectiveTimeScale( timeScale ) {
53786
53787		this.timeScale = timeScale;
53788		this._effectiveTimeScale = this.paused ? 0 : timeScale;
53789
53790		return this.stopWarping();
53791
53792	}
53793
53794	/**
53795	 * Returns the effective time scale of this action.
53796	 *
53797	 * @return {number} The effective time scale.
53798	 */
53799	getEffectiveTimeScale() {
53800
53801		return this._effectiveTimeScale;
53802
53803	}
53804
53805	/**
53806	 * Sets the duration for a single loop of this action.
53807	 *
53808	 * @param {number} duration - The duration to set.
53809	 * @return {AnimationAction} A reference to this animation action.
53810	 */
53811	setDuration( duration ) {
53812
53813		this.timeScale = this._clip.duration / duration;
53814
53815		return this.stopWarping();
53816
53817	}
53818
53819	/**
53820	 * Synchronizes this action with the passed other action.
53821	 *
53822	 * @param {AnimationAction} action - The action to sync with.
53823	 * @return {AnimationAction} A reference to this animation action.
53824	 */
53825	syncWith( action ) {
53826
53827		this.time = action.time;
53828		this.timeScale = action.timeScale;
53829
53830		return this.stopWarping();
53831
53832	}
53833
53834	/**
53835	 * Decelerates this animation's speed to `0` within the passed time interval.
53836	 *
53837	 * @param {number} duration - The duration.
53838	 * @return {AnimationAction} A reference to this animation action.
53839	 */
53840	halt( duration ) {
53841
53842		return this.warp( this._effectiveTimeScale, 0, duration );
53843
53844	}
53845
53846	/**
53847	 * Changes the playback speed, within the passed time interval, by modifying
53848	 * {@link AnimationAction#timeScale} gradually from `startTimeScale` to
53849	 * `endTimeScale`.
53850	 *
53851	 * @param {number} startTimeScale - The start time scale.
53852	 * @param {number} endTimeScale - The end time scale.
53853	 * @param {number} duration - The duration.
53854	 * @return {AnimationAction} A reference to this animation action.
53855	 */
53856	warp( startTimeScale, endTimeScale, duration ) {
53857
53858		const mixer = this._mixer,
53859			now = mixer.time,
53860			timeScale = this.timeScale;
53861
53862		let interpolant = this._timeScaleInterpolant;
53863
53864		if ( interpolant === null ) {
53865
53866			interpolant = mixer._lendControlInterpolant();
53867			this._timeScaleInterpolant = interpolant;
53868
53869		}
53870
53871		const times = interpolant.parameterPositions,
53872			values = interpolant.sampleValues;
53873
53874		times[ 0 ] = now;
53875		times[ 1 ] = now + duration;
53876
53877		values[ 0 ] = startTimeScale / timeScale;
53878		values[ 1 ] = endTimeScale / timeScale;
53879
53880		return this;
53881
53882	}
53883
53884	/**
53885	 * Stops any scheduled warping which is applied to this action.
53886	 *
53887	 * @return {AnimationAction} A reference to this animation action.
53888	 */
53889	stopWarping() {
53890
53891		const timeScaleInterpolant = this._timeScaleInterpolant;
53892
53893		if ( timeScaleInterpolant !== null ) {
53894
53895			this._timeScaleInterpolant = null;
53896			this._mixer._takeBackControlInterpolant( timeScaleInterpolant );
53897
53898		}
53899
53900		return this;
53901
53902	}
53903
53904	/**
53905	 * Returns the animation mixer of this animation action.
53906	 *
53907	 * @return {AnimationMixer} The animation mixer.
53908	 */
53909	getMixer() {
53910
53911		return this._mixer;
53912
53913	}
53914
53915	/**
53916	 * Returns the animation clip of this animation action.
53917	 *
53918	 * @return {AnimationClip} The animation clip.
53919	 */
53920	getClip() {
53921
53922		return this._clip;
53923
53924	}
53925
53926	/**
53927	 * Returns the root object of this animation action.
53928	 *
53929	 * @return {Object3D} The root object.
53930	 */
53931	getRoot() {
53932
53933		return this._localRoot || this._mixer._root;
53934
53935	}
53936
53937	// Internal
53938
53939	_update( time, deltaTime, timeDirection, accuIndex ) {
53940
53941		// called by the mixer
53942
53943		if ( ! this.enabled ) {
53944
53945			// call ._updateWeight() to update ._effectiveWeight
53946
53947			this._updateWeight( time );
53948			return;
53949
53950		}
53951
53952		const startTime = this._startTime;
53953
53954		if ( startTime !== null ) {
53955
53956			// check for scheduled start of action
53957
53958			const timeRunning = ( time - startTime ) * timeDirection;
53959			if ( timeRunning < 0 || timeDirection === 0 ) {
53960
53961				deltaTime = 0;
53962
53963			} else {
53964
53965
53966				this._startTime = null; // unschedule
53967				deltaTime = timeDirection * timeRunning;
53968
53969			}
53970
53971		}
53972
53973		// apply time scale and advance time
53974
53975		deltaTime *= this._updateTimeScale( time );
53976		const clipTime = this._updateTime( deltaTime );
53977
53978		// note: _updateTime may disable the action resulting in
53979		// an effective weight of 0
53980
53981		const weight = this._updateWeight( time );
53982
53983		if ( weight > 0 ) {
53984
53985			const interpolants = this._interpolants;
53986			const propertyMixers = this._propertyBindings;
53987
53988			switch ( this.blendMode ) {
53989
53990				case AdditiveAnimationBlendMode:
53991
53992					for ( let j = 0, m = interpolants.length; j !== m; ++ j ) {
53993
53994						interpolants[ j ].evaluate( clipTime );
53995						propertyMixers[ j ].accumulateAdditive( weight );
53996
53997					}
53998
53999					break;
54000
54001				case NormalAnimationBlendMode:
54002				default:
54003
54004					for ( let j = 0, m = interpolants.length; j !== m; ++ j ) {
54005
54006						interpolants[ j ].evaluate( clipTime );
54007						propertyMixers[ j ].accumulate( accuIndex, weight );
54008
54009					}
54010
54011			}
54012
54013		}
54014
54015	}
54016
54017	_updateWeight( time ) {
54018
54019		let weight = 0;
54020
54021		if ( this.enabled ) {
54022
54023			weight = this.weight;
54024			const interpolant = this._weightInterpolant;
54025
54026			if ( interpolant !== null ) {
54027
54028				const interpolantValue = interpolant.evaluate( time )[ 0 ];
54029
54030				weight *= interpolantValue;
54031
54032				if ( time > interpolant.parameterPositions[ 1 ] ) {
54033
54034					this.stopFading();
54035
54036					if ( interpolantValue === 0 ) {
54037
54038						// faded out, disable
54039						this.enabled = false;
54040
54041					}
54042
54043				}
54044
54045			}
54046
54047		}
54048
54049		this._effectiveWeight = weight;
54050		return weight;
54051
54052	}
54053
54054	_updateTimeScale( time ) {
54055
54056		let timeScale = 0;
54057
54058		if ( ! this.paused ) {
54059
54060			timeScale = this.timeScale;
54061
54062			const interpolant = this._timeScaleInterpolant;
54063
54064			if ( interpolant !== null ) {
54065
54066				const interpolantValue = interpolant.evaluate( time )[ 0 ];
54067
54068				timeScale *= interpolantValue;
54069
54070				if ( time > interpolant.parameterPositions[ 1 ] ) {
54071
54072					this.stopWarping();
54073
54074					if ( timeScale === 0 ) {
54075
54076						// motion has halted, pause
54077						this.paused = true;
54078
54079					} else {
54080
54081						// warp done - apply final time scale
54082						this.timeScale = timeScale;
54083
54084					}
54085
54086				}
54087
54088			}
54089
54090		}
54091
54092		this._effectiveTimeScale = timeScale;
54093		return timeScale;
54094
54095	}
54096
54097	_updateTime( deltaTime ) {
54098
54099		const duration = this._clip.duration;
54100		const loop = this.loop;
54101
54102		let time = this.time + deltaTime;
54103		let loopCount = this._loopCount;
54104
54105		const pingPong = ( loop === LoopPingPong );
54106
54107		if ( deltaTime === 0 ) {
54108
54109			if ( loopCount === -1 ) return time;
54110
54111			return ( pingPong && ( loopCount & 1 ) === 1 ) ? duration - time : time;
54112
54113		}
54114
54115		if ( loop === LoopOnce ) {
54116
54117			if ( loopCount === -1 ) {
54118
54119				// just started
54120
54121				this._loopCount = 0;
54122				this._setEndings( true, true, false );
54123
54124			}
54125
54126			handle_stop: {
54127
54128				if ( time >= duration ) {
54129
54130					time = duration;
54131
54132				} else if ( time < 0 ) {
54133
54134					time = 0;
54135
54136				} else {
54137
54138					this.time = time;
54139
54140					break handle_stop;
54141
54142				}
54143
54144				if ( this.clampWhenFinished ) this.paused = true;
54145				else this.enabled = false;
54146
54147				this.time = time;
54148
54149				this._mixer.dispatchEvent( {
54150					type: 'finished', action: this,
54151					direction: deltaTime < 0 ? -1 : 1
54152				} );
54153
54154			}
54155
54156		} else { // repetitive Repeat or PingPong
54157
54158			if ( loopCount === -1 ) {
54159
54160				// just started
54161
54162				if ( deltaTime >= 0 ) {
54163
54164					loopCount = 0;
54165
54166					this._setEndings( true, this.repetitions === 0, pingPong );
54167
54168				} else {
54169
54170					// when looping in reverse direction, the initial
54171					// transition through zero counts as a repetition,
54172					// so leave loopCount at -1
54173
54174					this._setEndings( this.repetitions === 0, true, pingPong );
54175
54176				}
54177
54178			}
54179
54180			if ( time >= duration || time < 0 ) {
54181
54182				// wrap around
54183
54184				const loopDelta = Math.floor( time / duration ); // signed
54185				time -= duration * loopDelta;
54186
54187				loopCount += Math.abs( loopDelta );
54188
54189				const pending = this.repetitions - loopCount;
54190
54191				if ( pending <= 0 ) {
54192
54193					// have to stop (switch state, clamp time, fire event)
54194
54195					if ( this.clampWhenFinished ) this.paused = true;
54196					else this.enabled = false;
54197
54198					time = deltaTime > 0 ? duration : 0;
54199
54200					this.time = time;
54201
54202					this._mixer.dispatchEvent( {
54203						type: 'finished', action: this,
54204						direction: deltaTime > 0 ? 1 : -1
54205					} );
54206
54207				} else {
54208
54209					// keep running
54210
54211					if ( pending === 1 ) {
54212
54213						// entering the last round
54214
54215						const atStart = deltaTime < 0;
54216						this._setEndings( atStart, ! atStart, pingPong );
54217
54218					} else {
54219
54220						this._setEndings( false, false, pingPong );
54221
54222					}
54223
54224					this._loopCount = loopCount;
54225
54226					this.time = time;
54227
54228					this._mixer.dispatchEvent( {
54229						type: 'loop', action: this, loopDelta: loopDelta
54230					} );
54231
54232				}
54233
54234			} else {
54235
54236				this.
vendor: 21,210 bytes, lines 54236-55199
54236_loopCount = loopCount;
54237				this.time = time;
54238
54239			}
54240
54241			if ( pingPong && ( loopCount & 1 ) === 1 ) {
54242
54243				// invert time for the "pong round"
54244
54245				return duration - time;
54246
54247			}
54248
54249		}
54250
54251		return time;
54252
54253	}
54254
54255	_setEndings( atStart, atEnd, pingPong ) {
54256
54257		const settings = this._interpolantSettings;
54258
54259		if ( pingPong ) {
54260
54261			settings.endingStart = ZeroSlopeEnding;
54262			settings.endingEnd = ZeroSlopeEnding;
54263
54264		} else {
54265
54266			// assuming for LoopOnce atStart == atEnd == true
54267
54268			if ( atStart ) {
54269
54270				settings.endingStart = this.zeroSlopeAtStart ? ZeroSlopeEnding : ZeroCurvatureEnding;
54271
54272			} else {
54273
54274				settings.endingStart = WrapAroundEnding;
54275
54276			}
54277
54278			if ( atEnd ) {
54279
54280				settings.endingEnd = this.zeroSlopeAtEnd ? ZeroSlopeEnding : ZeroCurvatureEnding;
54281
54282			} else {
54283
54284				settings.endingEnd = WrapAroundEnding;
54285
54286			}
54287
54288		}
54289
54290	}
54291
54292	_scheduleFading( duration, weightNow, weightThen ) {
54293
54294		const mixer = this._mixer, now = mixer.time;
54295		let interpolant = this._weightInterpolant;
54296
54297		if ( interpolant === null ) {
54298
54299			interpolant = mixer._lendControlInterpolant();
54300			this._weightInterpolant = interpolant;
54301
54302		}
54303
54304		const times = interpolant.parameterPositions,
54305			values = interpolant.sampleValues;
54306
54307		times[ 0 ] = now;
54308		values[ 0 ] = weightNow;
54309		times[ 1 ] = now + duration;
54310		values[ 1 ] = weightThen;
54311
54312		return this;
54313
54314	}
54315
54316}
54317
54318const _controlInterpolantsResultBuffer = new Float32Array( 1 );
54319
54320/**
54321 * `AnimationMixer` is a player for animations on a particular object in
54322 * the scene. When multiple objects in the scene are animated independently,
54323 * one `AnimationMixer` may be used for each object.
54324 */
54325class AnimationMixer extends EventDispatcher {
54326
54327	/**
54328	 * Constructs a new animation mixer.
54329	 *
54330	 * @param {Object3D} root - The object whose animations shall be played by this mixer.
54331	 */
54332	constructor( root ) {
54333
54334		super();
54335
54336		this._root = root;
54337		this._initMemoryManager();
54338		this._accuIndex = 0;
54339
54340		/**
54341		 * The global mixer time (in seconds; starting with `0` on the mixer's creation).
54342		 *
54343		 * @type {number}
54344		 * @default 0
54345		 */
54346		this.time = 0;
54347
54348		/**
54349		 * A scaling factor for the global time.
54350		 *
54351		 * Note: Setting this member to `0` and later back to `1` is a
54352		 * possibility to pause/unpause all actions that are controlled by this
54353		 * mixer.
54354		 *
54355		 * @type {number}
54356		 * @default 1
54357		 */
54358		this.timeScale = 1.0;
54359
54360		if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {
54361
54362			__THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) );
54363
54364		}
54365
54366	}
54367
54368	_bindAction( action, prototypeAction ) {
54369
54370		const root = action._localRoot || this._root,
54371			tracks = action._clip.tracks,
54372			nTracks = tracks.length,
54373			bindings = action._propertyBindings,
54374			interpolants = action._interpolants,
54375			rootUuid = root.uuid,
54376			bindingsByRoot = this._bindingsByRootAndName;
54377
54378		let bindingsByName = bindingsByRoot[ rootUuid ];
54379
54380		if ( bindingsByName === undefined ) {
54381
54382			bindingsByName = {};
54383			bindingsByRoot[ rootUuid ] = bindingsByName;
54384
54385		}
54386
54387		for ( let i = 0; i !== nTracks; ++ i ) {
54388
54389			const track = tracks[ i ],
54390				trackName = track.name;
54391
54392			let binding = bindingsByName[ trackName ];
54393
54394			if ( binding !== undefined ) {
54395
54396				++ binding.referenceCount;
54397				bindings[ i ] = binding;
54398
54399			} else {
54400
54401				binding = bindings[ i ];
54402
54403				if ( binding !== undefined ) {
54404
54405					// existing binding, make sure the cache knows
54406
54407					if ( binding._cacheIndex === null ) {
54408
54409						++ binding.referenceCount;
54410						this._addInactiveBinding( binding, rootUuid, trackName );
54411
54412					}
54413
54414					continue;
54415
54416				}
54417
54418				const path = prototypeAction && prototypeAction.
54419					_propertyBindings[ i ].binding.parsedPath;
54420
54421				binding = new PropertyMixer(
54422					PropertyBinding.create( root, trackName, path ),
54423					track.ValueTypeName, track.getValueSize() );
54424
54425				++ binding.referenceCount;
54426				this._addInactiveBinding( binding, rootUuid, trackName );
54427
54428				bindings[ i ] = binding;
54429
54430			}
54431
54432			interpolants[ i ].resultBuffer = binding.buffer;
54433
54434		}
54435
54436	}
54437
54438	_activateAction( action ) {
54439
54440		if ( ! this._isActiveAction( action ) ) {
54441
54442			if ( action._cacheIndex === null ) {
54443
54444				// this action has been forgotten by the cache, but the user
54445				// appears to be still using it -> rebind
54446
54447				const rootUuid = ( action._localRoot || this._root ).uuid,
54448					clipUuid = action._clip.uuid,
54449					actionsForClip = this._actionsByClip[ clipUuid ];
54450
54451				this._bindAction( action,
54452					actionsForClip && actionsForClip.knownActions[ 0 ] );
54453
54454				this._addInactiveAction( action, clipUuid, rootUuid );
54455
54456			}
54457
54458			const bindings = action._propertyBindings;
54459
54460			// increment reference counts / sort out state
54461			for ( let i = 0, n = bindings.length; i !== n; ++ i ) {
54462
54463				const binding = bindings[ i ];
54464
54465				if ( binding.useCount ++ === 0 ) {
54466
54467					this._lendBinding( binding );
54468					binding.saveOriginalState();
54469
54470				}
54471
54472			}
54473
54474			this._lendAction( action );
54475
54476		}
54477
54478	}
54479
54480	_deactivateAction( action ) {
54481
54482		if ( this._isActiveAction( action ) ) {
54483
54484			const bindings = action._propertyBindings;
54485
54486			// decrement reference counts / sort out state
54487			for ( let i = 0, n = bindings.length; i !== n; ++ i ) {
54488
54489				const binding = bindings[ i ];
54490
54491				if ( -- binding.useCount === 0 ) {
54492
54493					binding.restoreOriginalState();
54494					this._takeBackBinding( binding );
54495
54496				}
54497
54498			}
54499
54500			this._takeBackAction( action );
54501
54502		}
54503
54504	}
54505
54506	// Memory manager
54507
54508	_initMemoryManager() {
54509
54510		this._actions = []; // 'nActiveActions' followed by inactive ones
54511		this._nActiveActions = 0;
54512
54513		this._actionsByClip = {};
54514		// inside:
54515		// {
54516		// 	knownActions: Array< AnimationAction > - used as prototypes
54517		// 	actionByRoot: AnimationAction - lookup
54518		// }
54519
54520
54521		this._bindings = []; // 'nActiveBindings' followed by inactive ones
54522		this._nActiveBindings = 0;
54523
54524		this._bindingsByRootAndName = {}; // inside: Map< name, PropertyMixer >
54525
54526
54527		this._controlInterpolants = []; // same game as above
54528		this._nActiveControlInterpolants = 0;
54529
54530		const scope = this;
54531
54532		this.stats = {
54533
54534			actions: {
54535				get total() {
54536
54537					return scope._actions.length;
54538
54539				},
54540				get inUse() {
54541
54542					return scope._nActiveActions;
54543
54544				}
54545			},
54546			bindings: {
54547				get total() {
54548
54549					return scope._bindings.length;
54550
54551				},
54552				get inUse() {
54553
54554					return scope._nActiveBindings;
54555
54556				}
54557			},
54558			controlInterpolants: {
54559				get total() {
54560
54561					return scope._controlInterpolants.length;
54562
54563				},
54564				get inUse() {
54565
54566					return scope._nActiveControlInterpolants;
54567
54568				}
54569			}
54570
54571		};
54572
54573	}
54574
54575	// Memory management for AnimationAction objects
54576
54577	_isActiveAction( action ) {
54578
54579		const index = action._cacheIndex;
54580		return index !== null && index < this._nActiveActions;
54581
54582	}
54583
54584	_addInactiveAction( action, clipUuid, rootUuid ) {
54585
54586		const actions = this._actions,
54587			actionsByClip = this._actionsByClip;
54588
54589		let actionsForClip = actionsByClip[ clipUuid ];
54590
54591		if ( actionsForClip === undefined ) {
54592
54593			actionsForClip = {
54594
54595				knownActions: [ action ],
54596				actionByRoot: {}
54597
54598			};
54599
54600			action._byClipCacheIndex = 0;
54601
54602			actionsByClip[ clipUuid ] = actionsForClip;
54603
54604		} else {
54605
54606			const knownActions = actionsForClip.knownActions;
54607
54608			action._byClipCacheIndex = knownActions.length;
54609			knownActions.push( action );
54610
54611		}
54612
54613		action._cacheIndex = actions.length;
54614		actions.push( action );
54615
54616		actionsForClip.actionByRoot[ rootUuid ] = action;
54617
54618	}
54619
54620	_removeInactiveAction( action ) {
54621
54622		const actions = this._actions,
54623			lastInactiveAction = actions[ actions.length - 1 ],
54624			cacheIndex = action._cacheIndex;
54625
54626		lastInactiveAction._cacheIndex = cacheIndex;
54627		actions[ cacheIndex ] = lastInactiveAction;
54628		actions.pop();
54629
54630		action._cacheIndex = null;
54631
54632
54633		const clipUuid = action._clip.uuid,
54634			actionsByClip = this._actionsByClip,
54635			actionsForClip = actionsByClip[ clipUuid ],
54636			knownActionsForClip = actionsForClip.knownActions,
54637
54638			lastKnownAction =
54639				knownActionsForClip[ knownActionsForClip.length - 1 ],
54640
54641			byClipCacheIndex = action._byClipCacheIndex;
54642
54643		lastKnownAction._byClipCacheIndex = byClipCacheIndex;
54644		knownActionsForClip[ byClipCacheIndex ] = lastKnownAction;
54645		knownActionsForClip.pop();
54646
54647		action._byClipCacheIndex = null;
54648
54649
54650		const actionByRoot = actionsForClip.actionByRoot,
54651			rootUuid = ( action._localRoot || this._root ).uuid;
54652
54653		delete actionByRoot[ rootUuid ];
54654
54655		if ( knownActionsForClip.length === 0 ) {
54656
54657			delete actionsByClip[ clipUuid ];
54658
54659		}
54660
54661		this._removeInactiveBindingsForAction( action );
54662
54663	}
54664
54665	_removeInactiveBindingsForAction( action ) {
54666
54667		const bindings = action._propertyBindings;
54668
54669		for ( let i = 0, n = bindings.length; i !== n; ++ i ) {
54670
54671			const binding = bindings[ i ];
54672
54673			if ( -- binding.referenceCount === 0 ) {
54674
54675				this._removeInactiveBinding( binding );
54676
54677			}
54678
54679		}
54680
54681	}
54682
54683	_lendAction( action ) {
54684
54685		// [ active actions |  inactive actions  ]
54686		// [  active actions >| inactive actions ]
54687		//                 s        a
54688		//                  <-swap->
54689		//                 a        s
54690
54691		const actions = this._actions,
54692			prevIndex = action._cacheIndex,
54693
54694			lastActiveIndex = this._nActiveActions ++,
54695
54696			firstInactiveAction = actions[ lastActiveIndex ];
54697
54698		action._cacheIndex = lastActiveIndex;
54699		actions[ lastActiveIndex ] = action;
54700
54701		firstInactiveAction._cacheIndex = prevIndex;
54702		actions[ prevIndex ] = firstInactiveAction;
54703
54704	}
54705
54706	_takeBackAction( action ) {
54707
54708		// [  active actions  | inactive actions ]
54709		// [ active actions |< inactive actions  ]
54710		//        a        s
54711		//         <-swap->
54712		//        s        a
54713
54714		const actions = this._actions,
54715			prevIndex = action._cacheIndex,
54716
54717			firstInactiveIndex = -- this._nActiveActions,
54718
54719			lastActiveAction = actions[ firstInactiveIndex ];
54720
54721		action._cacheIndex = firstInactiveIndex;
54722		actions[ firstInactiveIndex ] = action;
54723
54724		lastActiveAction._cacheIndex = prevIndex;
54725		actions[ prevIndex ] = lastActiveAction;
54726
54727	}
54728
54729	// Memory management for PropertyMixer objects
54730
54731	_addInactiveBinding( binding, rootUuid, trackName ) {
54732
54733		const bindingsByRoot = this._bindingsByRootAndName,
54734			bindings = this._bindings;
54735
54736		let bindingByName = bindingsByRoot[ rootUuid ];
54737
54738		if ( bindingByName === undefined ) {
54739
54740			bindingByName = {};
54741			bindingsByRoot[ rootUuid ] = bindingByName;
54742
54743		}
54744
54745		bindingByName[ trackName ] = binding;
54746
54747		binding._cacheIndex = bindings.length;
54748		bindings.push( binding );
54749
54750	}
54751
54752	_removeInactiveBinding( binding ) {
54753
54754		const bindings = this._bindings,
54755			propBinding = binding.binding,
54756			rootUuid = propBinding.rootNode.uuid,
54757			trackName = propBinding.path,
54758			bindingsByRoot = this._bindingsByRootAndName,
54759			bindingByName = bindingsByRoot[ rootUuid ],
54760
54761			lastInactiveBinding = bindings[ bindings.length - 1 ],
54762			cacheIndex = binding._cacheIndex;
54763
54764		lastInactiveBinding._cacheIndex = cacheIndex;
54765		bindings[ cacheIndex ] = lastInactiveBinding;
54766		bindings.pop();
54767
54768		delete bindingByName[ trackName ];
54769
54770		if ( Object.keys( bindingByName ).length === 0 ) {
54771
54772			delete bindingsByRoot[ rootUuid ];
54773
54774		}
54775
54776	}
54777
54778	_lendBinding( binding ) {
54779
54780		const bindings = this._bindings,
54781			prevIndex = binding._cacheIndex,
54782
54783			lastActiveIndex = this._nActiveBindings ++,
54784
54785			firstInactiveBinding = bindings[ lastActiveIndex ];
54786
54787		binding._cacheIndex = lastActiveIndex;
54788		bindings[ lastActiveIndex ] = binding;
54789
54790		firstInactiveBinding._cacheIndex = prevIndex;
54791		bindings[ prevIndex ] = firstInactiveBinding;
54792
54793	}
54794
54795	_takeBackBinding( binding ) {
54796
54797		const bindings = this._bindings,
54798			prevIndex = binding._cacheIndex,
54799
54800			firstInactiveIndex = -- this._nActiveBindings,
54801
54802			lastActiveBinding = bindings[ firstInactiveIndex ];
54803
54804		binding._cacheIndex = firstInactiveIndex;
54805		bindings[ firstInactiveIndex ] = binding;
54806
54807		lastActiveBinding._cacheIndex = prevIndex;
54808		bindings[ prevIndex ] = lastActiveBinding;
54809
54810	}
54811
54812
54813	// Memory management of Interpolants for weight and time scale
54814
54815	_lendControlInterpolant() {
54816
54817		const interpolants = this._controlInterpolants,
54818			lastActiveIndex = this._nActiveControlInterpolants ++;
54819
54820		let interpolant = interpolants[ lastActiveIndex ];
54821
54822		if ( interpolant === undefined ) {
54823
54824			interpolant = new LinearInterpolant(
54825				new Float32Array( 2 ), new Float32Array( 2 ),
54826				1, _controlInterpolantsResultBuffer );
54827
54828			interpolant.__cacheIndex = lastActiveIndex;
54829			interpolants[ lastActiveIndex ] = interpolant;
54830
54831		}
54832
54833		return interpolant;
54834
54835	}
54836
54837	_takeBackControlInterpolant( interpolant ) {
54838
54839		const interpolants = this._controlInterpolants,
54840			prevIndex = interpolant.__cacheIndex,
54841
54842			firstInactiveIndex = -- this._nActiveControlInterpolants,
54843
54844			lastActiveInterpolant = interpolants[ firstInactiveIndex ];
54845
54846		interpolant.__cacheIndex = firstInactiveIndex;
54847		interpolants[ firstInactiveIndex ] = interpolant;
54848
54849		lastActiveInterpolant.__cacheIndex = prevIndex;
54850		interpolants[ prevIndex ] = lastActiveInterpolant;
54851
54852	}
54853
54854	/**
54855	 * Returns an instance of {@link AnimationAction} for the passed clip.
54856	 *
54857	 * If an action fitting the clip and root parameters doesn't yet exist, it
54858	 * will be created by this method. Calling this method several times with the
54859	 * same clip and root parameters always returns the same action.
54860	 *
54861	 * @param {AnimationClip|string} clip - An animation clip or alternatively the name of the animation clip.
54862	 * @param {Object3D} [optionalRoot] - An alternative root object.
54863	 * @param {(NormalAnimationBlendMode|AdditiveAnimationBlendMode)} [blendMode] - The blend mode.
54864	 * @return {?AnimationAction} The animation action.
54865	 */
54866	clipAction( clip, optionalRoot, blendMode ) {
54867
54868		const root = optionalRoot || this._root,
54869			rootUuid = root.uuid;
54870
54871		let clipObject = typeof clip === 'string' ? AnimationClip.findByName( root, clip ) : clip;
54872
54873		const clipUuid = clipObject !== null ? clipObject.uuid : clip;
54874
54875		const actionsForClip = this._actionsByClip[ clipUuid ];
54876		let prototypeAction = null;
54877
54878		if ( blendMode === undefined ) {
54879
54880			if ( clipObject !== null ) {
54881
54882				blendMode = clipObject.blendMode;
54883
54884			} else {
54885
54886				blendMode = NormalAnimationBlendMode;
54887
54888			}
54889
54890		}
54891
54892		if ( actionsForClip !== undefined ) {
54893
54894			const existingAction = actionsForClip.actionByRoot[ rootUuid ];
54895
54896			if ( existingAction !== undefined && existingAction.blendMode === blendMode ) {
54897
54898				return existingAction;
54899
54900			}
54901
54902			// we know the clip, so we don't have to parse all
54903			// the bindings again but can just copy
54904			prototypeAction = actionsForClip.knownActions[ 0 ];
54905
54906			// also, take the clip from the prototype action
54907			if ( clipObject === null )
54908				clipObject = prototypeAction._clip;
54909
54910		}
54911
54912		// clip must be known when specified via string
54913		if ( clipObject === null ) return null;
54914
54915		// allocate all resources required to run it
54916		const newAction = new AnimationAction( this, clipObject, optionalRoot, blendMode );
54917
54918		this._bindAction( newAction, prototypeAction );
54919
54920		// and make the action known to the memory manager
54921		this._addInactiveAction( newAction, clipUuid, rootUuid );
54922
54923		return newAction;
54924
54925	}
54926
54927	/**
54928	 * Returns an existing animation action for the passed clip.
54929	 *
54930	 * @param {AnimationClip|string} clip - An animation clip or alternatively the name of the animation clip.
54931	 * @param {Object3D} [optionalRoot] - An alternative root object.
54932	 * @return {?AnimationAction} The animation action. Returns `null` if no action was found.
54933	 */
54934	existingAction( clip, optionalRoot ) {
54935
54936		const root = optionalRoot || this._root,
54937			rootUuid = root.uuid,
54938
54939			clipObject = typeof clip === 'string' ?
54940				AnimationClip.findByName( root, clip ) : clip,
54941
54942			clipUuid = clipObject ? clipObject.uuid : clip,
54943
54944			actionsForClip = this._actionsByClip[ clipUuid ];
54945
54946		if ( actionsForClip !== undefined ) {
54947
54948			return actionsForClip.actionByRoot[ rootUuid ] || null;
54949
54950		}
54951
54952		return null;
54953
54954	}
54955
54956	/**
54957	 * Deactivates all previously scheduled actions on this mixer.
54958	 *
54959	 * @return {AnimationMixer} A reference to this animation mixer.
54960	 */
54961	stopAllAction() {
54962
54963		const actions = this._actions,
54964			nActions = this._nActiveActions;
54965
54966		for ( let i = nActions - 1; i >= 0; -- i ) {
54967
54968			actions[ i ].stop();
54969
54970		}
54971
54972		return this;
54973
54974	}
54975
54976	/**
54977	 * Advances the global mixer time and updates the animation.
54978	 *
54979	 * This is usually done in the render loop by passing the delta
54980	 * time from {@link Clock} or {@link Timer}.
54981	 *
54982	 * @param {number} deltaTime - The delta time in seconds.
54983	 * @return {AnimationMixer} A reference to this animation mixer.
54984	 */
54985	update( deltaTime ) {
54986
54987		deltaTime *= this.timeScale;
54988
54989		const actions = this._actions,
54990			nActions = this._nActiveActions,
54991
54992			time = this.time += deltaTime,
54993			timeDirection = Math.sign( deltaTime ),
54994
54995			accuIndex = this._accuIndex ^= 1;
54996
54997		// run active actions
54998
54999		for ( let i = 0; i !== nActions; ++ i ) {
55000
55001			const action = actions[ i ];
55002
55003			action._update( time, deltaTime, timeDirection, accuIndex );
55004
55005		}
55006
55007		// update scene graph
55008
55009		const bindings = this._bindings,
55010			nBindings = this._nActiveBindings;
55011
55012		for ( let i = 0; i !== nBindings; ++ i ) {
55013
55014			bindings[ i ].apply( accuIndex );
55015
55016		}
55017
55018		return this;
55019
55020	}
55021
55022	/**
55023	 * Sets the global mixer to a specific time and updates the animation accordingly.
55024	 *
55025	 * This is useful when you need to jump to an exact time in an animation. The
55026	 * input parameter will be scaled by {@link AnimationMixer#timeScale}
55027	 *
55028	 * @param {number} time - The time to set in seconds.
55029	 * @return {AnimationMixer} A reference to this animation mixer.
55030	 */
55031	setTime( time ) {
55032
55033		this.time = 0; // Zero out time attribute for AnimationMixer object;
55034		for ( let i = 0; i < this._actions.length; i ++ ) {
55035
55036			this._actions[ i ].time = 0; // Zero out time attribute for all associated AnimationAction objects.
55037
55038		}
55039
55040		return this.update( time ); // Update used to set exact time. Returns "this" AnimationMixer object.
55041
55042	}
55043
55044	/**
55045	 * Returns this mixer's root object.
55046	 *
55047	 * @return {Object3D} The mixer's root object.
55048	 */
55049	getRoot() {
55050
55051		return this._root;
55052
55053	}
55054
55055	/**
55056	 * Deallocates all memory resources for a clip. Before using this method make
55057	 * sure to call {@link AnimationAction#stop} for all related actions.
55058	 *
55059	 * @param {AnimationClip} clip - The clip to uncache.
55060	 */
55061	uncacheClip( clip ) {
55062
55063		const actions = this._actions,
55064			clipUuid = clip.uuid,
55065			actionsByClip = this._actionsByClip,
55066			actionsForClip = actionsByClip[ clipUuid ];
55067
55068		if ( actionsForClip !== undefined ) {
55069
55070			// note: just calling _removeInactiveAction would mess up the
55071			// iteration state and also require updating the state we can
55072			// just throw away
55073
55074			const actionsToRemove = actionsForClip.knownActions;
55075
55076			for ( let i = 0, n = actionsToRemove.length; i !== n; ++ i ) {
55077
55078				const action = actionsToRemove[ i ];
55079
55080				this._deactivateAction( action );
55081
55082				const cacheIndex = action._cacheIndex,
55083					lastInactiveAction = actions[ actions.length - 1 ];
55084
55085				action._cacheIndex = null;
55086				action._byClipCacheIndex = null;
55087
55088				lastInactiveAction._cacheIndex = cacheIndex;
55089				actions[ cacheIndex ] = lastInactiveAction;
55090				actions.pop();
55091
55092				this._removeInactiveBindingsForAction( action );
55093
55094			}
55095
55096			delete actionsByClip[ clipUuid ];
55097
55098		}
55099
55100	}
55101
55102	/**
55103	 * Deallocates all memory resources for a root object. Before using this
55104	 * method make sure to call {@link AnimationAction#stop} for all related
55105	 * actions or alternatively {@link AnimationMixer#stopAllAction} when the
55106	 * mixer operates on a single root.
55107	 *
55108	 * @param {Object3D} root - The root object to uncache.
55109	 */
55110	uncacheRoot( root ) {
55111
55112		const rootUuid = root.uuid,
55113			actionsByClip = this._actionsByClip;
55114
55115		for ( const clipUuid in actionsByClip ) {
55116
55117			const actionByRoot = actionsByClip[ clipUuid ].actionByRoot,
55118				action = actionByRoot[ rootUuid ];
55119
55120			if ( action !== undefined ) {
55121
55122				this._deactivateAction( action );
55123				this._removeInactiveAction( action );
55124
55125			}
55126
55127		}
55128
55129		const bindingsByRoot = this._bindingsByRootAndName,
55130			bindingByName = bindingsByRoot[ rootUuid ];
55131
55132		if ( bindingByName !== undefined ) {
55133
55134			for ( const trackName in bindingByName ) {
55135
55136				const binding = bindingByName[ trackName ];
55137				binding.restoreOriginalState();
55138				this._removeInactiveBinding( binding );
55139
55140			}
55141
55142		}
55143
55144	}
55145
55146	/**
55147	 * Deallocates all memory resources for an action. The action is identified by the
55148	 * given clip and an optional root object. Before using this method make
55149	 * sure to call {@link AnimationAction#stop} to deactivate the action.
55150	 *
55151	 * @param {AnimationClip|string} clip - An animation clip or alternatively the name of the animation clip.
55152	 * @param {Object3D} [optionalRoot] - An alternative root object.
55153	 */
55154	uncacheAction( clip, optionalRoot ) {
55155
55156		const action = this.existingAction( clip, optionalRoot );
55157
55158		if ( action !== null ) {
55159
55160			this._deactivateAction( action );
55161			this._removeInactiveAction( action );
55162
55163		}
55164
55165	}
55166
55167}
55168
55169/**
55170 * Represents a 3D render target.
55171 *
55172 * @augments RenderTarget
55173 */
55174class RenderTarget3D extends RenderTarget {
55175
55176	/**
55177	 * Constructs a new 3D render target.
55178	 *
55179	 * @param {number} [width=1] - The width of the render target.
55180	 * @param {number} [height=1] - The height of the render target.
55181	 * @param {number} [depth=1] - The height of the render target.
55182	 * @param {RenderTarget~Options} [options] - The configuration object.
55183	 */
55184	constructor( width = 1, height = 1, depth = 1, options = {} ) {
55185
55186		super( width, height, options );
55187
55188		/**
55189		 * This flag can be used for type testing.
55190		 *
55191		 * @type {boolean}
55192		 * @readonly
55193		 * @default true
55194		 */
55195		this.isRenderTarget3D = true;
55196
55197		this.depth = depth;
55198
55199		/
55199**
55200		 * Overwritten with a different texture type.
55201		 *
55202		 * @type {Data3DTexture}
55203		 */
55204		this.texture = new Data3DTexture( null, width, height, depth );
55205		this._setTextureOptions( options );
55206
55207		this.texture.isRenderTargetTexture = true
vendor: 13,226 bytes, lines 55207-55798
55207;
55208
55209	}
55210
55211}
55212
55213/**
55214 * Represents a uniform which is a global shader variable. They are passed to shader programs.
55215 *
55216 * When declaring a uniform of a {@link ShaderMaterial}, it is declared by value or by object.
55217 * ```js
55218 * uniforms: {
55219 * 	time: { value: 1.0 },
55220 * 	resolution: new Uniform( new Vector2() )
55221 * };
55222 * ```
55223 * Since this class can only be used in context of {@link ShaderMaterial}, it is only supported
55224 * in {@link WebGLRenderer}.
55225 */
55226class Uniform {
55227
55228	/**
55229	 * Constructs a new uniform.
55230	 *
55231	 * @param {any} value - The uniform value.
55232	 */
55233	constructor( value ) {
55234
55235		/**
55236		 * The uniform value.
55237		 *
55238		 * @type {any}
55239		 */
55240		this.value = value;
55241
55242	}
55243
55244	/**
55245	 * Returns a new uniform with copied values from this instance.
55246	 * If the value has a `clone()` method, the value is cloned as well.
55247	 *
55248	 * @return {Uniform} A clone of this instance.
55249	 */
55250	clone() {
55251
55252		return new Uniform( this.value.clone === undefined ? this.value : this.value.clone() );
55253
55254	}
55255
55256}
55257
55258let _id = 0;
55259
55260/**
55261 * A class for managing multiple uniforms in a single group. The renderer will process
55262 * such a definition as a single UBO.
55263 *
55264 * Since this class can only be used in context of {@link ShaderMaterial}, it is only supported
55265 * in {@link WebGLRenderer}.
55266 *
55267 * @augments EventDispatcher
55268 */
55269class UniformsGroup extends EventDispatcher {
55270
55271	/**
55272	 * Constructs a new uniforms group.
55273	 */
55274	constructor() {
55275
55276		super();
55277
55278		/**
55279		 * This flag can be used for type testing.
55280		 *
55281		 * @type {boolean}
55282		 * @readonly
55283		 * @default true
55284		 */
55285		this.isUniformsGroup = true;
55286
55287		/**
55288		 * The ID of the 3D object.
55289		 *
55290		 * @name UniformsGroup#id
55291		 * @type {number}
55292		 * @readonly
55293		 */
55294		Object.defineProperty( this, 'id', { value: _id ++ } );
55295
55296		/**
55297		 * The name of the uniforms group.
55298		 *
55299		 * @type {string}
55300		 */
55301		this.name = '';
55302
55303		/**
55304		 * The buffer usage.
55305		 *
55306		 * @type {(StaticDrawUsage|DynamicDrawUsage|StreamDrawUsage|StaticReadUsage|DynamicReadUsage|StreamReadUsage|StaticCopyUsage|DynamicCopyUsage|StreamCopyUsage)}
55307		 * @default StaticDrawUsage
55308		 */
55309		this.usage = StaticDrawUsage;
55310
55311		/**
55312		 * An array holding the uniforms.
55313		 *
55314		 * @type {Array<Uniform>}
55315		 */
55316		this.uniforms = [];
55317
55318	}
55319
55320	/**
55321	 * Adds the given uniform to this uniforms group.
55322	 *
55323	 * @param {Uniform} uniform - The uniform to add.
55324	 * @return {UniformsGroup} A reference to this uniforms group.
55325	 */
55326	add( uniform ) {
55327
55328		this.uniforms.push( uniform );
55329
55330		return this;
55331
55332	}
55333
55334	/**
55335	 * Removes the given uniform from this uniforms group.
55336	 *
55337	 * @param {Uniform} uniform - The uniform to remove.
55338	 * @return {UniformsGroup} A reference to this uniforms group.
55339	 */
55340	remove( uniform ) {
55341
55342		const index = this.uniforms.indexOf( uniform );
55343
55344		if ( index !== -1 ) this.uniforms.splice( index, 1 );
55345
55346		return this;
55347
55348	}
55349
55350	/**
55351	 * Sets the name of this uniforms group.
55352	 *
55353	 * @param {string} name - The name to set.
55354	 * @return {UniformsGroup} A reference to this uniforms group.
55355	 */
55356	setName( name ) {
55357
55358		this.name = name;
55359
55360		return this;
55361
55362	}
55363
55364	/**
55365	 * Sets the usage of this uniforms group.
55366	 *
55367	 * @param {(StaticDrawUsage|DynamicDrawUsage|StreamDrawUsage|StaticReadUsage|DynamicReadUsage|StreamReadUsage|StaticCopyUsage|DynamicCopyUsage|StreamCopyUsage)} value - The usage to set.
55368	 * @return {UniformsGroup} A reference to this uniforms group.
55369	 */
55370	setUsage( value ) {
55371
55372		this.usage = value;
55373
55374		return this;
55375
55376	}
55377
55378	/**
55379	 * Frees the GPU-related resources allocated by this instance. Call this
55380	 * method whenever this instance is no longer used in your app.
55381	 *
55382	 * @fires Texture#dispose
55383	 */
55384	dispose() {
55385
55386		this.dispatchEvent( { type: 'dispose' } );
55387
55388	}
55389
55390	/**
55391	 * Copies the values of the given uniforms group to this instance.
55392	 *
55393	 * @param {UniformsGroup} source - The uniforms group to copy.
55394	 * @return {UniformsGroup} A reference to this uniforms group.
55395	 */
55396	copy( source ) {
55397
55398		this.name = source.name;
55399		this.usage = source.usage;
55400
55401		const uniformsSource = source.uniforms;
55402
55403		this.uniforms.length = 0;
55404
55405		for ( let i = 0, l = uniformsSource.length; i < l; i ++ ) {
55406
55407			const uniforms = Array.isArray( uniformsSource[ i ] ) ? uniformsSource[ i ] : [ uniformsSource[ i ] ];
55408
55409			for ( let j = 0; j < uniforms.length; j ++ ) {
55410
55411				this.uniforms.push( uniforms[ j ].clone() );
55412
55413			}
55414
55415		}
55416
55417		return this;
55418
55419	}
55420
55421	/**
55422	 * Returns a new uniforms group with copied values from this instance.
55423	 *
55424	 * @return {UniformsGroup} A clone of this instance.
55425	 */
55426	clone() {
55427
55428		return new this.constructor().copy( this );
55429
55430	}
55431
55432}
55433
55434/**
55435 * An instanced version of an interleaved buffer.
55436 *
55437 * @augments InterleavedBuffer
55438 */
55439class InstancedInterleavedBuffer extends InterleavedBuffer {
55440
55441	/**
55442	 * Constructs a new instanced interleaved buffer.
55443	 *
55444	 * @param {TypedArray} array - A typed array with a shared buffer storing attribute data.
55445	 * @param {number} stride - The number of typed-array elements per vertex.
55446	 * @param {number} [meshPerAttribute=1] - Defines how often a value of this interleaved buffer should be repeated.
55447	 */
55448	constructor( array, stride, meshPerAttribute = 1 ) {
55449
55450		super( array, stride );
55451
55452		/**
55453		 * This flag can be used for type testing.
55454		 *
55455		 * @type {boolean}
55456		 * @readonly
55457		 * @default true
55458		 */
55459		this.isInstancedInterleavedBuffer = true;
55460
55461		/**
55462		 * Defines how often a value of this buffer attribute should be repeated,
55463		 * see {@link InstancedBufferAttribute#meshPerAttribute}.
55464		 *
55465		 * @type {number}
55466		 * @default 1
55467		 */
55468		this.meshPerAttribute = meshPerAttribute;
55469
55470	}
55471
55472	copy( source ) {
55473
55474		super.copy( source );
55475
55476		this.meshPerAttribute = source.meshPerAttribute;
55477
55478		return this;
55479
55480	}
55481
55482	clone( data ) {
55483
55484		const ib = super.clone( data );
55485
55486		ib.meshPerAttribute = this.meshPerAttribute;
55487
55488		return ib;
55489
55490	}
55491
55492	toJSON( data ) {
55493
55494		const json = super.toJSON( data );
55495
55496		json.isInstancedInterleavedBuffer = true;
55497		json.meshPerAttribute = this.meshPerAttribute;
55498
55499		return json;
55500
55501	}
55502
55503}
55504
55505/**
55506 * An alternative version of a buffer attribute with more control over the VBO.
55507 *
55508 * The renderer does not construct a VBO for this kind of attribute. Instead, it uses
55509 * whatever VBO is passed in constructor and can later be altered via the `buffer` property.
55510 *
55511 * The most common use case for this class is when some kind of GPGPU calculation interferes
55512 * or even produces the VBOs in question.
55513 *
55514 * Notice that this class can only be used with {@link WebGLRenderer}.
55515 */
55516class GLBufferAttribute {
55517
55518	/**
55519	 * Constructs a new GL buffer attribute.
55520	 *
55521	 * @param {WebGLBuffer} buffer - The native WebGL buffer.
55522	 * @param {number} type - The native data type (e.g. `gl.FLOAT`).
55523	 * @param {number} itemSize - The item size.
55524	 * @param {number} elementSize - The corresponding size (in bytes) for the given `type` parameter.
55525	 * @param {number} count - The expected number of vertices in VBO.
55526	 * @param {boolean} [normalized=false] - Whether the data are normalized or not.
55527	 */
55528	constructor( buffer, type, itemSize, elementSize, count, normalized = false ) {
55529
55530		/**
55531		 * This flag can be used for type testing.
55532		 *
55533		 * @type {boolean}
55534		 * @readonly
55535		 * @default true
55536		 */
55537		this.isGLBufferAttribute = true;
55538
55539		/**
55540		 * The name of the buffer attribute.
55541		 *
55542		 * @type {string}
55543		 */
55544		this.name = '';
55545
55546		/**
55547		 * The native WebGL buffer.
55548		 *
55549		 * @type {WebGLBuffer}
55550		 */
55551		this.buffer = buffer;
55552
55553		/**
55554		 * The native data type.
55555		 *
55556		 * @type {number}
55557		 */
55558		this.type = type;
55559
55560		/**
55561		 * The item size, see {@link BufferAttribute#itemSize}.
55562		 *
55563		 * @type {number}
55564		 */
55565		this.itemSize = itemSize;
55566
55567		/**
55568		 * The corresponding size (in bytes) for the given `type` parameter.
55569		 *
55570		 * @type {number}
55571		 */
55572		this.elementSize = elementSize;
55573
55574		/**
55575		 * The expected number of vertices in VBO.
55576		 *
55577		 * @type {number}
55578		 */
55579		this.count = count;
55580
55581		/**
55582		 * Applies to integer data only. Indicates how the underlying data in the buffer maps to
55583		 * the values in the GLSL code. For instance, if `buffer` contains data of `gl.UNSIGNED_SHORT`,
55584		 * and `normalized` is `true`, the values `0 - +65535` in the buffer data will be mapped to
55585		 * `0.0f - +1.0f` in the GLSL attribute. If `normalized` is `false`, the values will be converted
55586		 * to floats unmodified, i.e. `65535` becomes `65535.0f`.
55587		 *
55588		 * @type {boolean}
55589		 */
55590		this.normalized = normalized;
55591
55592		/**
55593		 * A version number, incremented every time the `needsUpdate` is set to `true`.
55594		 *
55595		 * @type {number}
55596		 */
55597		this.version = 0;
55598
55599	}
55600
55601	/**
55602	 * Flag to indicate that this attribute has changed and should be re-sent to
55603	 * the GPU. Set this to `true` when you modify the value of the array.
55604	 *
55605	 * @type {number}
55606	 * @default false
55607	 * @param {boolean} value
55608	 */
55609	set needsUpdate( value ) {
55610
55611		if ( value === true ) this.version ++;
55612
55613	}
55614
55615	/**
55616	 * Sets the given native WebGL buffer.
55617	 *
55618	 * @param {WebGLBuffer} buffer - The buffer to set.
55619	 * @return {BufferAttribute} A reference to this instance.
55620	 */
55621	setBuffer( buffer ) {
55622
55623		this.buffer = buffer;
55624
55625		return this;
55626
55627	}
55628
55629	/**
55630	 * Sets the given native data type and element size.
55631	 *
55632	 * @param {number} type - The native data type (e.g. `gl.FLOAT`).
55633	 * @param {number} elementSize - The corresponding size (in bytes) for the given `type` parameter.
55634	 * @return {BufferAttribute} A reference to this instance.
55635	 */
55636	setType( type, elementSize ) {
55637
55638		this.type = type;
55639		this.elementSize = elementSize;
55640
55641		return this;
55642
55643	}
55644
55645	/**
55646	 * Sets the item size.
55647	 *
55648	 * @param {number} itemSize - The item size.
55649	 * @return {BufferAttribute} A reference to this instance.
55650	 */
55651	setItemSize( itemSize ) {
55652
55653		this.itemSize = itemSize;
55654
55655		return this;
55656
55657	}
55658
55659	/**
55660	 * Sets the count (the expected number of vertices in VBO).
55661	 *
55662	 * @param {number} count - The count.
55663	 * @return {BufferAttribute} A reference to this instance.
55664	 */
55665	setCount( count ) {
55666
55667		this.count = count;
55668
55669		return this;
55670
55671	}
55672
55673}
55674
55675const _matrix = /*@__PURE__*/ new Matrix4();
55676
55677/**
55678 * This class is designed to assist with raycasting. Raycasting is used for
55679 * mouse picking (working out what objects in the 3d space the mouse is over)
55680 * amongst other things.
55681 */
55682class Raycaster {
55683
55684	/**
55685	 * Constructs a new raycaster.
55686	 *
55687	 * @param {Vector3} origin - The origin vector where the ray casts from.
55688	 * @param {Vector3} direction - The (normalized) direction vector that gives direction to the ray.
55689	 * @param {number} [near=0] - All results returned are further away than near. Near can't be negative.
55690	 * @param {number} [far=Infinity] - All results returned are closer than far. Far can't be lower than near.
55691	 */
55692	constructor( origin, direction, near = 0, far = Infinity ) {
55693
55694		/**
55695		 * The ray used for raycasting.
55696		 *
55697		 * @type {Ray}
55698		 */
55699		this.ray = new Ray( origin, direction );
55700
55701		/**
55702		 * All results returned are further away than near. Near can't be negative.
55703		 *
55704		 * @type {number}
55705		 * @default 0
55706		 */
55707		this.near = near;
55708
55709		/**
55710		 * All results returned are closer than far. Far can't be lower than near.
55711		 *
55712		 * @type {number}
55713		 * @default Infinity
55714		 */
55715		this.far = far;
55716
55717		/**
55718		 * The camera to use when raycasting against view-dependent objects such as
55719		 * billboarded objects like sprites. This field can be set manually or
55720		 * is set when calling `setFromCamera()`.
55721		 *
55722		 * @type {?Camera}
55723		 * @default null
55724		 */
55725		this.camera = null;
55726
55727		/**
55728		 * Allows to selectively ignore 3D objects when performing intersection tests.
55729		 * The following code example ensures that only 3D objects on layer `1` will be
55730		 * honored by raycaster.
55731		 * ```js
55732		 * raycaster.layers.set( 1 );
55733		 * object.layers.enable( 1 );
55734		 * ```
55735		 *
55736		 * @type {Layers}
55737		 */
55738		this.layers = new Layers();
55739
55740
55741		/**
55742		 * A parameter object that configures the raycasting. It has the structure:
55743		 *
55744		 * ```
55745		 * {
55746		 * 	Mesh: {},
55747		 * 	Line: { threshold: 1 },
55748		 * 	LOD: {},
55749		 * 	Points: { threshold: 1 },
55750		 * 	Sprite: {}
55751		 * }
55752		 * ```
55753		 * Where `threshold` is the precision of the raycaster when intersecting objects, in world units.
55754		 *
55755		 * @type {Object}
55756		 */
55757		this.params = {
55758			Mesh: {},
55759			Line: { threshold: 1 },
55760			LOD: {},
55761			Points: { threshold: 1 },
55762			Sprite: {}
55763		};
55764
55765	}
55766
55767	/**
55768	 * Updates the ray with a new origin and direction by copying the values from the arguments.
55769	 *
55770	 * @param {Vector3} origin - The origin vector where the ray casts from.
55771	 * @param {Vector3} direction - The (normalized) direction vector that gives direction to the ray.
55772	 */
55773	set( origin, direction ) {
55774
55775		// direction is assumed to be normalized (for accurate distance calculations)
55776
55777		this.ray.set( origin, direction );
55778
55779	}
55780
55781	/**
55782	 * Uses the given coordinates and camera to compute a new origin and direction for the internal ray.
55783	 *
55784	 * @param {Vector2} coords - 2D coordinates of the mouse, in normalized device coordinates (NDC).
55785	 * X and Y components should be between `-1` and `1`.
55786	 * @param {Camera} camera - The camera from which the ray should originate.
55787	 */
55788	setFromCamera( coords, camera ) {
55789
55790		if ( camera.isPerspectiveCamera ) {
55791
55792			this.ray.origin.setFromMatrixPosition( camera.matrixWorld );
55793			this.ray.direction.set( coords.x, coords.y, 0.5 ).unproject( camera ).sub( this.ray.origin ).normalize();
55794			this.camera = camera;
55795
55796		} else if ( camera.isOrthographicCamera ) {
55797
55798			this.ray.origin.set( coords.x, coords.y, 
55798( camera.near + camera.far ) / ( camera.near - camera.far ) ).unproject( camera ); // set origin in plane of camera
55799			this.ray.direction.set( 0, 0, -1 ).transformDirection( camera.matrixWorld );
55800			this.camera = camera;
55801
55802		} else {
55803
55804			error( 'Raycaster: Unsupported camera type: ' + camera.type );
55805
55806		}
55807
55808	}
55809
55810	/**
55811	 * Uses the given WebXR controller to compute a new origin and direction for the internal ray.
55812	 *
55813	 * @param {WebXRController} controller - The controller to copy the position and direction from.
55814	 * @return {Raycaster} A reference to this raycaster.
55815	 */
55816	setFromXRController( controller ) {
55817
55818		_matrix.identity().extractRotation( controller.matrixWorld );
55819
55820		this.ray.origin.setFromMatrixPosition( controller.matrixWorld );
55821		this.ray.direction.set( 0, 0, -1 ).applyMatrix4( _matrix );
55822
55823		return this;
55824
55825	}
55826
55827	/**
55828	 * The intersection point of a raycaster intersection test.
55829	 * @typedef {Object} Raycaster~Intersection
55830	 * @property {number} distance - The distance from the ray's origin to the intersection point.
55831	 * @property {number} distanceToRay -  Some 3D objects e.g. {@link Points} provide the distance of the
55832	 * intersection to the nearest point on the ray. For other objects it will be `undefined`.
55833	 * @property {Vector3} point - The intersection point, in world coordinates.
55834	 * @property {Object} face - The face that has been intersected.
55835	 * @property {number} faceIndex - The face index.
55836	 * @property {Object3D} object - The 3D object that has been intersected.
55837	 * @property {Vector2} uv - U,V coordinates at point of intersection.
55838	 * @property {Vector2} uv1 - Second set of U,V coordinates at point of intersection.
55839	 * @property {Vector3} normal - Interpolated normal vector at point of intersection.
55840	 * @property {number} instanceId - The index number of the instance where the ray
55841	 * intersects the {@link InstancedMesh}.
55842	 */
55843
55844	/**
55845	 * Checks all intersection between the ray and the object with or without the
55846	 * descendants. Intersections are returned sorted by distance, closest first.
55847	 *
55848	 * `Raycaster` delegates to the `raycast()` method of the passed 3D object, when
55849	 * evaluating whether the ray intersects the object or not. This allows meshes to respond
55850	 * differently to ray casting than lines or points.
55851	 *
55852	 * Note that for meshes, faces must be pointed towards the origin of the ray in order
55853	 * to be detected; intersections of the ray passing through the back of a face will not
55854	 * be detected. To raycast against both faces of an object, you'll want to set  {@link Material#side}
55855	 * to `THREE.DoubleSide`
vendor: 32,143 bytes, lines 55855-57256
55855.
55856	 *
55857	 * @param {Object3D} object - The 3D object to check for intersection with the ray.
55858	 * @param {boolean} [recursive=true] - If set to `true`, it also checks all descendants.
55859	 * Otherwise it only checks intersection with the object.
55860	 * @param {Array<Raycaster~Intersection>} [intersects=[]] The target array that holds the result of the method.
55861	 * @return {Array<Raycaster~Intersection>} An array holding the intersection points.
55862	 */
55863	intersectObject( object, recursive = true, intersects = [] ) {
55864
55865		intersect( object, this, intersects, recursive );
55866
55867		intersects.sort( ascSort );
55868
55869		return intersects;
55870
55871	}
55872
55873	/**
55874	 * Checks all intersection between the ray and the objects with or without
55875	 * the descendants. Intersections are returned sorted by distance, closest first.
55876	 *
55877	 * @param {Array<Object3D>} objects - The 3D objects to check for intersection with the ray.
55878	 * @param {boolean} [recursive=true] - If set to `true`, it also checks all descendants.
55879	 * Otherwise it only checks intersection with the object.
55880	 * @param {Array<Raycaster~Intersection>} [intersects=[]] The target array that holds the result of the method.
55881	 * @return {Array<Raycaster~Intersection>} An array holding the intersection points.
55882	 */
55883	intersectObjects( objects, recursive = true, intersects = [] ) {
55884
55885		for ( let i = 0, l = objects.length; i < l; i ++ ) {
55886
55887			intersect( objects[ i ], this, intersects, recursive );
55888
55889		}
55890
55891		intersects.sort( ascSort );
55892
55893		return intersects;
55894
55895	}
55896
55897}
55898
55899function ascSort( a, b ) {
55900
55901	return a.distance - b.distance;
55902
55903}
55904
55905function intersect( object, raycaster, intersects, recursive ) {
55906
55907	let propagate = true;
55908
55909	if ( object.layers.test( raycaster.layers ) ) {
55910
55911		const result = object.raycast( raycaster, intersects );
55912
55913		if ( result === false ) propagate = false;
55914
55915	}
55916
55917	if ( propagate === true && recursive === true ) {
55918
55919		const children = object.children;
55920
55921		for ( let i = 0, l = children.length; i < l; i ++ ) {
55922
55923			intersect( children[ i ], raycaster, intersects, true );
55924
55925		}
55926
55927	}
55928
55929}
55930
55931/**
55932 * Class for keeping track of time.
55933 *
55934 * @deprecated since r183.
55935 */
55936class Clock {
55937
55938	/**
55939	 * Constructs a new clock.
55940	 *
55941	 * @deprecated since 183.
55942	 * @param {boolean} [autoStart=true] - Whether to automatically start the clock when
55943	 * `getDelta()` is called for the first time.
55944	 */
55945	constructor( autoStart = true ) {
55946
55947		/**
55948		 * If set to `true`, the clock starts automatically when `getDelta()` is called
55949		 * for the first time.
55950		 *
55951		 * @type {boolean}
55952		 * @default true
55953		 */
55954		this.autoStart = autoStart;
55955
55956		/**
55957		 * Holds the time at which the clock's `start()` method was last called.
55958		 *
55959		 * @type {number}
55960		 * @default 0
55961		 */
55962		this.startTime = 0;
55963
55964		/**
55965		 * Holds the time at which the clock's `start()`, `getElapsedTime()` or
55966		 * `getDelta()` methods were last called.
55967		 *
55968		 * @type {number}
55969		 * @default 0
55970		 */
55971		this.oldTime = 0;
55972
55973		/**
55974		 * Keeps track of the total time that the clock has been running.
55975		 *
55976		 * @type {number}
55977		 * @default 0
55978		 */
55979		this.elapsedTime = 0;
55980
55981		/**
55982		 * Whether the clock is running or not.
55983		 *
55984		 * @type {boolean}
55985		 * @default true
55986		 */
55987		this.running = false;
55988
55989		warn( 'Clock: This module has been deprecated. Please use THREE.Timer instead.' ); // @deprecated, r183
55990
55991	}
55992
55993	/**
55994	 * Starts the clock. When `autoStart` is set to `true`, the method is automatically
55995	 * called by the class.
55996	 */
55997	start() {
55998
55999		this.startTime = performance.now();
56000
56001		this.oldTime = this.startTime;
56002		this.elapsedTime = 0;
56003		this.running = true;
56004
56005	}
56006
56007	/**
56008	 * Stops the clock.
56009	 */
56010	stop() {
56011
56012		this.getElapsedTime();
56013		this.running = false;
56014		this.autoStart = false;
56015
56016	}
56017
56018	/**
56019	 * Returns the elapsed time in seconds.
56020	 *
56021	 * @return {number} The elapsed time.
56022	 */
56023	getElapsedTime() {
56024
56025		this.getDelta();
56026		return this.elapsedTime;
56027
56028	}
56029
56030	/**
56031	 * Returns the delta time in seconds.
56032	 *
56033	 * @return {number} The delta time.
56034	 */
56035	getDelta() {
56036
56037		let diff = 0;
56038
56039		if ( this.autoStart && ! this.running ) {
56040
56041			this.start();
56042			return 0;
56043
56044		}
56045
56046		if ( this.running ) {
56047
56048			const newTime = performance.now();
56049
56050			diff = ( newTime - this.oldTime ) / 1000;
56051			this.oldTime = newTime;
56052
56053			this.elapsedTime += diff;
56054
56055		}
56056
56057		return diff;
56058
56059	}
56060
56061}
56062
56063/**
56064 * This class can be used to represent points in 3D space as
56065 * [Spherical coordinates](https://en.wikipedia.org/wiki/Spherical_coordinate_system).
56066 */
56067class Spherical {
56068
56069	/**
56070	 * Constructs a new spherical.
56071	 *
56072	 * @param {number} [radius=1] - The radius, or the Euclidean distance (straight-line distance) from the point to the origin.
56073	 * @param {number} [phi=0] - The polar angle in radians from the y (up) axis.
56074	 * @param {number} [theta=0] - The equator/azimuthal angle in radians around the y (up) axis.
56075	 */
56076	constructor( radius = 1, phi = 0, theta = 0 ) {
56077
56078		/**
56079		 * The radius, or the Euclidean distance (straight-line distance) from the point to the origin.
56080		 *
56081		 * @type {number}
56082		 * @default 1
56083		 */
56084		this.radius = radius;
56085
56086		/**
56087		 * The polar angle in radians from the y (up) axis.
56088		 *
56089		 * @type {number}
56090		 * @default 0
56091		 */
56092		this.phi = phi;
56093
56094		/**
56095		 * The equator/azimuthal angle in radians around the y (up) axis.
56096		 *
56097		 * @type {number}
56098		 * @default 0
56099		 */
56100		this.theta = theta;
56101
56102	}
56103
56104	/**
56105	 * Sets the spherical components by copying the given values.
56106	 *
56107	 * @param {number} radius - The radius.
56108	 * @param {number} phi - The polar angle.
56109	 * @param {number} theta - The azimuthal angle.
56110	 * @return {Spherical} A reference to this spherical.
56111	 */
56112	set( radius, phi, theta ) {
56113
56114		this.radius = radius;
56115		this.phi = phi;
56116		this.theta = theta;
56117
56118		return this;
56119
56120	}
56121
56122	/**
56123	 * Copies the values of the given spherical to this instance.
56124	 *
56125	 * @param {Spherical} other - The spherical to copy.
56126	 * @return {Spherical} A reference to this spherical.
56127	 */
56128	copy( other ) {
56129
56130		this.radius = other.radius;
56131		this.phi = other.phi;
56132		this.theta = other.theta;
56133
56134		return this;
56135
56136	}
56137
56138	/**
56139	 * Restricts the polar angle [page:.phi phi] to be between `0.000001` and pi -
56140	 * `0.000001`.
56141	 *
56142	 * @return {Spherical} A reference to this spherical.
56143	 */
56144	makeSafe() {
56145
56146		const EPS = 0.000001;
56147		this.phi = clamp( this.phi, EPS, Math.PI - EPS );
56148
56149		return this;
56150
56151	}
56152
56153	/**
56154	 * Sets the spherical components from the given vector which is assumed to hold
56155	 * Cartesian coordinates.
56156	 *
56157	 * @param {Vector3} v - The vector to set.
56158	 * @return {Spherical} A reference to this spherical.
56159	 */
56160	setFromVector3( v ) {
56161
56162		return this.setFromCartesianCoords( v.x, v.y, v.z );
56163
56164	}
56165
56166	/**
56167	 * Sets the spherical components from the given Cartesian coordinates.
56168	 *
56169	 * @param {number} x - The x value.
56170	 * @param {number} y - The y value.
56171	 * @param {number} z - The z value.
56172	 * @return {Spherical} A reference to this spherical.
56173	 */
56174	setFromCartesianCoords( x, y, z ) {
56175
56176		this.radius = Math.sqrt( x * x + y * y + z * z );
56177
56178		if ( this.radius === 0 ) {
56179
56180			this.theta = 0;
56181			this.phi = 0;
56182
56183		} else {
56184
56185			this.theta = Math.atan2( x, z );
56186			this.phi = Math.acos( clamp( y / this.radius, -1, 1 ) );
56187
56188		}
56189
56190		return this;
56191
56192	}
56193
56194	/**
56195	 * Returns a new spherical with copied values from this instance.
56196	 *
56197	 * @return {Spherical} A clone of this instance.
56198	 */
56199	clone() {
56200
56201		return new this.constructor().copy( this );
56202
56203	}
56204
56205}
56206
56207/**
56208 * This class can be used to represent points in 3D space as
56209 * [Cylindrical coordinates](https://en.wikipedia.org/wiki/Cylindrical_coordinate_system).
56210 */
56211class Cylindrical {
56212
56213	/**
56214	 * Constructs a new cylindrical.
56215	 *
56216	 * @param {number} [radius=1] - The distance from the origin to a point in the x-z plane.
56217	 * @param {number} [theta=0] - A counterclockwise angle in the x-z plane measured in radians from the positive z-axis.
56218	 * @param {number} [y=0] - The height above the x-z plane.
56219	 */
56220	constructor( radius = 1, theta = 0, y = 0 ) {
56221
56222		/**
56223		 * The distance from the origin to a point in the x-z plane.
56224		 *
56225		 * @type {number}
56226		 * @default 1
56227		 */
56228		this.radius = radius;
56229
56230		/**
56231		 * A counterclockwise angle in the x-z plane measured in radians from the positive z-axis.
56232		 *
56233		 * @type {number}
56234		 * @default 0
56235		 */
56236		this.theta = theta;
56237
56238		/**
56239		 * The height above the x-z plane.
56240		 *
56241		 * @type {number}
56242		 * @default 0
56243		 */
56244		this.y = y;
56245
56246	}
56247
56248	/**
56249	 * Sets the cylindrical components by copying the given values.
56250	 *
56251	 * @param {number} radius - The radius.
56252	 * @param {number} theta - The theta angle.
56253	 * @param {number} y - The height value.
56254	 * @return {Cylindrical} A reference to this cylindrical.
56255	 */
56256	set( radius, theta, y ) {
56257
56258		this.radius = radius;
56259		this.theta = theta;
56260		this.y = y;
56261
56262		return this;
56263
56264	}
56265
56266	/**
56267	 * Copies the values of the given cylindrical to this instance.
56268	 *
56269	 * @param {Cylindrical} other - The cylindrical to copy.
56270	 * @return {Cylindrical} A reference to this cylindrical.
56271	 */
56272	copy( other ) {
56273
56274		this.radius = other.radius;
56275		this.theta = other.theta;
56276		this.y = other.y;
56277
56278		return this;
56279
56280	}
56281
56282	/**
56283	 * Sets the cylindrical components from the given vector which is assumed to hold
56284	 * Cartesian coordinates.
56285	 *
56286	 * @param {Vector3} v - The vector to set.
56287	 * @return {Cylindrical} A reference to this cylindrical.
56288	 */
56289	setFromVector3( v ) {
56290
56291		return this.setFromCartesianCoords( v.x, v.y, v.z );
56292
56293	}
56294
56295	/**
56296	 * Sets the cylindrical components from the given Cartesian coordinates.
56297	 *
56298	 * @param {number} x - The x value.
56299	 * @param {number} y - The x value.
56300	 * @param {number} z - The x value.
56301	 * @return {Cylindrical} A reference to this cylindrical.
56302	 */
56303	setFromCartesianCoords( x, y, z ) {
56304
56305		this.radius = Math.sqrt( x * x + z * z );
56306		this.theta = Math.atan2( x, z );
56307		this.y = y;
56308
56309		return this;
56310
56311	}
56312
56313	/**
56314	 * Returns a new cylindrical with copied values from this instance.
56315	 *
56316	 * @return {Cylindrical} A clone of this instance.
56317	 */
56318	clone() {
56319
56320		return new this.constructor().copy( this );
56321
56322	}
56323
56324}
56325
56326/**
56327 * Represents a 2x2 matrix.
56328 *
56329 * A Note on Row-Major and Column-Major Ordering:
56330 *
56331 * The constructor and {@link Matrix2#set} method take arguments in
56332 * [row-major](https://en.wikipedia.org/wiki/Row-_and_column-major_order#Column-major_order)
56333 * order, while internally they are stored in the {@link Matrix2#elements} array in column-major order.
56334 * This means that calling:
56335 * ```js
56336 * const m = new THREE.Matrix2();
56337 * m.set( 11, 12,
56338 *        21, 22 );
56339 * ```
56340 * will result in the elements array containing:
56341 * ```js
56342 * m.elements = [ 11, 21,
56343 *                12, 22 ];
56344 * ```
56345 * and internally all calculations are performed using column-major ordering.
56346 * However, as the actual ordering makes no difference mathematically and
56347 * most people are used to thinking about matrices in row-major order, the
56348 * three.js documentation shows matrices in row-major order. Just bear in
56349 * mind that if you are reading the source code, you'll have to take the
56350 * transpose of any matrices outlined here to make sense of the calculations.
56351 */
56352class Matrix2 {
56353
56354	static {
56355
56356		/**
56357		 * This flag can be used for type testing.
56358		 *
56359		 * @type {boolean}
56360		 * @readonly
56361		 * @default true
56362		 */
56363		Matrix2.prototype.isMatrix2 = true;
56364
56365	}
56366
56367	/**
56368	 * Constructs a new 2x2 matrix. The arguments are supposed to be
56369	 * in row-major order. If no arguments are provided, the constructor
56370	 * initializes the matrix as an identity matrix.
56371	 *
56372	 * @param {number} [n11] - 1-1 matrix element.
56373	 * @param {number} [n12] - 1-2 matrix element.
56374	 * @param {number} [n21] - 2-1 matrix element.
56375	 * @param {number} [n22] - 2-2 matrix element.
56376	 */
56377	constructor( n11, n12, n21, n22 ) {
56378
56379		/**
56380		 * A column-major list of matrix values.
56381		 *
56382		 * @type {Array<number>}
56383		 */
56384		this.elements = [
56385			1, 0,
56386			0, 1,
56387		];
56388
56389		if ( n11 !== undefined ) {
56390
56391			this.set( n11, n12, n21, n22 );
56392
56393		}
56394
56395	}
56396
56397	/**
56398	 * Sets this matrix to the 2x2 identity matrix.
56399	 *
56400	 * @return {Matrix2} A reference to this matrix.
56401	 */
56402	identity() {
56403
56404		this.set(
56405			1, 0,
56406			0, 1,
56407		);
56408
56409		return this;
56410
56411	}
56412
56413	/**
56414	 * Sets the elements of the matrix from the given array.
56415	 *
56416	 * @param {Array<number>} array - The matrix elements in column-major order.
56417	 * @param {number} [offset=0] - Index of the first element in the array.
56418	 * @return {Matrix2} A reference to this matrix.
56419	 */
56420	fromArray( array, offset = 0 ) {
56421
56422		for ( let i = 0; i < 4; i ++ ) {
56423
56424			this.elements[ i ] = array[ i + offset ];
56425
56426		}
56427
56428		return this;
56429
56430	}
56431
56432	/**
56433	 * Sets the elements of the matrix.The arguments are supposed to be
56434	 * in row-major order.
56435	 *
56436	 * @param {number} n11 - 1-1 matrix element.
56437	 * @param {number} n12 - 1-2 matrix element.
56438	 * @param {number} n21 - 2-1 matrix element.
56439	 * @param {number} n22 - 2-2 matrix element.
56440	 * @return {Matrix2} A reference to this matrix.
56441	 */
56442	set( n11, n12, n21, n22 ) {
56443
56444		const te = this.elements;
56445
56446		te[ 0 ] = n11; te[ 2 ] = n12;
56447		te[ 1 ] = n21; te[ 3 ] = n22;
56448
56449		return this;
56450
56451	}
56452
56453}
56454
56455const _vector$4 = /*@__PURE__*/ new Vector2();
56456
56457/**
56458 * Represents an axis-aligned bounding box (AABB) in 2D space.
56459 */
56460class Box2 {
56461
56462	/**
56463	 * Constructs a new bounding box.
56464	 *
56465	 * @param {Vector2} [min=(Infinity,Infinity)] - A vector representing the lower boundary of the box.
56466	 * @param {Vector2} [max=(-Infinity,-Infinity)] - A vector representing the upper boundary of the box.
56467	 */
56468	constructor( min = new Vector2( + Infinity, + Infinity ), max = new Vector2( - Infinity, - Infinity ) ) {
56469
56470		/**
56471		 * This flag can be used for type testing.
56472		 *
56473		 * @type {boolean}
56474		 * @readonly
56475		 * @default true
56476		 */
56477		this.isBox2 = true;
56478
56479		/**
56480		 * The lower boundary of the box.
56481		 *
56482		 * @type {Vector2}
56483		 */
56484		this.min = min;
56485
56486		/**
56487		 * The upper boundary of the box.
56488		 *
56489		 * @type {Vector2}
56490		 */
56491		this.max = max;
56492
56493	}
56494
56495	/**
56496	 * Sets the lower and upper boundaries of this box.
56497	 * Please note that this method only copies the values from the given objects.
56498	 *
56499	 * @param {Vector2} min - The lower boundary of the box.
56500	 * @param {Vector2} max - The upper boundary of the box.
56501	 * @return {Box2} A reference to this bounding box.
56502	 */
56503	set( min, max ) {
56504
56505		this.min.copy( min );
56506		this.max.copy( max );
56507
56508		return this;
56509
56510	}
56511
56512	/**
56513	 * Sets the upper and lower bounds of this box so it encloses the position data
56514	 * in the given array.
56515	 *
56516	 * @param {Array<Vector2>} points - An array holding 2D position data as instances of {@link Vector2}.
56517	 * @return {Box2} A reference to this bounding box.
56518	 */
56519	setFromPoints( points ) {
56520
56521		this.makeEmpty();
56522
56523		for ( let i = 0, il = points.length; i < il; i ++ ) {
56524
56525			this.expandByPoint( points[ i ] );
56526
56527		}
56528
56529		return this;
56530
56531	}
56532
56533	/**
56534	 * Centers this box on the given center vector and sets this box's width, height and
56535	 * depth to the given size values.
56536	 *
56537	 * @param {Vector2} center - The center of the box.
56538	 * @param {Vector2} size - The x and y dimensions of the box.
56539	 * @return {Box2} A reference to this bounding box.
56540	 */
56541	setFromCenterAndSize( center, size ) {
56542
56543		const halfSize = _vector$4.copy( size ).multiplyScalar( 0.5 );
56544		this.min.copy( center ).sub( halfSize );
56545		this.max.copy( center ).add( halfSize );
56546
56547		return this;
56548
56549	}
56550
56551	/**
56552	 * Returns a new box with copied values from this instance.
56553	 *
56554	 * @return {Box2} A clone of this instance.
56555	 */
56556	clone() {
56557
56558		return new this.constructor().copy( this );
56559
56560	}
56561
56562	/**
56563	 * Copies the values of the given box to this instance.
56564	 *
56565	 * @param {Box2} box - The box to copy.
56566	 * @return {Box2} A reference to this bounding box.
56567	 */
56568	copy( box ) {
56569
56570		this.min.copy( box.min );
56571		this.max.copy( box.max );
56572
56573		return this;
56574
56575	}
56576
56577	/**
56578	 * Makes this box empty which means in encloses a zero space in 2D.
56579	 *
56580	 * @return {Box2} A reference to this bounding box.
56581	 */
56582	makeEmpty() {
56583
56584		this.min.x = this.min.y = + Infinity;
56585		this.max.x = this.max.y = - Infinity;
56586
56587		return this;
56588
56589	}
56590
56591	/**
56592	 * Returns true if this box includes zero points within its bounds.
56593	 * Note that a box with equal lower and upper bounds still includes one
56594	 * point, the one both bounds share.
56595	 *
56596	 * @return {boolean} Whether this box is empty or not.
56597	 */
56598	isEmpty() {
56599
56600		// this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
56601
56602		return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y );
56603
56604	}
56605
56606	/**
56607	 * Returns the center point of this box.
56608	 *
56609	 * @param {Vector2} target - The target vector that is used to store the method's result.
56610	 * @return {Vector2} The center point.
56611	 */
56612	getCenter( target ) {
56613
56614		return this.isEmpty() ? target.set( 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 );
56615
56616	}
56617
56618	/**
56619	 * Returns the dimensions of this box.
56620	 *
56621	 * @param {Vector2} target - The target vector that is used to store the method's result.
56622	 * @return {Vector2} The size.
56623	 */
56624	getSize( target ) {
56625
56626		return this.isEmpty() ? target.set( 0, 0 ) : target.subVectors( this.max, this.min );
56627
56628	}
56629
56630	/**
56631	 * Expands the boundaries of this box to include the given point.
56632	 *
56633	 * @param {Vector2} point - The point that should be included by the bounding box.
56634	 * @return {Box2} A reference to this bounding box.
56635	 */
56636	expandByPoint( point ) {
56637
56638		this.min.min( point );
56639		this.max.max( point );
56640
56641		return this;
56642
56643	}
56644
56645	/**
56646	 * Expands this box equilaterally by the given vector. The width of this
56647	 * box will be expanded by the x component of the vector in both
56648	 * directions. The height of this box will be expanded by the y component of
56649	 * the vector in both directions.
56650	 *
56651	 * @param {Vector2} vector - The vector that should expand the bounding box.
56652	 * @return {Box2} A reference to this bounding box.
56653	 */
56654	expandByVector( vector ) {
56655
56656		this.min.sub( vector );
56657		this.max.add( vector );
56658
56659		return this;
56660
56661	}
56662
56663	/**
56664	 * Expands each dimension of the box by the given scalar. If negative, the
56665	 * dimensions of the box will be contracted.
56666	 *
56667	 * @param {number} scalar - The scalar value that should expand the bounding box.
56668	 * @return {Box2} A reference to this bounding box.
56669	 */
56670	expandByScalar( scalar ) {
56671
56672		this.min.addScalar( - scalar );
56673		this.max.addScalar( scalar );
56674
56675		return this;
56676
56677	}
56678
56679	/**
56680	 * Returns `true` if the given point lies within or on the boundaries of this box.
56681	 *
56682	 * @param {Vector2} point - The point to test.
56683	 * @return {boolean} Whether the bounding box contains the given point or not.
56684	 */
56685	containsPoint( point ) {
56686
56687		return point.x >= this.min.x && point.x <= this.max.x &&
56688			point.y >= this.min.y && point.y <= this.max.y;
56689
56690	}
56691
56692	/**
56693	 * Returns `true` if this bounding box includes the entirety of the given bounding box.
56694	 * If this box and the given one are identical, this function also returns `true`.
56695	 *
56696	 * @param {Box2} box - The bounding box to test.
56697	 * @return {boolean} Whether the bounding box contains the given bounding box or not.
56698	 */
56699	containsBox( box ) {
56700
56701		return this.min.x <= box.min.x && box.max.x <= this.max.x &&
56702			this.min.y <= box.min.y && box.max.y <= this.max.y;
56703
56704	}
56705
56706	/**
56707	 * Returns a point as a proportion of this box's width and height.
56708	 *
56709	 * @param {Vector2} point - A point in 2D space.
56710	 * @param {Vector2} target - The target vector that is used to store the method's result.
56711	 * @return {Vector2} A point as a proportion of this box's width and height.
56712	 */
56713	getParameter( point, target ) {
56714
56715		// This can potentially have a divide by zero if the box
56716		// has a size dimension of 0.
56717
56718		return target.set(
56719			( point.x - this.min.x ) / ( this.max.x - this.min.x ),
56720			( point.y - this.min.y ) / ( this.max.y - this.min.y )
56721		);
56722
56723	}
56724
56725	/**
56726	 * Returns `true` if the given bounding box intersects with this bounding box.
56727	 *
56728	 * @param {Box2} box - The bounding box to test.
56729	 * @return {boolean} Whether the given bounding box intersects with this bounding box.
56730	 */
56731	intersectsBox( box ) {
56732
56733		// using 4 splitting planes to rule out intersections
56734
56735		return box.max.x >= this.min.x && box.min.x <= this.max.x &&
56736			box.max.y >= this.min.y && box.min.y <= this.max.y;
56737
56738	}
56739
56740	/**
56741	 * Clamps the given point within the bounds of this box.
56742	 *
56743	 * @param {Vector2} point - The point to clamp.
56744	 * @param {Vector2} target - The target vector that is used to store the method's result.
56745	 * @return {Vector2} The clamped point.
56746	 */
56747	clampPoint( point, target ) {
56748
56749		return target.copy( point ).clamp( this.min, this.max );
56750
56751	}
56752
56753	/**
56754	 * Returns the euclidean distance from any edge of this box to the specified point. If
56755	 * the given point lies inside of this box, the distance will be `0`.
56756	 *
56757	 * @param {Vector2} point - The point to compute the distance to.
56758	 * @return {number} The euclidean distance.
56759	 */
56760	distanceToPoint( point ) {
56761
56762		return this.clampPoint( point, _vector$4 ).distanceTo( point );
56763
56764	}
56765
56766	/**
56767	 * Computes the intersection of this bounding box and the given one, setting the upper
56768	 * bound of this box to the lesser of the two boxes' upper bounds and the
56769	 * lower bound of this box to the greater of the two boxes' lower bounds. If
56770	 * there's no overlap, makes this box empty.
56771	 *
56772	 * @param {Box2} box - The bounding box to intersect with.
56773	 * @return {Box2} A reference to this bounding box.
56774	 */
56775	intersect( box ) {
56776
56777		this.min.max( box.min );
56778		this.max.min( box.max );
56779
56780		if ( this.isEmpty() ) this.makeEmpty();
56781
56782		return this;
56783
56784	}
56785
56786	/**
56787	 * Computes the union of this box and another and the given one, setting the upper
56788	 * bound of this box to the greater of the two boxes' upper bounds and the
56789	 * lower bound of this box to the lesser of the two boxes' lower bounds.
56790	 *
56791	 * @param {Box2} box - The bounding box that will be unioned with this instance.
56792	 * @return {Box2} A reference to this bounding box.
56793	 */
56794	union( box ) {
56795
56796		this.min.min( box.min );
56797		this.max.max( box.max );
56798
56799		return this;
56800
56801	}
56802
56803	/**
56804	 * Adds the given offset to both the upper and lower bounds of this bounding box,
56805	 * effectively moving it in 2D space.
56806	 *
56807	 * @param {Vector2} offset - The offset that should be used to translate the bounding box.
56808	 * @return {Box2} A reference to this bounding box.
56809	 */
56810	translate( offset ) {
56811
56812		this.min.add( offset );
56813		this.max.add( offset );
56814
56815		return this;
56816
56817	}
56818
56819	/**
56820	 * Returns `true` if this bounding box is equal with the given one.
56821	 *
56822	 * @param {Box2} box - The box to test for equality.
56823	 * @return {boolean} Whether this bounding box is equal with the given one.
56824	 */
56825	equals( box ) {
56826
56827		return box.min.equals( this.min ) && box.max.equals( this.max );
56828
56829	}
56830
56831}
56832
56833const _startP = /*@__PURE__*/ new Vector3();
56834const _startEnd = /*@__PURE__*/ new Vector3();
56835
56836const _d1 = /*@__PURE__*/ new Vector3();
56837const _d2 = /*@__PURE__*/ new Vector3();
56838const _r = /*@__PURE__*/ new Vector3();
56839const _c1 = /*@__PURE__*/ new Vector3();
56840const _c2 = /*@__PURE__*/ new Vector3();
56841
56842/**
56843 * An analytical line segment in 3D space represented by a start and end point.
56844 */
56845class Line3 {
56846
56847	/**
56848	 * Constructs a new line segment.
56849	 *
56850	 * @param {Vector3} [start=(0,0,0)] - Start of the line segment.
56851	 * @param {Vector3} [end=(0,0,0)] - End of the line segment.
56852	 */
56853	constructor( start = new Vector3(), end = new Vector3() ) {
56854
56855		/**
56856		 * Start of the line segment.
56857		 *
56858		 * @type {Vector3}
56859		 */
56860		this.start = start;
56861
56862		/**
56863		 * End of the line segment.
56864		 *
56865		 * @type {Vector3}
56866		 */
56867		this.end = end;
56868
56869	}
56870
56871	/**
56872	 * Sets the start and end values by copying the given vectors.
56873	 *
56874	 * @param {Vector3} start - The start point.
56875	 * @param {Vector3} end - The end point.
56876	 * @return {Line3} A reference to this line segment.
56877	 */
56878	set( start, end ) {
56879
56880		this.start.copy( start );
56881		this.end.copy( end );
56882
56883		return this;
56884
56885	}
56886
56887	/**
56888	 * Copies the values of the given line segment to this instance.
56889	 *
56890	 * @param {Line3} line - The line segment to copy.
56891	 * @return {Line3} A reference to this line segment.
56892	 */
56893	copy( line ) {
56894
56895		this.start.copy( line.start );
56896		this.end.copy( line.end );
56897
56898		return this;
56899
56900	}
56901
56902	/**
56903	 * Returns the center of the line segment.
56904	 *
56905	 * @param {Vector3} target - The target vector that is used to store the method's result.
56906	 * @return {Vector3} The center point.
56907	 */
56908	getCenter( target ) {
56909
56910		return target.addVectors( this.start, this.end ).multiplyScalar( 0.5 );
56911
56912	}
56913
56914	/**
56915	 * Returns the delta vector of the line segment's start and end point.
56916	 *
56917	 * @param {Vector3} target - The target vector that is used to store the method's result.
56918	 * @return {Vector3} The delta vector.
56919	 */
56920	delta( target ) {
56921
56922		return target.subVectors( this.end, this.start );
56923
56924	}
56925
56926	/**
56927	 * Returns the squared Euclidean distance between the line' start and end point.
56928	 *
56929	 * @return {number} The squared Euclidean distance.
56930	 */
56931	distanceSq() {
56932
56933		return this.start.distanceToSquared( this.end );
56934
56935	}
56936
56937	/**
56938	 * Returns the Euclidean distance between the line' start and end point.
56939	 *
56940	 * @return {number} The Euclidean distance.
56941	 */
56942	distance() {
56943
56944		return this.start.distanceTo( this.end );
56945
56946	}
56947
56948	/**
56949	 * Returns a vector at a certain position along the line segment.
56950	 *
56951	 * @param {number} t - A value between `[0,1]` to represent a position along the line segment.
56952	 * @param {Vector3} target - The target vector that is used to store the method's result.
56953	 * @return {Vector3} The delta vector.
56954	 */
56955	at( t, target ) {
56956
56957		return this.delta( target ).multiplyScalar( t ).add( this.start );
56958
56959	}
56960
56961	/**
56962	 * Returns a point parameter based on the closest point as projected on the line segment.
56963	 *
56964	 * @param {Vector3} point - The point for which to return a point parameter.
56965	 * @param {boolean} clampToLine - Whether to clamp the result to the range `[0,1]` or not.
56966	 * @return {number} The point parameter.
56967	 */
56968	closestPointToPointParameter( point, clampToLine ) {
56969
56970		_startP.subVectors( point, this.start );
56971		_startEnd.subVectors( this.end, this.start );
56972
56973		const startEnd2 = _startEnd.dot( _startEnd );
56974
56975		if ( startEnd2 === 0 ) return 0;
56976
56977		const startEnd_startP = _startEnd.dot( _startP );
56978
56979		let t = startEnd_startP / startEnd2;
56980
56981		if ( clampToLine ) {
56982
56983			t = clamp( t, 0, 1 );
56984
56985		}
56986
56987		return t;
56988
56989	}
56990
56991	/**
56992	 * Returns the closest point on the line for a given point.
56993	 *
56994	 * @param {Vector3} point - The point to compute the closest point on the line for.
56995	 * @param {boolean} clampToLine - Whether to clamp the result to the range `[0,1]` or not.
56996	 * @param {Vector3} target - The target vector that is used to store the method's result.
56997	 * @return {Vector3} The closest point on the line.
56998	 */
56999	closestPointToPoint( point, clampToLine, target ) {
57000
57001		const t = this.closestPointToPointParameter( point, clampToLine );
57002
57003		return this.delta( target ).multiplyScalar( t ).add( this.start );
57004
57005	}
57006
57007	/**
57008	 * Returns the closest squared distance between this line segment and the given one.
57009	 *
57010	 * @param {Line3} line - The line segment to compute the closest squared distance to.
57011	 * @param {Vector3} [c1] - The closest point on this line segment.
57012	 * @param {Vector3} [c2] - The closest point on the given line segment.
57013	 * @return {number} The squared distance between this line segment and the given one.
57014	 */
57015	distanceSqToLine3( line, c1 = _c1, c2 = _c2 ) {
57016
57017		// from Real-Time Collision Detection by Christer Ericson, chapter 5.1.9
57018
57019		// Computes closest points C1 and C2 of S1(s)=P1+s*(Q1-P1) and
57020		// S2(t)=P2+t*(Q2-P2), returning s and t. Function result is squared
57021		// distance between between S1(s) and S2(t)
57022
57023		const EPSILON = 1e-8 * 1e-8; // must be squared since we compare squared length
57024		let s, t;
57025
57026		const p1 = this.start;
57027		const p2 = line.start;
57028		const q1 = this.end;
57029		const q2 = line.end;
57030
57031		_d1.subVectors( q1, p1 ); // Direction vector of segment S1
57032		_d2.subVectors( q2, p2 ); // Direction vector of segment S2
57033		_r.subVectors( p1, p2 );
57034
57035		const a = _d1.dot( _d1 ); // Squared length of segment S1, always nonnegative
57036		const e = _d2.dot( _d2 ); // Squared length of segment S2, always nonnegative
57037		const f = _d2.dot( _r );
57038
57039		// Check if either or both segments degenerate into points
57040
57041		if ( a <= EPSILON && e <= EPSILON ) {
57042
57043			// Both segments degenerate into points
57044
57045			c1.copy( p1 );
57046			c2.copy( p2 );
57047
57048			c1.sub( c2 );
57049
57050			return c1.dot( c1 );
57051
57052		}
57053
57054		if ( a <= EPSILON ) {
57055
57056			// First segment degenerates into a point
57057
57058			s = 0;
57059			t = f / e; // s = 0 => t = (b*s + f) / e = f / e
57060			t = clamp( t, 0, 1 );
57061
57062
57063		} else {
57064
57065			const c = _d1.dot( _r );
57066
57067			if ( e <= EPSILON ) {
57068
57069				// Second segment degenerates into a point
57070
57071				t = 0;
57072				s = clamp( - c / a, 0, 1 ); // t = 0 => s = (b*t - c) / a = -c / a
57073
57074			} else {
57075
57076				// The general nondegenerate case starts here
57077
57078				const b = _d1.dot( _d2 );
57079				const denom = a * e - b * b; // Always nonnegative
57080
57081				// If segments not parallel, compute closest point on L1 to L2 and
57082				// clamp to segment S1. Else pick arbitrary s (here 0)
57083
57084				if ( denom !== 0 ) {
57085
57086					s = clamp( ( b * f - c * e ) / denom, 0, 1 );
57087
57088				} else {
57089
57090					s = 0;
57091
57092				}
57093
57094				// Compute point on L2 closest to S1(s) using
57095				// t = Dot((P1 + D1*s) - P2,D2) / Dot(D2,D2) = (b*s + f) / e
57096
57097				t = ( b * s + f ) / e;
57098
57099				// If t in [0,1] done. Else clamp t, recompute s for the new value
57100				// of t using s = Dot((P2 + D2*t) - P1,D1) / Dot(D1,D1)= (t*b - c) / a
57101				// and clamp s to [0, 1]
57102
57103				if ( t < 0 ) {
57104
57105					t = 0.;
57106					s = clamp( - c / a, 0, 1 );
57107
57108				} else if ( t > 1 ) {
57109
57110					t = 1;
57111					s = clamp( ( b - c ) / a, 0, 1 );
57112
57113				}
57114
57115			}
57116
57117		}
57118
57119		c1.copy( p1 ).addScaledVector( _d1, s );
57120		c2.copy( p2 ).addScaledVector( _d2, t );
57121
57122		return c1.distanceToSquared( c2 );
57123
57124	}
57125
57126	/**
57127	 * Applies a 4x4 transformation matrix to this line segment.
57128	 *
57129	 * @param {Matrix4} matrix - The transformation matrix.
57130	 * @return {Line3} A reference to this line segment.
57131	 */
57132	applyMatrix4( matrix ) {
57133
57134		this.start.applyMatrix4( matrix );
57135		this.end.applyMatrix4( matrix );
57136
57137		return this;
57138
57139	}
57140
57141	/**
57142	 * Returns `true` if this line segment is equal with the given one.
57143	 *
57144	 * @param {Line3} line - The line segment to test for equality.
57145	 * @return {boolean} Whether this line segment is equal with the given one.
57146	 */
57147	equals( line ) {
57148
57149		return line.start.equals( this.start ) && line.end.equals( this.end );
57150
57151	}
57152
57153	/**
57154	 * Returns a new line segment with copied values from this instance.
57155	 *
57156	 * @return {Line3} A clone of this instance.
57157	 */
57158	clone() {
57159
57160		return new this.constructor().copy( this );
57161
57162	}
57163
57164}
57165
57166const _vector$3 = /*@__PURE__*/ new Vector3();
57167
57168/**
57169 * This displays a cone shaped helper object for a {@link SpotLight}.
57170 *
57171 * When the spot light or its target are transformed or light properties are
57172 * changed, it's necessary to call the `update()` method of the respective helper.
57173 *
57174 * ```js
57175 * const spotLight = new THREE.SpotLight( 0xffffff );
57176 * spotLight.position.set( 10, 10, 10 );
57177 * scene.add( spotLight );
57178 *
57179 * const spotLightHelper = new THREE.SpotLightHelper( spotLight );
57180 * scene.add( spotLightHelper );
57181 * ```
57182 *
57183 * @augments Object3D
57184 */
57185class SpotLightHelper extends Object3D {
57186
57187	/**
57188	 * Constructs a new spot light helper.
57189	 *
57190	 * @param {HemisphereLight} light - The light to be visualized.
57191	 * @param {number|Color|string} [color] - The helper's color. If not set, the helper will take
57192	 * the color of the light.
57193	 */
57194	constructor( light, color ) {
57195
57196		super();
57197
57198		/**
57199		 * The light being visualized.
57200		 *
57201		 * @type {SpotLight}
57202		 */
57203		this.light = light;
57204
57205		this.matrixAutoUpdate = false;
57206
57207		/**
57208		 * The color parameter passed in the constructor.
57209		 * If not set, the helper will take the color of the light.
57210		 *
57211		 * @type {number|Color|string}
57212		 */
57213		this.color = color;
57214
57215		this.type = 'SpotLightHelper';
57216
57217		const geometry = new BufferGeometry();
57218
57219		const positions = [
57220			0, 0, 0, 	0, 0, 1,
57221			0, 0, 0, 	1, 0, 1,
57222			0, 0, 0,	-1, 0, 1,
57223			0, 0, 0, 	0, 1, 1,
57224			0, 0, 0, 	0, -1, 1
57225		];
57226
57227		for ( let i = 0, j = 1, l = 32; i < l; i ++, j ++ ) {
57228
57229			const p1 = ( i / l ) * Math.PI * 2;
57230			const p2 = ( j / l ) * Math.PI * 2;
57231
57232			positions.push(
57233				Math.cos( p1 ), Math.sin( p1 ), 1,
57234				Math.cos( p2 ), Math.sin( p2 ), 1
57235			);
57236
57237		}
57238
57239		geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
57240
57241		const material = new LineBasicMaterial( { fog: false, toneMapped: false } );
57242
57243		this.cone = new LineSegments( geometry, material );
57244		this.add( this.cone );
57245
57246		this.update();
57247
57248	}
57249
57250	/**
57251	 * Frees the GPU-related resources allocated by this instance. Call this
57252	 * method whenever this instance is no longer used in your app.
57253	 */
57254	dispose() {
57255
57256		
vendor: 2,946 bytes, lines 57256-57390
57256this.cone.geometry.dispose();
57257		this.cone.material.dispose();
57258
57259	}
57260
57261	/**
57262	 * Updates the helper to match the position and direction of the
57263	 * light being visualized.
57264	 */
57265	update() {
57266
57267		this.light.updateWorldMatrix( true, false );
57268		this.light.target.updateWorldMatrix( true, false );
57269
57270		// update the local matrix based on the parent and light target transforms
57271		if ( this.parent ) {
57272
57273			this.parent.updateWorldMatrix( true );
57274
57275			this.matrix
57276				.copy( this.parent.matrixWorld )
57277				.invert()
57278				.multiply( this.light.matrixWorld );
57279
57280		} else {
57281
57282			this.matrix.copy( this.light.matrixWorld );
57283
57284		}
57285
57286		this.matrixWorld.copy( this.light.matrixWorld );
57287
57288		const coneLength = this.light.distance ? this.light.distance : 1000;
57289		const coneWidth = coneLength * Math.tan( this.light.angle );
57290
57291		this.cone.scale.set( coneWidth, coneWidth, coneLength );
57292
57293		_vector$3.setFromMatrixPosition( this.light.target.matrixWorld );
57294
57295		this.cone.lookAt( _vector$3 );
57296
57297		if ( this.color !== undefined ) {
57298
57299			this.cone.material.color.set( this.color );
57300
57301		} else {
57302
57303			this.cone.material.color.copy( this.light.color );
57304
57305		}
57306
57307	}
57308
57309}
57310
57311const _vector$2 = /*@__PURE__*/ new Vector3();
57312const _boneMatrix = /*@__PURE__*/ new Matrix4();
57313const _matrixWorldInv = /*@__PURE__*/ new Matrix4();
57314
57315/**
57316 * A helper object to assist with visualizing a {@link Skeleton}.
57317 *
57318 * ```js
57319 * const helper = new THREE.SkeletonHelper( skinnedMesh );
57320 * scene.add( helper );
57321 * ```
57322 *
57323 * @augments LineSegments
57324 */
57325class SkeletonHelper extends LineSegments {
57326
57327	/**
57328	 * Constructs a new skeleton helper.
57329	 *
57330	 * @param {Object3D} object -  Usually an instance of {@link SkinnedMesh}. However, any 3D object
57331	 * can be used if it represents a hierarchy of bones (see {@link Bone}).
57332	 */
57333	constructor( object ) {
57334
57335		const bones = getBoneList( object );
57336
57337		const geometry = new BufferGeometry();
57338
57339		const vertices = [];
57340		const colors = [];
57341
57342		for ( let i = 0; i < bones.length; i ++ ) {
57343
57344			const bone = bones[ i ];
57345
57346			if ( bone.parent && bone.parent.isBone ) {
57347
57348				vertices.push( 0, 0, 0 );
57349				vertices.push( 0, 0, 0 );
57350				colors.push( 0, 0, 0 );
57351				colors.push( 0, 0, 0 );
57352
57353			}
57354
57355		}
57356
57357		geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
57358		geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
57359
57360		const material = new LineBasicMaterial( { vertexColors: true, depthTest: false, depthWrite: false, toneMapped: false, transparent: true } );
57361
57362		super( geometry, material );
57363
57364		/**
57365		 * This flag can be used for type testing.
57366		 *
57367		 * @type {boolean}
57368		 * @readonly
57369		 * @default true
57370		 */
57371		this.isSkeletonHelper = true;
57372
57373		this.type = 'SkeletonHelper';
57374
57375		/**
57376		 * The object being visualized.
57377		 *
57378		 * @type {Object3D}
57379		 */
57380		this.root = object;
57381
57382		/**
57383		 * The list of bones that the helper visualizes.
57384		 *
57385		 * @type {Array<Bone>}
57386		 */
57387		this.bones = bones;
57388
57389		this.matrix = object.matrixWorld;
57390		this.matrixAutoUpdate = false;
vendor: 14,852 bytes, lines 57391-58021
57391
57392		// colors
57393
57394		const color1 = new Color( 0x0000ff );
57395		const color2 = new Color( 0x00ff00 );
57396
57397		this.setColors( color1, color2 );
57398
57399	}
57400
57401	updateMatrixWorld( force ) {
57402
57403		const bones = this.bones;
57404
57405		const geometry = this.geometry;
57406		const position = geometry.getAttribute( 'position' );
57407
57408		_matrixWorldInv.copy( this.root.matrixWorld ).invert();
57409
57410		for ( let i = 0, j = 0; i < bones.length; i ++ ) {
57411
57412			const bone = bones[ i ];
57413
57414			if ( bone.parent && bone.parent.isBone ) {
57415
57416				_boneMatrix.multiplyMatrices( _matrixWorldInv, bone.matrixWorld );
57417				_vector$2.setFromMatrixPosition( _boneMatrix );
57418				position.setXYZ( j, _vector$2.x, _vector$2.y, _vector$2.z );
57419
57420				_boneMatrix.multiplyMatrices( _matrixWorldInv, bone.parent.matrixWorld );
57421				_vector$2.setFromMatrixPosition( _boneMatrix );
57422				position.setXYZ( j + 1, _vector$2.x, _vector$2.y, _vector$2.z );
57423
57424				j += 2;
57425
57426			}
57427
57428		}
57429
57430		geometry.getAttribute( 'position' ).needsUpdate = true;
57431
57432		super.updateMatrixWorld( force );
57433
57434	}
57435
57436	/**
57437	 * Defines the colors of the helper.
57438	 *
57439	 * @param {Color} color1 - The first line color for each bone.
57440	 * @param {Color} color2 - The second line color for each bone.
57441	 * @return {SkeletonHelper} A reference to this helper.
57442	 */
57443	setColors( color1, color2 ) {
57444
57445		const geometry = this.geometry;
57446		const colorAttribute = geometry.getAttribute( 'color' );
57447
57448		for ( let i = 0; i < colorAttribute.count; i += 2 ) {
57449
57450			colorAttribute.setXYZ( i, color1.r, color1.g, color1.b );
57451			colorAttribute.setXYZ( i + 1, color2.r, color2.g, color2.b );
57452
57453		}
57454
57455		colorAttribute.needsUpdate = true;
57456
57457		return this;
57458
57459	}
57460
57461	/**
57462	 * Frees the GPU-related resources allocated by this instance. Call this
57463	 * method whenever this instance is no longer used in your app.
57464	 */
57465	dispose() {
57466
57467		this.geometry.dispose();
57468		this.material.dispose();
57469
57470	}
57471
57472}
57473
57474
57475function getBoneList( object ) {
57476
57477	const boneList = [];
57478
57479	if ( object.isBone === true ) {
57480
57481		boneList.push( object );
57482
57483	}
57484
57485	for ( let i = 0; i < object.children.length; i ++ ) {
57486
57487		boneList.push( ...getBoneList( object.children[ i ] ) );
57488
57489	}
57490
57491	return boneList;
57492
57493}
57494
57495/**
57496 * This displays a helper object consisting of a spherical mesh for
57497 * visualizing an instance of {@link PointLight}.
57498 *
57499 * ```js
57500 * const pointLight = new THREE.PointLight( 0xff0000, 1, 100 );
57501 * pointLight.position.set( 10, 10, 10 );
57502 * scene.add( pointLight );
57503 *
57504 * const sphereSize = 1;
57505 * const pointLightHelper = new THREE.PointLightHelper( pointLight, sphereSize );
57506 * scene.add( pointLightHelper );
57507 * ```
57508 *
57509 * @augments Mesh
57510 */
57511class PointLightHelper extends Mesh {
57512
57513	/**
57514	 * Constructs a new point light helper.
57515	 *
57516	 * @param {PointLight} light - The light to be visualized.
57517	 * @param {number} [sphereSize=1] - The size of the sphere helper.
57518	 * @param {number|Color|string} [color] - The helper's color. If not set, the helper will take
57519	 * the color of the light.
57520	 */
57521	constructor( light, sphereSize, color ) {
57522
57523		const geometry = new SphereGeometry( sphereSize, 4, 2 );
57524		const material = new MeshBasicMaterial( { wireframe: true, fog: false, toneMapped: false } );
57525
57526		super( geometry, material );
57527
57528		/**
57529		 * The light being visualized.
57530		 *
57531		 * @type {PointLight}
57532		 */
57533		this.light = light;
57534
57535		/**
57536		 * The color parameter passed in the constructor.
57537		 * If not set, the helper will take the color of the light.
57538		 *
57539		 * @type {number|Color|string}
57540		 */
57541		this.color = color;
57542
57543		this.type = 'PointLightHelper';
57544
57545		this.matrix = this.light.matrixWorld;
57546		this.matrixAutoUpdate = false;
57547
57548		this.update();
57549
57550	}
57551
57552	/**
57553	 * Frees the GPU-related resources allocated by this instance. Call this
57554	 * method whenever this instance is no longer used in your app.
57555	 */
57556	dispose() {
57557
57558		this.geometry.dispose();
57559		this.material.dispose();
57560
57561	}
57562
57563	/**
57564	 * Updates the helper to match the position of the
57565	 * light being visualized.
57566	 */
57567	update() {
57568
57569		this.light.updateWorldMatrix( true, false );
57570
57571		if ( this.color !== undefined ) {
57572
57573			this.material.color.set( this.color );
57574
57575		} else {
57576
57577			this.material.color.copy( this.light.color );
57578
57579		}
57580
57581		/*
57582		const d = this.light.distance;
57583
57584		if ( d === 0.0 ) {
57585
57586			this.lightDistance.visible = false;
57587
57588		} else {
57589
57590			this.lightDistance.visible = true;
57591			this.lightDistance.scale.set( d, d, d );
57592
57593		}
57594		*/
57595
57596	}
57597
57598}
57599
57600const _vector$1 = /*@__PURE__*/ new Vector3();
57601const _color1 = /*@__PURE__*/ new Color();
57602const _color2 = /*@__PURE__*/ new Color();
57603
57604/**
57605 * Creates a visual aid consisting of a spherical mesh for a
57606 * given {@link HemisphereLight}.
57607 *
57608 * When the hemisphere light is transformed or its light properties are changed,
57609 * it's necessary to call the `update()` method of the respective helper.
57610 *
57611 * ```js
57612 * const light = new THREE.HemisphereLight( 0xffffbb, 0x080820, 1 );
57613 * const helper = new THREE.HemisphereLightHelper( light, 5 );
57614 * scene.add( helper );
57615 * ```
57616 *
57617 * @augments Object3D
57618 */
57619class HemisphereLightHelper extends Object3D {
57620
57621	/**
57622	 * Constructs a new hemisphere light helper.
57623	 *
57624	 * @param {HemisphereLight} light - The light to be visualized.
57625	 * @param {number} [size=1] - The size of the mesh used to visualize the light.
57626	 * @param {number|Color|string} [color] - The helper's color. If not set, the helper will take
57627	 * the color of the light.
57628	 */
57629	constructor( light, size, color ) {
57630
57631		super();
57632
57633		/**
57634		 * The light being visualized.
57635		 *
57636		 * @type {HemisphereLight}
57637		 */
57638		this.light = light;
57639
57640		this.matrix = light.matrixWorld;
57641		this.matrixAutoUpdate = false;
57642
57643		/**
57644		 * The color parameter passed in the constructor.
57645		 * If not set, the helper will take the color of the light.
57646		 *
57647		 * @type {number|Color|string}
57648		 */
57649		this.color = color;
57650
57651		this.type = 'HemisphereLightHelper';
57652
57653		const geometry = new OctahedronGeometry( size );
57654		geometry.rotateY( Math.PI * 0.5 );
57655
57656		this.material = new MeshBasicMaterial( { wireframe: true, fog: false, toneMapped: false } );
57657		if ( this.color === undefined ) this.material.vertexColors = true;
57658
57659		const position = geometry.getAttribute( 'position' );
57660		const colors = new Float32Array( position.count * 3 );
57661
57662		geometry.setAttribute( 'color', new BufferAttribute( colors, 3 ) );
57663
57664		this.add( new Mesh( geometry, this.material ) );
57665
57666		this.update();
57667
57668	}
57669
57670	/**
57671	 * Frees the GPU-related resources allocated by this instance. Call this
57672	 * method whenever this instance is no longer used in your app.
57673	 */
57674	dispose() {
57675
57676		this.children[ 0 ].geometry.dispose();
57677		this.children[ 0 ].material.dispose();
57678
57679	}
57680
57681	/**
57682	 * Updates the helper to match the position and direction of the
57683	 * light being visualized.
57684	 */
57685	update() {
57686
57687		const mesh = this.children[ 0 ];
57688
57689		if ( this.color !== undefined ) {
57690
57691			this.material.color.set( this.color );
57692
57693		} else {
57694
57695			const colors = mesh.geometry.getAttribute( 'color' );
57696
57697			_color1.copy( this.light.color );
57698			_color2.copy( this.light.groundColor );
57699
57700			for ( let i = 0, l = colors.count; i < l; i ++ ) {
57701
57702				const color = ( i < ( l / 2 ) ) ? _color1 : _color2;
57703
57704				colors.setXYZ( i, color.r, color.g, color.b );
57705
57706			}
57707
57708			colors.needsUpdate = true;
57709
57710		}
57711
57712		this.light.updateWorldMatrix( true, false );
57713
57714		mesh.lookAt( _vector$1.setFromMatrixPosition( this.light.matrixWorld ).negate() );
57715
57716	}
57717
57718}
57719
57720/**
57721 * The helper is an object to define grids. Grids are two-dimensional
57722 * arrays of lines.
57723 *
57724 * ```js
57725 * const size = 10;
57726 * const divisions = 10;
57727 *
57728 * const gridHelper = new THREE.GridHelper( size, divisions );
57729 * scene.add( gridHelper );
57730 * ```
57731 *
57732 * @augments LineSegments
57733 */
57734class GridHelper extends LineSegments {
57735
57736	/**
57737	 * Constructs a new grid helper.
57738	 *
57739	 * @param {number} [size=10] - The size of the grid.
57740	 * @param {number} [divisions=10] - The number of divisions across the grid.
57741	 * @param {number|Color|string} [color1=0x444444] - The color of the center line.
57742	 * @param {number|Color|string} [color2=0x888888] - The color of the lines of the grid.
57743	 */
57744	constructor( size = 10, divisions = 10, color1 = 0x444444, color2 = 0x888888 ) {
57745
57746		color1 = new Color( color1 );
57747		color2 = new Color( color2 );
57748
57749		const center = divisions / 2;
57750		const step = size / divisions;
57751		const halfSize = size / 2;
57752
57753		const vertices = [], colors = [];
57754
57755		for ( let i = 0, j = 0, k = - halfSize; i <= divisions; i ++, k += step ) {
57756
57757			vertices.push( - halfSize, 0, k, halfSize, 0, k );
57758			vertices.push( k, 0, - halfSize, k, 0, halfSize );
57759
57760			const color = i === center ? color1 : color2;
57761
57762			color.toArray( colors, j ); j += 3;
57763			color.toArray( colors, j ); j += 3;
57764			color.toArray( colors, j ); j += 3;
57765			color.toArray( colors, j ); j += 3;
57766
57767		}
57768
57769		const geometry = new BufferGeometry();
57770		geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
57771		geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
57772
57773		const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } );
57774
57775		super( geometry, material );
57776
57777		this.type = 'GridHelper';
57778
57779	}
57780
57781	/**
57782	 * Frees the GPU-related resources allocated by this instance. Call this
57783	 * method whenever this instance is no longer used in your app.
57784	 */
57785	dispose() {
57786
57787		this.geometry.dispose();
57788		this.material.dispose();
57789
57790	}
57791
57792}
57793
57794/**
57795 * This helper is an object to define polar grids. Grids are
57796 * two-dimensional arrays of lines.
57797 *
57798 * ```js
57799 * const radius = 10;
57800 * const sectors = 16;
57801 * const rings = 8;
57802 * const divisions = 64;
57803 *
57804 * const helper = new THREE.PolarGridHelper( radius, sectors, rings, divisions );
57805 * scene.add( helper );
57806 * ```
57807 *
57808 * @augments LineSegments
57809 */
57810class PolarGridHelper extends LineSegments {
57811
57812	/**
57813	 * Constructs a new polar grid helper.
57814	 *
57815	 * @param {number} [radius=10] - The radius of the polar grid. This can be any positive number.
57816	 * @param {number} [sectors=16] - The number of sectors the grid will be divided into. This can be any positive integer.
57817	 * @param {number} [rings=16] - The number of rings. This can be any positive integer.
57818	 * @param {number} [divisions=64] - The number of line segments used for each circle. This can be any positive integer.
57819	 * @param {number|Color|string} [color1=0x444444] - The first color used for grid elements.
57820	 * @param {number|Color|string} [color2=0x888888] -  The second color used for grid elements.
57821	 */
57822	constructor( radius = 10, sectors = 16, rings = 8, divisions = 64, color1 = 0x444444, color2 = 0x888888 ) {
57823
57824		color1 = new Color( color1 );
57825		color2 = new Color( color2 );
57826
57827		const vertices = [];
57828		const colors = [];
57829
57830		// create the sectors
57831
57832		if ( sectors > 1 ) {
57833
57834			for ( let i = 0; i < sectors; i ++ ) {
57835
57836				const v = ( i / sectors ) * ( Math.PI * 2 );
57837
57838				const x = Math.sin( v ) * radius;
57839				const z = Math.cos( v ) * radius;
57840
57841				vertices.push( 0, 0, 0 );
57842				vertices.push( x, 0, z );
57843
57844				const color = ( i & 1 ) ? color1 : color2;
57845
57846				colors.push( color.r, color.g, color.b );
57847				colors.push( color.r, color.g, color.b );
57848
57849			}
57850
57851		}
57852
57853		// create the rings
57854
57855		for ( let i = 0; i < rings; i ++ ) {
57856
57857			const color = ( i & 1 ) ? color1 : color2;
57858
57859			const r = radius - ( radius / rings * i );
57860
57861			for ( let j = 0; j < divisions; j ++ ) {
57862
57863				// first vertex
57864
57865				let v = ( j / divisions ) * ( Math.PI * 2 );
57866
57867				let x = Math.sin( v ) * r;
57868				let z = Math.cos( v ) * r;
57869
57870				vertices.push( x, 0, z );
57871				colors.push( color.r, color.g, color.b );
57872
57873				// second vertex
57874
57875				v = ( ( j + 1 ) / divisions ) * ( Math.PI * 2 );
57876
57877				x = Math.sin( v ) * r;
57878				z = Math.cos( v ) * r;
57879
57880				vertices.push( x, 0, z );
57881				colors.push( color.r, color.g, color.b );
57882
57883			}
57884
57885		}
57886
57887		const geometry = new BufferGeometry();
57888		geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
57889		geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
57890
57891		const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } );
57892
57893		super( geometry, material );
57894
57895		this.type = 'PolarGridHelper';
57896
57897	}
57898
57899	/**
57900	 * Frees the GPU-related resources allocated by this instance. Call this
57901	 * method whenever this instance is no longer used in your app.
57902	 */
57903	dispose() {
57904
57905		this.geometry.dispose();
57906		this.material.dispose();
57907
57908	}
57909
57910}
57911
57912const _v1 = /*@__PURE__*/ new Vector3();
57913const _v2 = /*@__PURE__*/ new Vector3();
57914const _v3 = /*@__PURE__*/ new Vector3();
57915
57916/**
57917 * Helper object to assist with visualizing a {@link DirectionalLight}'s
57918 * effect on the scene. This consists of a plane and a line representing the
57919 * light's position and direction.
57920 *
57921 * When the directional light or its target are transformed or light properties
57922 * are changed, it's necessary to call the `update()` method of the respective helper.
57923 *
57924 * ```js
57925 * const light = new THREE.DirectionalLight( 0xFFFFFF );
57926 * scene.add( light );
57927 *
57928 * const helper = new THREE.DirectionalLightHelper( light, 5 );
57929 * scene.add( helper );
57930 * ```
57931 *
57932 * @augments Object3D
57933 */
57934class DirectionalLightHelper extends Object3D {
57935
57936	/**
57937	 * Constructs a new directional light helper.
57938	 *
57939	 * @param {DirectionalLight} light - The light to be visualized.
57940	 * @param {number} [size=1] - The dimensions of the plane.
57941	 * @param {number|Color|string} [color] - The helper's color. If not set, the helper will take
57942	 * the color of the light.
57943	 */
57944	constructor( light, size, color ) {
57945
57946		super();
57947
57948		/**
57949		 * The light being visualized.
57950		 *
57951		 * @type {DirectionalLight}
57952		 */
57953		this.light = light;
57954
57955		this.matrix = light.matrixWorld;
57956		this.matrixAutoUpdate = false;
57957
57958		/**
57959		 * The color parameter passed in the constructor.
57960		 * If not set, the helper will take the color of the light.
57961		 *
57962		 * @type {number|Color|string}
57963		 */
57964		this.color = color;
57965
57966		this.type = 'DirectionalLightHelper';
57967
57968		if ( size === undefined ) size = 1;
57969
57970		let geometry = new BufferGeometry();
57971		geometry.setAttribute( 'position', new Float32BufferAttribute( [
57972			- size, size, 0,
57973			size, size, 0,
57974			size, - size, 0,
57975			- size, - size, 0,
57976			- size, size, 0
57977		], 3 ) );
57978
57979		const material = new LineBasicMaterial( { fog: false, toneMapped: false } );
57980
57981		/**
57982		 * Contains the line showing the location of the directional light.
57983		 *
57984		 * @type {Line}
57985		 */
57986		this.lightPlane = new Line( geometry, material );
57987		this.add( this.lightPlane );
57988
57989		geometry = new BufferGeometry();
57990		geometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 0, 1 ], 3 ) );
57991
57992		/**
57993		 * Represents the target line of the directional light.
57994		 *
57995		 * @type {Line}
57996		 */
57997		this.targetLine = new Line( geometry, material );
57998		this.add( this.targetLine );
57999
58000		this.update();
58001
58002	}
58003
58004	/**
58005	 * Frees the GPU-related resources allocated by this instance. Call this
58006	 * method whenever this instance is no longer used in your app.
58007	 */
58008	dispose() {
58009
58010		this.lightPlane.geometry.dispose();
58011		this.lightPlane.material.dispose();
58012		this.targetLine.geometry.dispose();
58013		this.targetLine.material.dispose();
58014
58015	}
58016
58017	/**
58018	 * Updates the helper to match the position and direction of the
58019	 * light being visualized.
58020	 */
58021	update() {
vendor: 10,100 bytes, lines 58021-58358
58021
58022
58023		this.light.updateWorldMatrix( true, false );
58024		this.light.target.updateWorldMatrix( true, false );
58025
58026		_v1.setFromMatrixPosition( this.light.matrixWorld );
58027		_v2.setFromMatrixPosition( this.light.target.matrixWorld );
58028		_v3.subVectors( _v2, _v1 );
58029
58030		this.lightPlane.lookAt( _v2 );
58031
58032		if ( this.color !== undefined ) {
58033
58034			this.lightPlane.material.color.set( this.color );
58035			this.targetLine.material.color.set( this.color );
58036
58037		} else {
58038
58039			this.lightPlane.material.color.copy( this.light.color );
58040			this.targetLine.material.color.copy( this.light.color );
58041
58042		}
58043
58044		this.targetLine.lookAt( _v2 );
58045		this.targetLine.scale.z = _v3.length();
58046
58047	}
58048
58049}
58050
58051const _vector = /*@__PURE__*/ new Vector3();
58052const _camera = /*@__PURE__*/ new Camera();
58053
58054/**
58055 * This helps with visualizing what a camera contains in its frustum. It
58056 * visualizes the frustum of a camera using a line segments.
58057 *
58058 * Based on frustum visualization in [lightgl.js shadowmap example](https://github.com/evanw/lightgl.js/blob/master/tests/shadowmap.html).
58059 *
58060 * `CameraHelper` must be a child of the scene.
58061 *
58062 * When the camera is transformed or its projection matrix is changed, it's necessary
58063 * to call the `update()` method of the respective helper.
58064 *
58065 * ```js
58066 * const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
58067 * const helper = new THREE.CameraHelper( camera );
58068 * scene.add( helper );
58069 * ```
58070 *
58071 * @augments LineSegments
58072 */
58073class CameraHelper extends LineSegments {
58074
58075	/**
58076	 * Constructs a new arrow helper.
58077	 *
58078	 * @param {Camera} camera - The camera to visualize.
58079	 */
58080	constructor( camera ) {
58081
58082		const geometry = new BufferGeometry();
58083		const material = new LineBasicMaterial( { color: 0xffffff, vertexColors: true, toneMapped: false } );
58084
58085		const vertices = [];
58086		const colors = [];
58087
58088		const pointMap = {};
58089
58090		// near
58091
58092		addLine( 'n1', 'n2' );
58093		addLine( 'n2', 'n4' );
58094		addLine( 'n4', 'n3' );
58095		addLine( 'n3', 'n1' );
58096
58097		// far
58098
58099		addLine( 'f1', 'f2' );
58100		addLine( 'f2', 'f4' );
58101		addLine( 'f4', 'f3' );
58102		addLine( 'f3', 'f1' );
58103
58104		// sides
58105
58106		addLine( 'n1', 'f1' );
58107		addLine( 'n2', 'f2' );
58108		addLine( 'n3', 'f3' );
58109		addLine( 'n4', 'f4' );
58110
58111		// cone
58112
58113		addLine( 'p', 'n1' );
58114		addLine( 'p', 'n2' );
58115		addLine( 'p', 'n3' );
58116		addLine( 'p', 'n4' );
58117
58118		// up
58119
58120		addLine( 'u1', 'u2' );
58121		addLine( 'u2', 'u3' );
58122		addLine( 'u3', 'u1' );
58123
58124		// target
58125
58126		addLine( 'c', 't' );
58127		addLine( 'p', 'c' );
58128
58129		// cross
58130
58131		addLine( 'cn1', 'cn2' );
58132		addLine( 'cn3', 'cn4' );
58133
58134		addLine( 'cf1', 'cf2' );
58135		addLine( 'cf3', 'cf4' );
58136
58137		function addLine( a, b ) {
58138
58139			addPoint( a );
58140			addPoint( b );
58141
58142		}
58143
58144		function addPoint( id ) {
58145
58146			vertices.push( 0, 0, 0 );
58147			colors.push( 0, 0, 0 );
58148
58149			if ( pointMap[ id ] === undefined ) {
58150
58151				pointMap[ id ] = [];
58152
58153			}
58154
58155			pointMap[ id ].push( ( vertices.length / 3 ) - 1 );
58156
58157		}
58158
58159		geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
58160		geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
58161
58162		super( geometry, material );
58163
58164		this.type = 'CameraHelper';
58165
58166		/**
58167		 * The camera being visualized.
58168		 *
58169		 * @type {Camera}
58170		 */
58171		this.camera = camera;
58172		if ( this.camera.updateProjectionMatrix ) this.camera.updateProjectionMatrix();
58173
58174		this.matrix = camera.matrixWorld;
58175		this.matrixAutoUpdate = false;
58176
58177		/**
58178		 * This contains the points used to visualize the camera.
58179		 *
58180		 * @type {Object<string,Array<number>>}
58181		 */
58182		this.pointMap = pointMap;
58183
58184		this.update();
58185
58186		// colors
58187
58188		const colorFrustum = new Color( 0xffaa00 );
58189		const colorCone = new Color( 0xff0000 );
58190		const colorUp = new Color( 0x00aaff );
58191		const colorTarget = new Color( 0xffffff );
58192		const colorCross = new Color( 0x333333 );
58193
58194		this.setColors( colorFrustum, colorCone, colorUp, colorTarget, colorCross );
58195
58196	}
58197
58198	/**
58199	 * Defines the colors of the helper.
58200	 *
58201	 * @param {Color} frustum - The frustum line color.
58202	 * @param {Color} cone - The cone line color.
58203	 * @param {Color} up - The up line color.
58204	 * @param {Color} target - The target line color.
58205	 * @param {Color} cross - The cross line color.
58206	 * @return {CameraHelper} A reference to this helper.
58207	 */
58208	setColors( frustum, cone, up, target, cross ) {
58209
58210		const geometry = this.geometry;
58211
58212		const colorAttribute = geometry.getAttribute( 'color' );
58213
58214		// near
58215
58216		colorAttribute.setXYZ( 0, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 1, frustum.r, frustum.g, frustum.b ); // n1, n2
58217		colorAttribute.setXYZ( 2, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 3, frustum.r, frustum.g, frustum.b ); // n2, n4
58218		colorAttribute.setXYZ( 4, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 5, frustum.r, frustum.g, frustum.b ); // n4, n3
58219		colorAttribute.setXYZ( 6, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 7, frustum.r, frustum.g, frustum.b ); // n3, n1
58220
58221		// far
58222
58223		colorAttribute.setXYZ( 8, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 9, frustum.r, frustum.g, frustum.b ); // f1, f2
58224		colorAttribute.setXYZ( 10, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 11, frustum.r, frustum.g, frustum.b ); // f2, f4
58225		colorAttribute.setXYZ( 12, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 13, frustum.r, frustum.g, frustum.b ); // f4, f3
58226		colorAttribute.setXYZ( 14, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 15, frustum.r, frustum.g, frustum.b ); // f3, f1
58227
58228		// sides
58229
58230		colorAttribute.setXYZ( 16, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 17, frustum.r, frustum.g, frustum.b ); // n1, f1
58231		colorAttribute.setXYZ( 18, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 19, frustum.r, frustum.g, frustum.b ); // n2, f2
58232		colorAttribute.setXYZ( 20, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 21, frustum.r, frustum.g, frustum.b ); // n3, f3
58233		colorAttribute.setXYZ( 22, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 23, frustum.r, frustum.g, frustum.b ); // n4, f4
58234
58235		// cone
58236
58237		colorAttribute.setXYZ( 24, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 25, cone.r, cone.g, cone.b ); // p, n1
58238		colorAttribute.setXYZ( 26, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 27, cone.r, cone.g, cone.b ); // p, n2
58239		colorAttribute.setXYZ( 28, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 29, cone.r, cone.g, cone.b ); // p, n3
58240		colorAttribute.setXYZ( 30, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 31, cone.r, cone.g, cone.b ); // p, n4
58241
58242		// up
58243
58244		colorAttribute.setXYZ( 32, up.r, up.g, up.b ); colorAttribute.setXYZ( 33, up.r, up.g, up.b ); // u1, u2
58245		colorAttribute.setXYZ( 34, up.r, up.g, up.b ); colorAttribute.setXYZ( 35, up.r, up.g, up.b ); // u2, u3
58246		colorAttribute.setXYZ( 36, up.r, up.g, up.b ); colorAttribute.setXYZ( 37, up.r, up.g, up.b ); // u3, u1
58247
58248		// target
58249
58250		colorAttribute.setXYZ( 38, target.r, target.g, target.b ); colorAttribute.setXYZ( 39, target.r, target.g, target.b ); // c, t
58251		colorAttribute.setXYZ( 40, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 41, cross.r, cross.g, cross.b ); // p, c
58252
58253		// cross
58254
58255		colorAttribute.setXYZ( 42, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 43, cross.r, cross.g, cross.b ); // cn1, cn2
58256		colorAttribute.setXYZ( 44, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 45, cross.r, cross.g, cross.b ); // cn3, cn4
58257
58258		colorAttribute.setXYZ( 46, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 47, cross.r, cross.g, cross.b ); // cf1, cf2
58259		colorAttribute.setXYZ( 48, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 49, cross.r, cross.g, cross.b ); // cf3, cf4
58260
58261		colorAttribute.needsUpdate = true;
58262
58263		return this;
58264
58265	}
58266
58267	/**
58268	 * Updates the helper based on the projection matrix of the camera.
58269	 */
58270	update() {
58271
58272		const geometry = this.geometry;
58273		const pointMap = this.pointMap;
58274
58275		const w = 1, h = 1;
58276
58277		let nearZ, farZ;
58278
58279		// we need just camera projection matrix inverse
58280		// world matrix must be identity
58281
58282		_camera.projectionMatrixInverse.copy( this.camera.projectionMatrixInverse );
58283
58284		// Adjust z values based on coordinate system
58285
58286		if ( this.camera.reversedDepth === true ) {
58287
58288			nearZ = 1;
58289			farZ = 0;
58290
58291		} else {
58292
58293			if ( this.camera.coordinateSystem === WebGLCoordinateSystem ) {
58294
58295				nearZ = -1;
58296				farZ = 1;
58297
58298			} else if ( this.camera.coordinateSystem === WebGPUCoordinateSystem ) {
58299
58300				nearZ = 0;
58301				farZ = 1;
58302
58303			} else {
58304
58305				throw new Error( 'THREE.CameraHelper.update(): Invalid coordinate system: ' + this.camera.coordinateSystem );
58306
58307			}
58308
58309		}
58310
58311
58312		// center / target
58313		setPoint( 'c', pointMap, geometry, _camera, 0, 0, nearZ );
58314		setPoint( 't', pointMap, geometry, _camera, 0, 0, farZ );
58315
58316		// near
58317
58318		setPoint( 'n1', pointMap, geometry, _camera, - w, - h, nearZ );
58319		setPoint( 'n2', pointMap, geometry, _camera, w, - h, nearZ );
58320		setPoint( 'n3', pointMap, geometry, _camera, - w, h, nearZ );
58321		setPoint( 'n4', pointMap, geometry, _camera, w, h, nearZ );
58322
58323		// far
58324
58325		setPoint( 'f1', pointMap, geometry, _camera, - w, - h, farZ );
58326		setPoint( 'f2', pointMap, geometry, _camera, w, - h, farZ );
58327		setPoint( 'f3', pointMap, geometry, _camera, - w, h, farZ );
58328		setPoint( 'f4', pointMap, geometry, _camera, w, h, farZ );
58329
58330		// up
58331
58332		setPoint( 'u1', pointMap, geometry, _camera, w * 0.7, h * 1.1, nearZ );
58333		setPoint( 'u2', pointMap, geometry, _camera, - w * 0.7, h * 1.1, nearZ );
58334		setPoint( 'u3', pointMap, geometry, _camera, 0, h * 2, nearZ );
58335
58336		// cross
58337
58338		setPoint( 'cf1', pointMap, geometry, _camera, - w, 0, farZ );
58339		setPoint( 'cf2', pointMap, geometry, _camera, w, 0, farZ );
58340		setPoint( 'cf3', pointMap, geometry, _camera, 0, - h, farZ );
58341		setPoint( 'cf4', pointMap, geometry, _camera, 0, h, farZ );
58342
58343		setPoint( 'cn1', pointMap, geometry, _camera, - w, 0, nearZ );
58344		setPoint( 'cn2', pointMap, geometry, _camera, w, 0, nearZ );
58345		setPoint( 'cn3', pointMap, geometry, _camera, 0, - h, nearZ );
58346		setPoint( 'cn4', pointMap, geometry, _camera, 0, h, nearZ );
58347
58348		geometry.getAttribute( 'position' ).needsUpdate = true;
58349
58350	}
58351
58352	/**
58353	 * Frees the GPU-related resources allocated by this instance. Call this
58354	 * method whenever this instance is no longer used in your app.
58355	 */
58356	dispose() {
58357
58358		
vendor: 12,560 bytes, lines 58358-58895
58358this.geometry.dispose();
58359		this.material.dispose();
58360
58361	}
58362
58363}
58364
58365
58366function setPoint( point, pointMap, geometry, camera, x, y, z ) {
58367
58368	_vector.set( x, y, z ).unproject( camera );
58369
58370	const points = pointMap[ point ];
58371
58372	if ( points !== undefined ) {
58373
58374		const position = geometry.getAttribute( 'position' );
58375
58376		for ( let i = 0, l = points.length; i < l; i ++ ) {
58377
58378			position.setXYZ( points[ i ], _vector.x, _vector.y, _vector.z );
58379
58380		}
58381
58382	}
58383
58384}
58385
58386const _box = /*@__PURE__*/ new Box3();
58387
58388/**
58389 * Helper object to graphically show the world-axis-aligned bounding box
58390 * around an object. The actual bounding box is handled with {@link Box3},
58391 * this is just a visual helper for debugging. It can be automatically
58392 * resized with {@link BoxHelper#update} when the object it's created from
58393 * is transformed. Note that the object must have a geometry for this to work,
58394 * so it won't work with sprites.
58395 *
58396 * ```js
58397 * const sphere = new THREE.SphereGeometry();
58398 * const object = new THREE.Mesh( sphere, new THREE.MeshBasicMaterial( 0xff0000 ) );
58399 * const box = new THREE.BoxHelper( object, 0xffff00 );
58400 * scene.add( box );
58401 * ```
58402 *
58403 * @augments LineSegments
58404 */
58405class BoxHelper extends LineSegments {
58406
58407	/**
58408	 * Constructs a new box helper.
58409	 *
58410	 * @param {Object3D} [object] - The 3D object to show the world-axis-aligned bounding box.
58411	 * @param {number|Color|string} [color=0xffff00] - The box's color.
58412	 */
58413	constructor( object, color = 0xffff00 ) {
58414
58415		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 ] );
58416		const positions = new Float32Array( 8 * 3 );
58417
58418		const geometry = new BufferGeometry();
58419		geometry.setIndex( new BufferAttribute( indices, 1 ) );
58420		geometry.setAttribute( 'position', new BufferAttribute( positions, 3 ) );
58421
58422		super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) );
58423
58424		/**
58425		 * The 3D object being visualized.
58426		 *
58427		 * @type {Object3D}
58428		 */
58429		this.object = object;
58430		this.type = 'BoxHelper';
58431
58432		this.matrixAutoUpdate = false;
58433
58434		this.update();
58435
58436	}
58437
58438	/**
58439	 * Updates the helper's geometry to match the dimensions of the object,
58440	 * including any children.
58441	 */
58442	update() {
58443
58444		if ( this.object !== undefined ) {
58445
58446			_box.setFromObject( this.object );
58447
58448		}
58449
58450		if ( _box.isEmpty() ) return;
58451
58452		const min = _box.min;
58453		const max = _box.max;
58454
58455		/*
58456			5____4
58457		1/___0/|
58458		| 6__|_7
58459		2/___3/
58460
58461		0: max.x, max.y, max.z
58462		1: min.x, max.y, max.z
58463		2: min.x, min.y, max.z
58464		3: max.x, min.y, max.z
58465		4: max.x, max.y, min.z
58466		5: min.x, max.y, min.z
58467		6: min.x, min.y, min.z
58468		7: max.x, min.y, min.z
58469		*/
58470
58471		const position = this.geometry.attributes.position;
58472		const array = position.array;
58473
58474		array[ 0 ] = max.x; array[ 1 ] = max.y; array[ 2 ] = max.z;
58475		array[ 3 ] = min.x; array[ 4 ] = max.y; array[ 5 ] = max.z;
58476		array[ 6 ] = min.x; array[ 7 ] = min.y; array[ 8 ] = max.z;
58477		array[ 9 ] = max.x; array[ 10 ] = min.y; array[ 11 ] = max.z;
58478		array[ 12 ] = max.x; array[ 13 ] = max.y; array[ 14 ] = min.z;
58479		array[ 15 ] = min.x; array[ 16 ] = max.y; array[ 17 ] = min.z;
58480		array[ 18 ] = min.x; array[ 19 ] = min.y; array[ 20 ] = min.z;
58481		array[ 21 ] = max.x; array[ 22 ] = min.y; array[ 23 ] = min.z;
58482
58483		position.needsUpdate = true;
58484
58485		this.geometry.computeBoundingSphere();
58486
58487	}
58488
58489	/**
58490	 * Updates the wireframe box for the passed object.
58491	 *
58492	 * @param {Object3D} object - The 3D object to create the helper for.
58493	 * @return {BoxHelper} A reference to this instance.
58494	 */
58495	setFromObject( object ) {
58496
58497		this.object = object;
58498		this.update();
58499
58500		return this;
58501
58502	}
58503
58504	copy( source, recursive ) {
58505
58506		super.copy( source, recursive );
58507
58508		this.object = source.object;
58509
58510		return this;
58511
58512	}
58513
58514	/**
58515	 * Frees the GPU-related resources allocated by this instance. Call this
58516	 * method whenever this instance is no longer used in your app.
58517	 */
58518	dispose() {
58519
58520		this.geometry.dispose();
58521		this.material.dispose();
58522
58523	}
58524
58525}
58526
58527/**
58528 * A helper object to visualize an instance of {@link Box3}.
58529 *
58530 * ```js
58531 * const box = new THREE.Box3();
58532 * box.setFromCenterAndSize( new THREE.Vector3( 1, 1, 1 ), new THREE.Vector3( 2, 1, 3 ) );
58533 *
58534 * const helper = new THREE.Box3Helper( box, 0xffff00 );
58535 * scene.add( helper )
58536 * ```
58537 *
58538 * @augments LineSegments
58539 */
58540class Box3Helper extends LineSegments {
58541
58542	/**
58543	 * Constructs a new box3 helper.
58544	 *
58545	 * @param {Box3} box - The box to visualize.
58546	 * @param {number|Color|string} [color=0xffff00] - The box's color.
58547	 */
58548	constructor( box, color = 0xffff00 ) {
58549
58550		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 ] );
58551
58552		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 ];
58553
58554		const geometry = new BufferGeometry();
58555
58556		geometry.setIndex( new BufferAttribute( indices, 1 ) );
58557
58558		geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
58559
58560		super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) );
58561
58562		/**
58563		 * The box being visualized.
58564		 *
58565		 * @type {Box3}
58566		 */
58567		this.box = box;
58568
58569		this.type = 'Box3Helper';
58570
58571		this.geometry.computeBoundingSphere();
58572
58573	}
58574
58575	updateMatrixWorld( force ) {
58576
58577		const box = this.box;
58578
58579		if ( box.isEmpty() ) return;
58580
58581		box.getCenter( this.position );
58582
58583		box.getSize( this.scale );
58584
58585		this.scale.multiplyScalar( 0.5 );
58586
58587		super.updateMatrixWorld( force );
58588
58589	}
58590
58591	/**
58592	 * Frees the GPU-related resources allocated by this instance. Call this
58593	 * method whenever this instance is no longer used in your app.
58594	 */
58595	dispose() {
58596
58597		this.geometry.dispose();
58598		this.material.dispose();
58599
58600	}
58601
58602}
58603
58604/**
58605 * A helper object to visualize an instance of {@link Plane}.
58606 *
58607 * ```js
58608 * const plane = new THREE.Plane( new THREE.Vector3( 1, 1, 0.2 ), 3 );
58609 * const helper = new THREE.PlaneHelper( plane, 1, 0xffff00 );
58610 * scene.add( helper );
58611 * ```
58612 *
58613 * @augments Line
58614 */
58615class PlaneHelper extends Line {
58616
58617	/**
58618	 * Constructs a new plane helper.
58619	 *
58620	 * @param {Plane} plane - The plane to be visualized.
58621	 * @param {number} [size=1] - The side length of plane helper.
58622	 * @param {number|Color|string} [hex=0xffff00] - The helper's color.
58623	 */
58624	constructor( plane, size = 1, hex = 0xffff00 ) {
58625
58626		const color = hex;
58627
58628		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 ];
58629
58630		const geometry = new BufferGeometry();
58631		geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
58632		geometry.computeBoundingSphere();
58633
58634		super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) );
58635
58636		this.type = 'PlaneHelper';
58637
58638		/**
58639		 * The plane being visualized.
58640		 *
58641		 * @type {Plane}
58642		 */
58643		this.plane = plane;
58644
58645		/**
58646		 * The side length of plane helper.
58647		 *
58648		 * @type {number}
58649		 * @default 1
58650		 */
58651		this.size = size;
58652
58653		const positions2 = [ 1, 1, 0, -1, 1, 0, -1, -1, 0, 1, 1, 0, -1, -1, 0, 1, -1, 0 ];
58654
58655		const geometry2 = new BufferGeometry();
58656		geometry2.setAttribute( 'position', new Float32BufferAttribute( positions2, 3 ) );
58657		geometry2.computeBoundingSphere();
58658
58659		this.add( new Mesh( geometry2, new MeshBasicMaterial( { color: color, opacity: 0.2, transparent: true, depthWrite: false, toneMapped: false } ) ) );
58660
58661	}
58662
58663	updateMatrixWorld( force ) {
58664
58665		this.position.set( 0, 0, 0 );
58666
58667		this.scale.set( 0.5 * this.size, 0.5 * this.size, 1 );
58668
58669		this.lookAt( this.plane.normal );
58670
58671		this.translateZ( - this.plane.constant );
58672
58673		super.updateMatrixWorld( force );
58674
58675	}
58676
58677	/**
58678	 * Updates the helper to match the position and direction of the
58679	 * light being visualized.
58680	 */
58681	dispose() {
58682
58683		this.geometry.dispose();
58684		this.material.dispose();
58685		this.children[ 0 ].geometry.dispose();
58686		this.children[ 0 ].material.dispose();
58687
58688	}
58689
58690}
58691
58692const _axis = /*@__PURE__*/ new Vector3();
58693let _lineGeometry, _coneGeometry;
58694
58695/**
58696 * An 3D arrow object for visualizing directions.
58697 *
58698 * ```js
58699 * const dir = new THREE.Vector3( 1, 2, 0 );
58700 *
58701 * //normalize the direction vector (convert to vector of length 1)
58702 * dir.normalize();
58703 *
58704 * const origin = new THREE.Vector3( 0, 0, 0 );
58705 * const length = 1;
58706 * const hex = 0xffff00;
58707 *
58708 * const arrowHelper = new THREE.ArrowHelper( dir, origin, length, hex );
58709 * scene.add( arrowHelper );
58710 * ```
58711 *
58712 * @augments Object3D
58713 */
58714class ArrowHelper extends Object3D {
58715
58716	/**
58717	 * Constructs a new arrow helper.
58718	 *
58719	 * @param {Vector3} [dir=(0, 0, 1)] - The (normalized) direction vector.
58720	 * @param {Vector3} [origin=(0, 0, 0)] - Point at which the arrow starts.
58721	 * @param {number} [length=1] - Length of the arrow in world units.
58722	 * @param {(number|Color|string)} [color=0xffff00] - Color of the arrow.
58723	 * @param {number} [headLength=length*0.2] - The length of the head of the arrow.
58724	 * @param {number} [headWidth=headLength*0.2] - The width of the head of the arrow.
58725	 */
58726	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 ) {
58727
58728		super();
58729
58730		this.type = 'ArrowHelper';
58731
58732		if ( _lineGeometry === undefined ) {
58733
58734			_lineGeometry = new BufferGeometry();
58735			_lineGeometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 1, 0 ], 3 ) );
58736
58737			_coneGeometry = new ConeGeometry( 0.5, 1, 5, 1 );
58738			_coneGeometry.translate( 0, -0.5, 0 );
58739
58740		}
58741
58742		this.position.copy( origin );
58743
58744		/**
58745		 * The line part of the arrow helper.
58746		 *
58747		 * @type {Line}
58748		 */
58749		this.line = new Line( _lineGeometry, new LineBasicMaterial( { color: color, toneMapped: false } ) );
58750		this.line.matrixAutoUpdate = false;
58751		this.add( this.line );
58752
58753		/**
58754		 * The cone part of the arrow helper.
58755		 *
58756		 * @type {Mesh}
58757		 */
58758		this.cone = new Mesh( _coneGeometry, new MeshBasicMaterial( { color: color, toneMapped: false } ) );
58759		this.cone.matrixAutoUpdate = false;
58760		this.add( this.cone );
58761
58762		this.setDirection( dir );
58763		this.setLength( length, headLength, headWidth );
58764
58765	}
58766
58767	/**
58768	 * Sets the direction of the helper.
58769	 *
58770	 * @param {Vector3} dir - The normalized direction vector.
58771	 */
58772	setDirection( dir ) {
58773
58774		// dir is assumed to be normalized
58775
58776		if ( dir.y > 0.99999 ) {
58777
58778			this.quaternion.set( 0, 0, 0, 1 );
58779
58780		} else if ( dir.y < -0.99999 ) {
58781
58782			this.quaternion.set( 1, 0, 0, 0 );
58783
58784		} else {
58785
58786			_axis.set( dir.z, 0, - dir.x ).normalize();
58787
58788			const radians = Math.acos( dir.y );
58789
58790			this.quaternion.setFromAxisAngle( _axis, radians );
58791
58792		}
58793
58794	}
58795
58796	/**
58797	 * Sets the length of the helper.
58798	 *
58799	 * @param {number} length - Length of the arrow in world units.
58800	 * @param {number} [headLength=length*0.2] - The length of the head of the arrow.
58801	 * @param {number} [headWidth=headLength*0.2] - The width of the head of the arrow.
58802	 */
58803	setLength( length, headLength = length * 0.2, headWidth = headLength * 0.2 ) {
58804
58805		this.line.scale.set( 1, Math.max( 0.0001, length - headLength ), 1 ); // see #17458
58806		this.line.updateMatrix();
58807
58808		this.cone.scale.set( headWidth, headLength, headWidth );
58809		this.cone.position.y = length;
58810		this.cone.updateMatrix();
58811
58812	}
58813
58814	/**
58815	 * Sets the color of the helper.
58816	 *
58817	 * @param {number|Color|string} color - The color to set.
58818	 */
58819	setColor( color ) {
58820
58821		this.line.material.color.set( color );
58822		this.cone.material.color.set( color );
58823
58824	}
58825
58826	copy( source ) {
58827
58828		super.copy( source, false );
58829
58830		this.line.copy( source.line );
58831		this.cone.copy( source.cone );
58832
58833		return this;
58834
58835	}
58836
58837	/**
58838	 * Frees the GPU-related resources allocated by this instance. Call this
58839	 * method whenever this instance is no longer used in your app.
58840	 */
58841	dispose() {
58842
58843		this.line.geometry.dispose();
58844		this.line.material.dispose();
58845		this.cone.geometry.dispose();
58846		this.cone.material.dispose();
58847
58848	}
58849
58850}
58851
58852/**
58853 * An axis object to visualize the 3 axes in a simple way.
58854 * The X axis is red. The Y axis is green. The Z axis is blue.
58855 *
58856 * ```js
58857 * const axesHelper = new THREE.AxesHelper( 5 );
58858 * scene.add( axesHelper );
58859 * ```
58860 *
58861 * @augments LineSegments
58862 */
58863class AxesHelper extends LineSegments {
58864
58865	/**
58866	 * Constructs a new axes helper.
58867	 *
58868	 * @param {number} [size=1] - Size of the lines representing the axes.
58869	 */
58870	constructor( size = 1 ) {
58871
58872		const vertices = [
58873			0, 0, 0,	size, 0, 0,
58874			0, 0, 0,	0, size, 0,
58875			0, 0, 0,	0, 0, size
58876		];
58877
58878		const colors = [
58879			1, 0, 0,	1, 0.6, 0,
58880			0, 1, 0,	0.6, 1, 0,
58881			0, 0, 1,	0, 0.6, 1
58882		];
58883
58884		const geometry = new BufferGeometry();
58885		geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
58886		geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
58887
58888		const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } );
58889
58890		super( geometry, material );
58891
58892		this.type = 'AxesHelper';
58893
58894	}
58895
vendor: 9,197 bytes, lines 58896-59300
58896	/**
58897	 * Defines the colors of the axes helper.
58898	 *
58899	 * @param {number|Color|string} xAxisColor - The color for the x axis.
58900	 * @param {number|Color|string} yAxisColor - The color for the y axis.
58901	 * @param {number|Color|string} zAxisColor - The color for the z axis.
58902	 * @return {AxesHelper} A reference to this axes helper.
58903	 */
58904	setColors( xAxisColor, yAxisColor, zAxisColor ) {
58905
58906		const color = new Color();
58907		const array = this.geometry.attributes.color.array;
58908
58909		color.set( xAxisColor );
58910		color.toArray( array, 0 );
58911		color.toArray( array, 3 );
58912
58913		color.set( yAxisColor );
58914		color.toArray( array, 6 );
58915		color.toArray( array, 9 );
58916
58917		color.set( zAxisColor );
58918		color.toArray( array, 12 );
58919		color.toArray( array, 15 );
58920
58921		this.geometry.attributes.color.needsUpdate = true;
58922
58923		return this;
58924
58925	}
58926
58927	/**
58928	 * Frees the GPU-related resources allocated by this instance. Call this
58929	 * method whenever this instance is no longer used in your app.
58930	 */
58931	dispose() {
58932
58933		this.geometry.dispose();
58934		this.material.dispose();
58935
58936	}
58937
58938}
58939
58940/**
58941 * This class is used to convert a series of paths to an array of
58942 * shapes. It is specifically used in context of fonts and SVG.
58943 */
58944class ShapePath {
58945
58946	/**
58947	 * Constructs a new shape path.
58948	 */
58949	constructor() {
58950
58951		this.type = 'ShapePath';
58952
58953		/**
58954		 * The color of the shape.
58955		 *
58956		 * @type {Color}
58957		 */
58958		this.color = new Color();
58959
58960		/**
58961		 * The paths that have been generated for this shape.
58962		 *
58963		 * @type {Array<Path>}
58964		 * @default null
58965		 */
58966		this.subPaths = [];
58967
58968		/**
58969		 * The current path that is being generated.
58970		 *
58971		 * @type {?Path}
58972		 * @default null
58973		 */
58974		this.currentPath = null;
58975
58976	}
58977
58978	/**
58979	 * Creates a new path and moves it current point to the given one.
58980	 *
58981	 * @param {number} x - The x coordinate.
58982	 * @param {number} y - The y coordinate.
58983	 * @return {ShapePath} A reference to this shape path.
58984	 */
58985	moveTo( x, y ) {
58986
58987		this.currentPath = new Path();
58988		this.subPaths.push( this.currentPath );
58989		this.currentPath.moveTo( x, y );
58990
58991		return this;
58992
58993	}
58994
58995	/**
58996	 * Adds an instance of {@link LineCurve} to the path by connecting
58997	 * the current point with the given one.
58998	 *
58999	 * @param {number} x - The x coordinate of the end point.
59000	 * @param {number} y - The y coordinate of the end point.
59001	 * @return {ShapePath} A reference to this shape path.
59002	 */
59003	lineTo( x, y ) {
59004
59005		this.currentPath.lineTo( x, y );
59006
59007		return this;
59008
59009	}
59010
59011	/**
59012	 * Adds an instance of {@link QuadraticBezierCurve} to the path by connecting
59013	 * the current point with the given one.
59014	 *
59015	 * @param {number} aCPx - The x coordinate of the control point.
59016	 * @param {number} aCPy - The y coordinate of the control point.
59017	 * @param {number} aX - The x coordinate of the end point.
59018	 * @param {number} aY - The y coordinate of the end point.
59019	 * @return {ShapePath} A reference to this shape path.
59020	 */
59021	quadraticCurveTo( aCPx, aCPy, aX, aY ) {
59022
59023		this.currentPath.quadraticCurveTo( aCPx, aCPy, aX, aY );
59024
59025		return this;
59026
59027	}
59028
59029	/**
59030	 * Adds an instance of {@link CubicBezierCurve} to the path by connecting
59031	 * the current point with the given one.
59032	 *
59033	 * @param {number} aCP1x - The x coordinate of the first control point.
59034	 * @param {number} aCP1y - The y coordinate of the first control point.
59035	 * @param {number} aCP2x - The x coordinate of the second control point.
59036	 * @param {number} aCP2y - The y coordinate of the second control point.
59037	 * @param {number} aX - The x coordinate of the end point.
59038	 * @param {number} aY - The y coordinate of the end point.
59039	 * @return {ShapePath} A reference to this shape path.
59040	 */
59041	bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) {
59042
59043		this.currentPath.bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY );
59044
59045		return this;
59046
59047	}
59048
59049	/**
59050	 * Adds an instance of {@link SplineCurve} to the path by connecting
59051	 * the current point with the given list of points.
59052	 *
59053	 * @param {Array<Vector2>} pts - An array of points in 2D space.
59054	 * @return {ShapePath} A reference to this shape path.
59055	 */
59056	splineThru( pts ) {
59057
59058		this.currentPath.splineThru( pts );
59059
59060		return this;
59061
59062	}
59063
59064	/**
59065	 * Converts the paths into an array of shapes.
59066	 *
59067	 * @param {boolean} isCCW - By default solid shapes are  defined clockwise (CW) and holes are defined counterclockwise (CCW).
59068	 * If this flag is set to `true`, then those are flipped.
59069	 * @return {Array<Shape>} An array of shapes.
59070	 */
59071	toShapes( isCCW ) {
59072
59073		function toShapesNoHoles( inSubpaths ) {
59074
59075			const shapes = [];
59076
59077			for ( let i = 0, l = inSubpaths.length; i < l; i ++ ) {
59078
59079				const tmpPath = inSubpaths[ i ];
59080
59081				const tmpShape = new Shape();
59082				tmpShape.curves = tmpPath.curves;
59083
59084				shapes.push( tmpShape );
59085
59086			}
59087
59088			return shapes;
59089
59090		}
59091
59092		function isPointInsidePolygon( inPt, inPolygon ) {
59093
59094			const polyLen = inPolygon.length;
59095
59096			// inPt on polygon contour => immediate success    or
59097			// toggling of inside/outside at every single! intersection point of an edge
59098			//  with the horizontal line through inPt, left of inPt
59099			//  not counting lowerY endpoints of edges and whole edges on that line
59100			let inside = false;
59101			for ( let p = polyLen - 1, q = 0; q < polyLen; p = q ++ ) {
59102
59103				let edgeLowPt = inPolygon[ p ];
59104				let edgeHighPt = inPolygon[ q ];
59105
59106				let edgeDx = edgeHighPt.x - edgeLowPt.x;
59107				let edgeDy = edgeHighPt.y - edgeLowPt.y;
59108
59109				if ( Math.abs( edgeDy ) > Number.EPSILON ) {
59110
59111					// not parallel
59112					if ( edgeDy < 0 ) {
59113
59114						edgeLowPt = inPolygon[ q ]; edgeDx = - edgeDx;
59115						edgeHighPt = inPolygon[ p ]; edgeDy = - edgeDy;
59116
59117					}
59118
59119					if ( ( inPt.y < edgeLowPt.y ) || ( inPt.y > edgeHighPt.y ) ) 		continue;
59120
59121					if ( inPt.y === edgeLowPt.y ) {
59122
59123						if ( inPt.x === edgeLowPt.x )		return	true;		// inPt is on contour ?
59124						// continue;				// no intersection or edgeLowPt => doesn't count !!!
59125
59126					} else {
59127
59128						const perpEdge = edgeDy * ( inPt.x - edgeLowPt.x ) - edgeDx * ( inPt.y - edgeLowPt.y );
59129						if ( perpEdge === 0 )				return	true;		// inPt is on contour ?
59130						if ( perpEdge < 0 ) 				continue;
59131						inside = ! inside;		// true intersection left of inPt
59132
59133					}
59134
59135				} else {
59136
59137					// parallel or collinear
59138					if ( inPt.y !== edgeLowPt.y ) 		continue;			// parallel
59139					// edge lies on the same horizontal line as inPt
59140					if ( ( ( edgeHighPt.x <= inPt.x ) && ( inPt.x <= edgeLowPt.x ) ) ||
59141						 ( ( edgeLowPt.x <= inPt.x ) && ( inPt.x <= edgeHighPt.x ) ) )		return	true;	// inPt: Point on contour !
59142					// continue;
59143
59144				}
59145
59146			}
59147
59148			return	inside;
59149
59150		}
59151
59152		const isClockWise = ShapeUtils.isClockWise;
59153
59154		const subPaths = this.subPaths;
59155		if ( subPaths.length === 0 ) return [];
59156
59157		let solid, tmpPath, tmpShape;
59158		const shapes = [];
59159
59160		if ( subPaths.length === 1 ) {
59161
59162			tmpPath = subPaths[ 0 ];
59163			tmpShape = new Shape();
59164			tmpShape.curves = tmpPath.curves;
59165			shapes.push( tmpShape );
59166			return shapes;
59167
59168		}
59169
59170		let holesFirst = ! isClockWise( subPaths[ 0 ].getPoints() );
59171		holesFirst = isCCW ? ! holesFirst : holesFirst;
59172
59173		// log("Holes first", holesFirst);
59174
59175		const betterShapeHoles = [];
59176		const newShapes = [];
59177		let newShapeHoles = [];
59178		let mainIdx = 0;
59179		let tmpPoints;
59180
59181		newShapes[ mainIdx ] = undefined;
59182		newShapeHoles[ mainIdx ] = [];
59183
59184		for ( let i = 0, l = subPaths.length; i < l; i ++ ) {
59185
59186			tmpPath = subPaths[ i ];
59187			tmpPoints = tmpPath.getPoints();
59188			solid = isClockWise( tmpPoints );
59189			solid = isCCW ? ! solid : solid;
59190
59191			if ( solid ) {
59192
59193				if ( ( ! holesFirst ) && ( newShapes[ mainIdx ] ) )	mainIdx ++;
59194
59195				newShapes[ mainIdx ] = { s: new Shape(), p: tmpPoints };
59196				newShapes[ mainIdx ].s.curves = tmpPath.curves;
59197
59198				if ( holesFirst )	mainIdx ++;
59199				newShapeHoles[ mainIdx ] = [];
59200
59201				//log('cw', i);
59202
59203			} else {
59204
59205				newShapeHoles[ mainIdx ].push( { h: tmpPath, p: tmpPoints[ 0 ] } );
59206
59207				//log('ccw', i);
59208
59209			}
59210
59211		}
59212
59213		// only Holes? -> probably all Shapes with wrong orientation
59214		if ( ! newShapes[ 0 ] )	return	toShapesNoHoles( subPaths );
59215
59216
59217		if ( newShapes.length > 1 ) {
59218
59219			let ambiguous = false;
59220			let toChange = 0;
59221
59222			for ( let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
59223
59224				betterShapeHoles[ sIdx ] = [];
59225
59226			}
59227
59228			for ( let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
59229
59230				const sho = newShapeHoles[ sIdx ];
59231
59232				for ( let hIdx = 0; hIdx < sho.length; hIdx ++ ) {
59233
59234					const ho = sho[ hIdx ];
59235					let hole_unassigned = true;
59236
59237					for ( let s2Idx = 0; s2Idx < newShapes.length; s2Idx ++ ) {
59238
59239						if ( isPointInsidePolygon( ho.p, newShapes[ s2Idx ].p ) ) {
59240
59241							if ( sIdx !== s2Idx )	toChange ++;
59242
59243							if ( hole_unassigned ) {
59244
59245								hole_unassigned = false;
59246								betterShapeHoles[ s2Idx ].push( ho );
59247
59248							} else {
59249
59250								ambiguous = true;
59251
59252							}
59253
59254						}
59255
59256					}
59257
59258					if ( hole_unassigned ) {
59259
59260						betterShapeHoles[ sIdx ].push( ho );
59261
59262					}
59263
59264				}
59265
59266			}
59267
59268			if ( toChange > 0 && ambiguous === false ) {
59269
59270				newShapeHoles = betterShapeHoles;
59271
59272			}
59273
59274		}
59275
59276		let tmpHoles;
59277
59278		for ( let i = 0, il = newShapes.length; i < il; i ++ ) {
59279
59280			tmpShape = newShapes[ i ].s;
59281			shapes.push( tmpShape );
59282			tmpHoles = newShapeHoles[ i ];
59283
59284			for ( let j = 0, jl = tmpHoles.length; j < jl; j ++ ) {
59285
59286				tmpShape.holes.push( tmpHoles[ j ].h );
59287
59288			}
59289
59290		}
59291
59292		//log("shape", shapes);
59293
59294		return shapes;
59295
59296	}
59297
59298}
59299
59300/**
59301 * Abstract base class for controls.
59302 *
59303 * @abstract
59304 * @augments EventDispatcher
59305 */
59306class Controls extends EventDispatcher {
59307
59308	/**
59309	 * Constructs a new controls instance.
59310	 *
59311	 * @param {Object3D} object - The object that is managed by the controls.
59312	 * @param {?HTMLElement} domElement - The HTML element used for event listeners.
59313	 */
59314	constructor( object, domElement = null ) {
59315
59316		super();
59317
59318		/**
59319		 * The object that is managed by the controls.
59320		 *
59321		 * @type {Object3D}
59322		 */
59323		this.object = object;
59324
59325		/**
59326		 * The HTML element used for event listeners.
59327		 *
59328		 * @type {?HTMLElement}
59329		 * @default null
59330		 */
59331		this.domElement = domElement;
59332
59333		/**
59334		 * Whether the controls responds to user input or not.
59335		 *
59336		 * @type {boolean}
59337		 * @default true
59338		 */
59339		this.enabled = true;
59340
59341		/**
59342		 * The internal state of the controls.
59343		 *
59344		 * @type {number}
59345		 * @default -1
59346		 */
59347		this.state = -1;
59348
59349		/**
59350		 * This object defines the keyboard input of the controls.
59351		 *
59352		 * @type {Object}
59353		 */
59354		this.keys = {};
59355
59356		/**
59357		 * This object defines what type of actions are assigned to the available mouse buttons.
59358		 * It depends on the control implementation what kind of mouse buttons and actions are supported.
59359		 *
59360		 * @type {{LEFT: ?number, MIDDLE: ?number, RIGHT: ?number}}
59361		 */
59362		this.mouseButtons = { LEFT: null, MIDDLE: null, RIGHT: null };
59363
59364		/**
59365		 * This object defines what type of actions are assigned to what kind of touch interaction.
59366		 * It depends on the control implementation what kind of touch interaction and actions are supported.
59367		 *
59368		 * @type {{ONE: ?number, TWO: ?number}}
59369		 */
59370		this.touches = { ONE: null, TWO: null };
59371
59372	}
59373
59374	/**
59375	 * Connects the controls to the DOM. This method has so called "side effects" since
59376	 * it adds the module's event listeners to the DOM.
59377	 *
59378	 * @param {HTMLElement} element - The DOM element to connect to.
59379	 */
59380	connect( element ) {
59381
59382		if ( element === undefined ) {
59383
59384			warn( 'Controls: connect() now requires an element.' ); // @deprecated, the warning can be removed with r185
59385			return;
59386
59387		}
vendor: 8,049 bytes, lines 59387-59640
59387
59388
59389		if ( this.domElement !== null ) this.disconnect();
59390
59391		this.domElement = element;
59392
59393	}
59394
59395	/**
59396	 * Disconnects the controls from the DOM.
59397	 */
59398	disconnect() {}
59399
59400	/**
59401	 * Call this method if you no longer want use to the controls. It frees all internal
59402	 * resources and removes all event listeners.
59403	 */
59404	dispose() {}
59405
59406	/**
59407	 * Controls should implement this method if they have to update their internal state
59408	 * per simulation step.
59409	 *
59410	 * @param {number} [delta] - The time delta in seconds.
59411	 */
59412	update( /* delta */ ) {}
59413
59414}
59415
59416/**
59417 * Scales the texture as large as possible within its surface without cropping
59418 * or stretching the texture. The method preserves the original aspect ratio of
59419 * the texture. Akin to CSS `object-fit: contain`
59420 *
59421 * @param {Texture} texture - The texture.
59422 * @param {number} aspect - The texture's aspect ratio.
59423 * @return {Texture} The updated texture.
59424 */
59425function contain( texture, aspect ) {
59426
59427	const imageAspect = ( texture.image && texture.image.width ) ? texture.image.width / texture.image.height : 1;
59428
59429	if ( imageAspect > aspect ) {
59430
59431		texture.repeat.x = 1;
59432		texture.repeat.y = imageAspect / aspect;
59433
59434		texture.offset.x = 0;
59435		texture.offset.y = ( 1 - texture.repeat.y ) / 2;
59436
59437	} else {
59438
59439		texture.repeat.x = aspect / imageAspect;
59440		texture.repeat.y = 1;
59441
59442		texture.offset.x = ( 1 - texture.repeat.x ) / 2;
59443		texture.offset.y = 0;
59444
59445	}
59446
59447	return texture;
59448
59449}
59450
59451/**
59452 * Scales the texture to the smallest possible size to fill the surface, leaving
59453 * no empty space. The method preserves the original aspect ratio of the texture.
59454 * Akin to CSS `object-fit: cover`.
59455 *
59456 * @param {Texture} texture - The texture.
59457 * @param {number} aspect - The texture's aspect ratio.
59458 * @return {Texture} The updated texture.
59459 */
59460function cover( texture, aspect ) {
59461
59462	const imageAspect = ( texture.image && texture.image.width ) ? texture.image.width / texture.image.height : 1;
59463
59464	if ( imageAspect > aspect ) {
59465
59466		texture.repeat.x = aspect / imageAspect;
59467		texture.repeat.y = 1;
59468
59469		texture.offset.x = ( 1 - texture.repeat.x ) / 2;
59470		texture.offset.y = 0;
59471
59472	} else {
59473
59474		texture.repeat.x = 1;
59475		texture.repeat.y = imageAspect / aspect;
59476
59477		texture.offset.x = 0;
59478		texture.offset.y = ( 1 - texture.repeat.y ) / 2;
59479
59480	}
59481
59482	return texture;
59483
59484}
59485
59486/**
59487 * Configures the texture to the default transformation. Akin to CSS `object-fit: fill`.
59488 *
59489 * @param {Texture} texture - The texture.
59490 * @return {Texture} The updated texture.
59491 */
59492function fill( texture ) {
59493
59494	texture.repeat.x = 1;
59495	texture.repeat.y = 1;
59496
59497	texture.offset.x = 0;
59498	texture.offset.y = 0;
59499
59500	return texture;
59501
59502}
59503
59504/**
59505 * Determines how many bytes must be used to represent the texture.
59506 *
59507 * @param {number} width - The width of the texture.
59508 * @param {number} height - The height of the texture.
59509 * @param {number} format - The texture's format.
59510 * @param {number} type - The texture's type.
59511 * @return {number} The byte length.
59512 */
59513function getByteLength( width, height, format, type ) {
59514
59515	const typeByteLength = getTextureTypeByteLength( type );
59516
59517	switch ( format ) {
59518
59519		// https://registry.khronos.org/OpenGL-Refpages/es3.0/html/glTexImage2D.xhtml
59520		case AlphaFormat:
59521			return width * height;
59522		case RedFormat:
59523			return ( ( width * height ) / typeByteLength.components ) * typeByteLength.byteLength;
59524		case RedIntegerFormat:
59525			return ( ( width * height ) / typeByteLength.components ) * typeByteLength.byteLength;
59526		case RGFormat:
59527			return ( ( width * height * 2 ) / typeByteLength.components ) * typeByteLength.byteLength;
59528		case RGIntegerFormat:
59529			return ( ( width * height * 2 ) / typeByteLength.components ) * typeByteLength.byteLength;
59530		case RGBFormat:
59531			return ( ( width * height * 3 ) / typeByteLength.components ) * typeByteLength.byteLength;
59532		case RGBAFormat:
59533			return ( ( width * height * 4 ) / typeByteLength.components ) * typeByteLength.byteLength;
59534		case RGBAIntegerFormat:
59535			return ( ( width * height * 4 ) / typeByteLength.components ) * typeByteLength.byteLength;
59536
59537		// https://registry.khronos.org/webgl/extensions/WEBGL_compressed_texture_s3tc_srgb/
59538		case RGB_S3TC_DXT1_Format:
59539		case RGBA_S3TC_DXT1_Format:
59540			return Math.floor( ( width + 3 ) / 4 ) * Math.floor( ( height + 3 ) / 4 ) * 8;
59541		case RGBA_S3TC_DXT3_Format:
59542		case RGBA_S3TC_DXT5_Format:
59543			return Math.floor( ( width + 3 ) / 4 ) * Math.floor( ( height + 3 ) / 4 ) * 16;
59544
59545		// https://registry.khronos.org/webgl/extensions/WEBGL_compressed_texture_pvrtc/
59546		case RGB_PVRTC_2BPPV1_Format:
59547		case RGBA_PVRTC_2BPPV1_Format:
59548			return ( Math.max( width, 16 ) * Math.max( height, 8 ) ) / 4;
59549		case RGB_PVRTC_4BPPV1_Format:
59550		case RGBA_PVRTC_4BPPV1_Format:
59551			return ( Math.max( width, 8 ) * Math.max( height, 8 ) ) / 2;
59552
59553		// https://registry.khronos.org/webgl/extensions/WEBGL_compressed_texture_etc/
59554		case RGB_ETC1_Format:
59555		case RGB_ETC2_Format:
59556		case R11_EAC_Format:
59557		case SIGNED_R11_EAC_Format:
59558			return Math.floor( ( width + 3 ) / 4 ) * Math.floor( ( height + 3 ) / 4 ) * 8;
59559		case RGBA_ETC2_EAC_Format:
59560		case RG11_EAC_Format:
59561		case SIGNED_RG11_EAC_Format:
59562			return Math.floor( ( width + 3 ) / 4 ) * Math.floor( ( height + 3 ) / 4 ) * 16;
59563
59564		// https://registry.khronos.org/webgl/extensions/WEBGL_compressed_texture_astc/
59565		case RGBA_ASTC_4x4_Format:
59566			return Math.floor( ( width + 3 ) / 4 ) * Math.floor( ( height + 3 ) / 4 ) * 16;
59567		case RGBA_ASTC_5x4_Format:
59568			return Math.floor( ( width + 4 ) / 5 ) * Math.floor( ( height + 3 ) / 4 ) * 16;
59569		case RGBA_ASTC_5x5_Format:
59570			return Math.floor( ( width + 4 ) / 5 ) * Math.floor( ( height + 4 ) / 5 ) * 16;
59571		case RGBA_ASTC_6x5_Format:
59572			return Math.floor( ( width + 5 ) / 6 ) * Math.floor( ( height + 4 ) / 5 ) * 16;
59573		case RGBA_ASTC_6x6_Format:
59574			return Math.floor( ( width + 5 ) / 6 ) * Math.floor( ( height + 5 ) / 6 ) * 16;
59575		case RGBA_ASTC_8x5_Format:
59576			return Math.floor( ( width + 7 ) / 8 ) * Math.floor( ( height + 4 ) / 5 ) * 16;
59577		case RGBA_ASTC_8x6_Format:
59578			return Math.floor( ( width + 7 ) / 8 ) * Math.floor( ( height + 5 ) / 6 ) * 16;
59579		case RGBA_ASTC_8x8_Format:
59580			return Math.floor( ( width + 7 ) / 8 ) * Math.floor( ( height + 7 ) / 8 ) * 16;
59581		case RGBA_ASTC_10x5_Format:
59582			return Math.floor( ( width + 9 ) / 10 ) * Math.floor( ( height + 4 ) / 5 ) * 16;
59583		case RGBA_ASTC_10x6_Format:
59584			return Math.floor( ( width + 9 ) / 10 ) * Math.floor( ( height + 5 ) / 6 ) * 16;
59585		case RGBA_ASTC_10x8_Format:
59586			return Math.floor( ( width + 9 ) / 10 ) * Math.floor( ( height + 7 ) / 8 ) * 16;
59587		case RGBA_ASTC_10x10_Format:
59588			return Math.floor( ( width + 9 ) / 10 ) * Math.floor( ( height + 9 ) / 10 ) * 16;
59589		case RGBA_ASTC_12x10_Format:
59590			return Math.floor( ( width + 11 ) / 12 ) * Math.floor( ( height + 9 ) / 10 ) * 16;
59591		case RGBA_ASTC_12x12_Format:
59592			return Math.floor( ( width + 11 ) / 12 ) * Math.floor( ( height + 11 ) / 12 ) * 16;
59593
59594		// https://registry.khronos.org/webgl/extensions/EXT_texture_compression_bptc/
59595		case RGBA_BPTC_Format:
59596		case RGB_BPTC_SIGNED_Format:
59597		case RGB_BPTC_UNSIGNED_Format:
59598			return Math.ceil( width / 4 ) * Math.ceil( height / 4 ) * 16;
59599
59600		// https://registry.khronos.org/webgl/extensions/EXT_texture_compression_rgtc/
59601		case RED_RGTC1_Format:
59602		case SIGNED_RED_RGTC1_Format:
59603			return Math.ceil( width / 4 ) * Math.ceil( height / 4 ) * 8;
59604		case RED_GREEN_RGTC2_Format:
59605		case SIGNED_RED_GREEN_RGTC2_Format:
59606			return Math.ceil( width / 4 ) * Math.ceil( height / 4 ) * 16;
59607
59608	}
59609
59610	throw new Error(
59611		`Unable to determine texture byte length for ${format} format.`,
59612	);
59613
59614}
59615
59616function getTextureTypeByteLength( type ) {
59617
59618	switch ( type ) {
59619
59620		case UnsignedByteType:
59621		case ByteType:
59622			return { byteLength: 1, components: 1 };
59623		case UnsignedShortType:
59624		case ShortType:
59625		case HalfFloatType:
59626			return { byteLength: 2, components: 1 };
59627		case UnsignedShort4444Type:
59628		case UnsignedShort5551Type:
59629			return { byteLength: 2, components: 4 };
59630		case UnsignedIntType:
59631		case IntType:
59632		case FloatType:
59633			return { byteLength: 4, components: 1 };
59634		case UnsignedInt5999Type:
59635		case UnsignedInt101111Type:
59636			return { byteLength: 4, components: 3 };
59637
59638	}
59639
59640	throw new Error( `
59640Unknown texture type ${type}.` );
59641
59642}
59643
59644/**
59645 * A class containing utility functions for textures.
59646 *
59647 * @hideconstructor
59648 */
59649class TextureUtils {
59650
59651	/**
59652	 * Scales the texture as large as possible within its surface without cropping
59653	 * or stretching the texture. The method preserves the original aspect ratio of
59654	 * the texture. Akin to CSS `object-fit: contain`
59655	 *
59656	 * @param {Texture} texture - The texture.
59657	 * @param {number} aspect - The texture's aspect ratio.
59658	 * @return {Texture} The updated texture.
59659	 */
59660	static contain( texture, aspect ) {
59661
59662		return contain( texture, aspect );
59663
59664	}
59665
59666	/**
59667	 * Scales the texture to the smallest possible size to fill the surface, leaving
59668	 * no empty space. The method preserves the original aspect ratio of the texture.
59669	 * Akin to CSS `object-fit: cover`.
59670	 *
59671	 * @param {Texture} texture - The texture.
59672	 * @param {number} aspect - The texture's aspect ratio.
59673	 * @return {Texture} The updated texture.
59674	 */
59675	static cover( texture, aspect ) {
59676
59677		return cover( texture, aspect );
59678
59679	}
59680
59681	/**
59682	 * Configures the texture to the default transformation. Akin to CSS `object-fit: fill`.
59683	 *
59684	 * @param {Texture} texture - The texture.
59685	 * @return {Texture} The updated texture.
59686	 */
59687	static fill( texture ) {
59688
59689		return fill( texture );
59690
59691	}
59692
59693	/**
59694	 * Determines how many bytes must be used to represent the texture.
59695	 *
59696	 * @param {number} width - The width of the texture.
59697	 * @param {number} height - The height of the texture.
59698	 * @param {number} format - The texture's format.
59699	 * @param {number} type - The texture's type.
59700	 * @return {number} The byte length.
59701	 */
59702	static getByteLength( width, height, format, type ) {
59703
59704		return getByteLength( width, height, format, type );
59705
59706	}
59707
59708}
59709
59710if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {
59711
59712	__THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'register', { detail: {
59713		revision: REVISION,
59714	} } ) );
59715
59716}
59717
59718if ( typeof window !== 'undefined' ) {
59719
59720	if ( window.__THREE__ ) {
59721
59722		warn( 'WARNING: Multiple instances of Three.js being imported.' );
59723
59724	} else {
59725
59726		window.__THREE__ = REVISION;
59727
59728	}
59729
59730}
59731
59732export { 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, 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, Orthogra
59732phicCamera, 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, 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, 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.