UNPKG

1.04 MBJavaScriptView Raw
1// Polyfills
2
3if ( Number.EPSILON === undefined ) {
4
5 Number.EPSILON = Math.pow( 2, - 52 );
6
7}
8
9if ( Number.isInteger === undefined ) {
10
11 // Missing in IE
12 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger
13
14 Number.isInteger = function ( value ) {
15
16 return typeof value === 'number' && isFinite( value ) && Math.floor( value ) === value;
17
18 };
19
20}
21
22//
23
24if ( Math.sign === undefined ) {
25
26 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign
27
28 Math.sign = function ( x ) {
29
30 return ( x < 0 ) ? - 1 : ( x > 0 ) ? 1 : + x;
31
32 };
33
34}
35
36if ( 'name' in Function.prototype === false ) {
37
38 // Missing in IE
39 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name
40
41 Object.defineProperty( Function.prototype, 'name', {
42
43 get: function () {
44
45 return this.toString().match( /^\s*function\s*([^\(\s]*)/ )[ 1 ];
46
47 }
48
49 } );
50
51}
52
53if ( Object.assign === undefined ) {
54
55 // Missing in IE
56 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
57
58 ( function () {
59
60 Object.assign = function ( target ) {
61
62 if ( target === undefined || target === null ) {
63
64 throw new TypeError( 'Cannot convert undefined or null to object' );
65
66 }
67
68 var output = Object( target );
69
70 for ( var index = 1; index < arguments.length; index ++ ) {
71
72 var source = arguments[ index ];
73
74 if ( source !== undefined && source !== null ) {
75
76 for ( var nextKey in source ) {
77
78 if ( Object.prototype.hasOwnProperty.call( source, nextKey ) ) {
79
80 output[ nextKey ] = source[ nextKey ];
81
82 }
83
84 }
85
86 }
87
88 }
89
90 return output;
91
92 };
93
94 } )();
95
96}
97
98/**
99 * https://github.com/mrdoob/eventdispatcher.js/
100 */
101
102function EventDispatcher() {}
103
104Object.assign( EventDispatcher.prototype, {
105
106 addEventListener: function ( type, listener ) {
107
108 if ( this._listeners === undefined ) this._listeners = {};
109
110 var listeners = this._listeners;
111
112 if ( listeners[ type ] === undefined ) {
113
114 listeners[ type ] = [];
115
116 }
117
118 if ( listeners[ type ].indexOf( listener ) === - 1 ) {
119
120 listeners[ type ].push( listener );
121
122 }
123
124 },
125
126 hasEventListener: function ( type, listener ) {
127
128 if ( this._listeners === undefined ) return false;
129
130 var listeners = this._listeners;
131
132 return listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1;
133
134 },
135
136 removeEventListener: function ( type, listener ) {
137
138 if ( this._listeners === undefined ) return;
139
140 var listeners = this._listeners;
141 var listenerArray = listeners[ type ];
142
143 if ( listenerArray !== undefined ) {
144
145 var index = listenerArray.indexOf( listener );
146
147 if ( index !== - 1 ) {
148
149 listenerArray.splice( index, 1 );
150
151 }
152
153 }
154
155 },
156
157 dispatchEvent: function ( event ) {
158
159 if ( this._listeners === undefined ) return;
160
161 var listeners = this._listeners;
162 var listenerArray = listeners[ event.type ];
163
164 if ( listenerArray !== undefined ) {
165
166 event.target = this;
167
168 var array = listenerArray.slice( 0 );
169
170 for ( var i = 0, l = array.length; i < l; i ++ ) {
171
172 array[ i ].call( this, event );
173
174 }
175
176 }
177
178 }
179
180} );
181
182var REVISION = '92';
183var MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2 };
184var CullFaceNone = 0;
185var CullFaceBack = 1;
186var CullFaceFront = 2;
187var CullFaceFrontBack = 3;
188var FrontFaceDirectionCW = 0;
189var FrontFaceDirectionCCW = 1;
190var BasicShadowMap = 0;
191var PCFShadowMap = 1;
192var PCFSoftShadowMap = 2;
193var FrontSide = 0;
194var BackSide = 1;
195var DoubleSide = 2;
196var FlatShading = 1;
197var SmoothShading = 2;
198var NoColors = 0;
199var FaceColors = 1;
200var VertexColors = 2;
201var NoBlending = 0;
202var NormalBlending = 1;
203var AdditiveBlending = 2;
204var SubtractiveBlending = 3;
205var MultiplyBlending = 4;
206var CustomBlending = 5;
207var AddEquation = 100;
208var SubtractEquation = 101;
209var ReverseSubtractEquation = 102;
210var MinEquation = 103;
211var MaxEquation = 104;
212var ZeroFactor = 200;
213var OneFactor = 201;
214var SrcColorFactor = 202;
215var OneMinusSrcColorFactor = 203;
216var SrcAlphaFactor = 204;
217var OneMinusSrcAlphaFactor = 205;
218var DstAlphaFactor = 206;
219var OneMinusDstAlphaFactor = 207;
220var DstColorFactor = 208;
221var OneMinusDstColorFactor = 209;
222var SrcAlphaSaturateFactor = 210;
223var NeverDepth = 0;
224var AlwaysDepth = 1;
225var LessDepth = 2;
226var LessEqualDepth = 3;
227var EqualDepth = 4;
228var GreaterEqualDepth = 5;
229var GreaterDepth = 6;
230var NotEqualDepth = 7;
231var MultiplyOperation = 0;
232var MixOperation = 1;
233var AddOperation = 2;
234var NoToneMapping = 0;
235var LinearToneMapping = 1;
236var ReinhardToneMapping = 2;
237var Uncharted2ToneMapping = 3;
238var CineonToneMapping = 4;
239var UVMapping = 300;
240var CubeReflectionMapping = 301;
241var CubeRefractionMapping = 302;
242var EquirectangularReflectionMapping = 303;
243var EquirectangularRefractionMapping = 304;
244var SphericalReflectionMapping = 305;
245var CubeUVReflectionMapping = 306;
246var CubeUVRefractionMapping = 307;
247var RepeatWrapping = 1000;
248var ClampToEdgeWrapping = 1001;
249var MirroredRepeatWrapping = 1002;
250var NearestFilter = 1003;
251var NearestMipMapNearestFilter = 1004;
252var NearestMipMapLinearFilter = 1005;
253var LinearFilter = 1006;
254var LinearMipMapNearestFilter = 1007;
255var LinearMipMapLinearFilter = 1008;
256var UnsignedByteType = 1009;
257var ByteType = 1010;
258var ShortType = 1011;
259var UnsignedShortType = 1012;
260var IntType = 1013;
261var UnsignedIntType = 1014;
262var FloatType = 1015;
263var HalfFloatType = 1016;
264var UnsignedShort4444Type = 1017;
265var UnsignedShort5551Type = 1018;
266var UnsignedShort565Type = 1019;
267var UnsignedInt248Type = 1020;
268var AlphaFormat = 1021;
269var RGBFormat = 1022;
270var RGBAFormat = 1023;
271var LuminanceFormat = 1024;
272var LuminanceAlphaFormat = 1025;
273var RGBEFormat = RGBAFormat;
274var DepthFormat = 1026;
275var DepthStencilFormat = 1027;
276var RGB_S3TC_DXT1_Format = 33776;
277var RGBA_S3TC_DXT1_Format = 33777;
278var RGBA_S3TC_DXT3_Format = 33778;
279var RGBA_S3TC_DXT5_Format = 33779;
280var RGB_PVRTC_4BPPV1_Format = 35840;
281var RGB_PVRTC_2BPPV1_Format = 35841;
282var RGBA_PVRTC_4BPPV1_Format = 35842;
283var RGBA_PVRTC_2BPPV1_Format = 35843;
284var RGB_ETC1_Format = 36196;
285var RGBA_ASTC_4x4_Format = 37808;
286var RGBA_ASTC_5x4_Format = 37809;
287var RGBA_ASTC_5x5_Format = 37810;
288var RGBA_ASTC_6x5_Format = 37811;
289var RGBA_ASTC_6x6_Format = 37812;
290var RGBA_ASTC_8x5_Format = 37813;
291var RGBA_ASTC_8x6_Format = 37814;
292var RGBA_ASTC_8x8_Format = 37815;
293var RGBA_ASTC_10x5_Format = 37816;
294var RGBA_ASTC_10x6_Format = 37817;
295var RGBA_ASTC_10x8_Format = 37818;
296var RGBA_ASTC_10x10_Format = 37819;
297var RGBA_ASTC_12x10_Format = 37820;
298var RGBA_ASTC_12x12_Format = 37821;
299var LoopOnce = 2200;
300var LoopRepeat = 2201;
301var LoopPingPong = 2202;
302var InterpolateDiscrete = 2300;
303var InterpolateLinear = 2301;
304var InterpolateSmooth = 2302;
305var ZeroCurvatureEnding = 2400;
306var ZeroSlopeEnding = 2401;
307var WrapAroundEnding = 2402;
308var TrianglesDrawMode = 0;
309var TriangleStripDrawMode = 1;
310var TriangleFanDrawMode = 2;
311var LinearEncoding = 3000;
312var sRGBEncoding = 3001;
313var GammaEncoding = 3007;
314var RGBEEncoding = 3002;
315var LogLuvEncoding = 3003;
316var RGBM7Encoding = 3004;
317var RGBM16Encoding = 3005;
318var RGBDEncoding = 3006;
319var BasicDepthPacking = 3200;
320var RGBADepthPacking = 3201;
321
322/**
323 * @author alteredq / http://alteredqualia.com/
324 * @author mrdoob / http://mrdoob.com/
325 */
326
327var _Math = {
328
329 DEG2RAD: Math.PI / 180,
330 RAD2DEG: 180 / Math.PI,
331
332 generateUUID: ( function () {
333
334 // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136
335
336 var lut = [];
337
338 for ( var i = 0; i < 256; i ++ ) {
339
340 lut[ i ] = ( i < 16 ? '0' : '' ) + ( i ).toString( 16 );
341
342 }
343
344 return function generateUUID() {
345
346 var d0 = Math.random() * 0xffffffff | 0;
347 var d1 = Math.random() * 0xffffffff | 0;
348 var d2 = Math.random() * 0xffffffff | 0;
349 var d3 = Math.random() * 0xffffffff | 0;
350 var uuid = lut[ d0 & 0xff ] + lut[ d0 >> 8 & 0xff ] + lut[ d0 >> 16 & 0xff ] + lut[ d0 >> 24 & 0xff ] + '-' +
351 lut[ d1 & 0xff ] + lut[ d1 >> 8 & 0xff ] + '-' + lut[ d1 >> 16 & 0x0f | 0x40 ] + lut[ d1 >> 24 & 0xff ] + '-' +
352 lut[ d2 & 0x3f | 0x80 ] + lut[ d2 >> 8 & 0xff ] + '-' + lut[ d2 >> 16 & 0xff ] + lut[ d2 >> 24 & 0xff ] +
353 lut[ d3 & 0xff ] + lut[ d3 >> 8 & 0xff ] + lut[ d3 >> 16 & 0xff ] + lut[ d3 >> 24 & 0xff ];
354
355 // .toUpperCase() here flattens concatenated strings to save heap memory space.
356 return uuid.toUpperCase();
357
358 };
359
360 } )(),
361
362 clamp: function ( value, min, max ) {
363
364 return Math.max( min, Math.min( max, value ) );
365
366 },
367
368 // compute euclidian modulo of m % n
369 // https://en.wikipedia.org/wiki/Modulo_operation
370
371 euclideanModulo: function ( n, m ) {
372
373 return ( ( n % m ) + m ) % m;
374
375 },
376
377 // Linear mapping from range <a1, a2> to range <b1, b2>
378
379 mapLinear: function ( x, a1, a2, b1, b2 ) {
380
381 return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 );
382
383 },
384
385 // https://en.wikipedia.org/wiki/Linear_interpolation
386
387 lerp: function ( x, y, t ) {
388
389 return ( 1 - t ) * x + t * y;
390
391 },
392
393 // http://en.wikipedia.org/wiki/Smoothstep
394
395 smoothstep: function ( x, min, max ) {
396
397 if ( x <= min ) return 0;
398 if ( x >= max ) return 1;
399
400 x = ( x - min ) / ( max - min );
401
402 return x * x * ( 3 - 2 * x );
403
404 },
405
406 smootherstep: function ( x, min, max ) {
407
408 if ( x <= min ) return 0;
409 if ( x >= max ) return 1;
410
411 x = ( x - min ) / ( max - min );
412
413 return x * x * x * ( x * ( x * 6 - 15 ) + 10 );
414
415 },
416
417 // Random integer from <low, high> interval
418
419 randInt: function ( low, high ) {
420
421 return low + Math.floor( Math.random() * ( high - low + 1 ) );
422
423 },
424
425 // Random float from <low, high> interval
426
427 randFloat: function ( low, high ) {
428
429 return low + Math.random() * ( high - low );
430
431 },
432
433 // Random float from <-range/2, range/2> interval
434
435 randFloatSpread: function ( range ) {
436
437 return range * ( 0.5 - Math.random() );
438
439 },
440
441 degToRad: function ( degrees ) {
442
443 return degrees * _Math.DEG2RAD;
444
445 },
446
447 radToDeg: function ( radians ) {
448
449 return radians * _Math.RAD2DEG;
450
451 },
452
453 isPowerOfTwo: function ( value ) {
454
455 return ( value & ( value - 1 ) ) === 0 && value !== 0;
456
457 },
458
459 ceilPowerOfTwo: function ( value ) {
460
461 return Math.pow( 2, Math.ceil( Math.log( value ) / Math.LN2 ) );
462
463 },
464
465 floorPowerOfTwo: function ( value ) {
466
467 return Math.pow( 2, Math.floor( Math.log( value ) / Math.LN2 ) );
468
469 }
470
471};
472
473/**
474 * @author mrdoob / http://mrdoob.com/
475 * @author philogb / http://blog.thejit.org/
476 * @author egraether / http://egraether.com/
477 * @author zz85 / http://www.lab4games.net/zz85/blog
478 */
479
480function Vector2( x, y ) {
481
482 this.x = x || 0;
483 this.y = y || 0;
484
485}
486
487Object.defineProperties( Vector2.prototype, {
488
489 "width": {
490
491 get: function () {
492
493 return this.x;
494
495 },
496
497 set: function ( value ) {
498
499 this.x = value;
500
501 }
502
503 },
504
505 "height": {
506
507 get: function () {
508
509 return this.y;
510
511 },
512
513 set: function ( value ) {
514
515 this.y = value;
516
517 }
518
519 }
520
521} );
522
523Object.assign( Vector2.prototype, {
524
525 isVector2: true,
526
527 set: function ( x, y ) {
528
529 this.x = x;
530 this.y = y;
531
532 return this;
533
534 },
535
536 setScalar: function ( scalar ) {
537
538 this.x = scalar;
539 this.y = scalar;
540
541 return this;
542
543 },
544
545 setX: function ( x ) {
546
547 this.x = x;
548
549 return this;
550
551 },
552
553 setY: function ( y ) {
554
555 this.y = y;
556
557 return this;
558
559 },
560
561 setComponent: function ( index, value ) {
562
563 switch ( index ) {
564
565 case 0: this.x = value; break;
566 case 1: this.y = value; break;
567 default: throw new Error( 'index is out of range: ' + index );
568
569 }
570
571 return this;
572
573 },
574
575 getComponent: function ( index ) {
576
577 switch ( index ) {
578
579 case 0: return this.x;
580 case 1: return this.y;
581 default: throw new Error( 'index is out of range: ' + index );
582
583 }
584
585 },
586
587 clone: function () {
588
589 return new this.constructor( this.x, this.y );
590
591 },
592
593 copy: function ( v ) {
594
595 this.x = v.x;
596 this.y = v.y;
597
598 return this;
599
600 },
601
602 add: function ( v, w ) {
603
604 if ( w !== undefined ) {
605
606 console.warn( 'THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
607 return this.addVectors( v, w );
608
609 }
610
611 this.x += v.x;
612 this.y += v.y;
613
614 return this;
615
616 },
617
618 addScalar: function ( s ) {
619
620 this.x += s;
621 this.y += s;
622
623 return this;
624
625 },
626
627 addVectors: function ( a, b ) {
628
629 this.x = a.x + b.x;
630 this.y = a.y + b.y;
631
632 return this;
633
634 },
635
636 addScaledVector: function ( v, s ) {
637
638 this.x += v.x * s;
639 this.y += v.y * s;
640
641 return this;
642
643 },
644
645 sub: function ( v, w ) {
646
647 if ( w !== undefined ) {
648
649 console.warn( 'THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
650 return this.subVectors( v, w );
651
652 }
653
654 this.x -= v.x;
655 this.y -= v.y;
656
657 return this;
658
659 },
660
661 subScalar: function ( s ) {
662
663 this.x -= s;
664 this.y -= s;
665
666 return this;
667
668 },
669
670 subVectors: function ( a, b ) {
671
672 this.x = a.x - b.x;
673 this.y = a.y - b.y;
674
675 return this;
676
677 },
678
679 multiply: function ( v ) {
680
681 this.x *= v.x;
682 this.y *= v.y;
683
684 return this;
685
686 },
687
688 multiplyScalar: function ( scalar ) {
689
690 this.x *= scalar;
691 this.y *= scalar;
692
693 return this;
694
695 },
696
697 divide: function ( v ) {
698
699 this.x /= v.x;
700 this.y /= v.y;
701
702 return this;
703
704 },
705
706 divideScalar: function ( scalar ) {
707
708 return this.multiplyScalar( 1 / scalar );
709
710 },
711
712 applyMatrix3: function ( m ) {
713
714 var x = this.x, y = this.y;
715 var e = m.elements;
716
717 this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ];
718 this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ];
719
720 return this;
721
722 },
723
724 min: function ( v ) {
725
726 this.x = Math.min( this.x, v.x );
727 this.y = Math.min( this.y, v.y );
728
729 return this;
730
731 },
732
733 max: function ( v ) {
734
735 this.x = Math.max( this.x, v.x );
736 this.y = Math.max( this.y, v.y );
737
738 return this;
739
740 },
741
742 clamp: function ( min, max ) {
743
744 // assumes min < max, componentwise
745
746 this.x = Math.max( min.x, Math.min( max.x, this.x ) );
747 this.y = Math.max( min.y, Math.min( max.y, this.y ) );
748
749 return this;
750
751 },
752
753 clampScalar: function () {
754
755 var min = new Vector2();
756 var max = new Vector2();
757
758 return function clampScalar( minVal, maxVal ) {
759
760 min.set( minVal, minVal );
761 max.set( maxVal, maxVal );
762
763 return this.clamp( min, max );
764
765 };
766
767 }(),
768
769 clampLength: function ( min, max ) {
770
771 var length = this.length();
772
773 return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
774
775 },
776
777 floor: function () {
778
779 this.x = Math.floor( this.x );
780 this.y = Math.floor( this.y );
781
782 return this;
783
784 },
785
786 ceil: function () {
787
788 this.x = Math.ceil( this.x );
789 this.y = Math.ceil( this.y );
790
791 return this;
792
793 },
794
795 round: function () {
796
797 this.x = Math.round( this.x );
798 this.y = Math.round( this.y );
799
800 return this;
801
802 },
803
804 roundToZero: function () {
805
806 this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
807 this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
808
809 return this;
810
811 },
812
813 negate: function () {
814
815 this.x = - this.x;
816 this.y = - this.y;
817
818 return this;
819
820 },
821
822 dot: function ( v ) {
823
824 return this.x * v.x + this.y * v.y;
825
826 },
827
828 lengthSq: function () {
829
830 return this.x * this.x + this.y * this.y;
831
832 },
833
834 length: function () {
835
836 return Math.sqrt( this.x * this.x + this.y * this.y );
837
838 },
839
840 manhattanLength: function () {
841
842 return Math.abs( this.x ) + Math.abs( this.y );
843
844 },
845
846 normalize: function () {
847
848 return this.divideScalar( this.length() || 1 );
849
850 },
851
852 angle: function () {
853
854 // computes the angle in radians with respect to the positive x-axis
855
856 var angle = Math.atan2( this.y, this.x );
857
858 if ( angle < 0 ) angle += 2 * Math.PI;
859
860 return angle;
861
862 },
863
864 distanceTo: function ( v ) {
865
866 return Math.sqrt( this.distanceToSquared( v ) );
867
868 },
869
870 distanceToSquared: function ( v ) {
871
872 var dx = this.x - v.x, dy = this.y - v.y;
873 return dx * dx + dy * dy;
874
875 },
876
877 manhattanDistanceTo: function ( v ) {
878
879 return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y );
880
881 },
882
883 setLength: function ( length ) {
884
885 return this.normalize().multiplyScalar( length );
886
887 },
888
889 lerp: function ( v, alpha ) {
890
891 this.x += ( v.x - this.x ) * alpha;
892 this.y += ( v.y - this.y ) * alpha;
893
894 return this;
895
896 },
897
898 lerpVectors: function ( v1, v2, alpha ) {
899
900 return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );
901
902 },
903
904 equals: function ( v ) {
905
906 return ( ( v.x === this.x ) && ( v.y === this.y ) );
907
908 },
909
910 fromArray: function ( array, offset ) {
911
912 if ( offset === undefined ) offset = 0;
913
914 this.x = array[ offset ];
915 this.y = array[ offset + 1 ];
916
917 return this;
918
919 },
920
921 toArray: function ( array, offset ) {
922
923 if ( array === undefined ) array = [];
924 if ( offset === undefined ) offset = 0;
925
926 array[ offset ] = this.x;
927 array[ offset + 1 ] = this.y;
928
929 return array;
930
931 },
932
933 fromBufferAttribute: function ( attribute, index, offset ) {
934
935 if ( offset !== undefined ) {
936
937 console.warn( 'THREE.Vector2: offset has been removed from .fromBufferAttribute().' );
938
939 }
940
941 this.x = attribute.getX( index );
942 this.y = attribute.getY( index );
943
944 return this;
945
946 },
947
948 rotateAround: function ( center, angle ) {
949
950 var c = Math.cos( angle ), s = Math.sin( angle );
951
952 var x = this.x - center.x;
953 var y = this.y - center.y;
954
955 this.x = x * c - y * s + center.x;
956 this.y = x * s + y * c + center.y;
957
958 return this;
959
960 }
961
962} );
963
964/**
965 * @author mrdoob / http://mrdoob.com/
966 * @author supereggbert / http://www.paulbrunt.co.uk/
967 * @author philogb / http://blog.thejit.org/
968 * @author jordi_ros / http://plattsoft.com
969 * @author D1plo1d / http://github.com/D1plo1d
970 * @author alteredq / http://alteredqualia.com/
971 * @author mikael emtinger / http://gomo.se/
972 * @author timknip / http://www.floorplanner.com/
973 * @author bhouston / http://clara.io
974 * @author WestLangley / http://github.com/WestLangley
975 */
976
977function Matrix4() {
978
979 this.elements = [
980
981 1, 0, 0, 0,
982 0, 1, 0, 0,
983 0, 0, 1, 0,
984 0, 0, 0, 1
985
986 ];
987
988 if ( arguments.length > 0 ) {
989
990 console.error( 'THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.' );
991
992 }
993
994}
995
996Object.assign( Matrix4.prototype, {
997
998 isMatrix4: true,
999
1000 set: function ( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
1001
1002 var te = this.elements;
1003
1004 te[ 0 ] = n11; te[ 4 ] = n12; te[ 8 ] = n13; te[ 12 ] = n14;
1005 te[ 1 ] = n21; te[ 5 ] = n22; te[ 9 ] = n23; te[ 13 ] = n24;
1006 te[ 2 ] = n31; te[ 6 ] = n32; te[ 10 ] = n33; te[ 14 ] = n34;
1007 te[ 3 ] = n41; te[ 7 ] = n42; te[ 11 ] = n43; te[ 15 ] = n44;
1008
1009 return this;
1010
1011 },
1012
1013 identity: function () {
1014
1015 this.set(
1016
1017 1, 0, 0, 0,
1018 0, 1, 0, 0,
1019 0, 0, 1, 0,
1020 0, 0, 0, 1
1021
1022 );
1023
1024 return this;
1025
1026 },
1027
1028 clone: function () {
1029
1030 return new Matrix4().fromArray( this.elements );
1031
1032 },
1033
1034 copy: function ( m ) {
1035
1036 var te = this.elements;
1037 var me = m.elements;
1038
1039 te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ]; te[ 3 ] = me[ 3 ];
1040 te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ]; te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ];
1041 te[ 8 ] = me[ 8 ]; te[ 9 ] = me[ 9 ]; te[ 10 ] = me[ 10 ]; te[ 11 ] = me[ 11 ];
1042 te[ 12 ] = me[ 12 ]; te[ 13 ] = me[ 13 ]; te[ 14 ] = me[ 14 ]; te[ 15 ] = me[ 15 ];
1043
1044 return this;
1045
1046 },
1047
1048 copyPosition: function ( m ) {
1049
1050 var te = this.elements, me = m.elements;
1051
1052 te[ 12 ] = me[ 12 ];
1053 te[ 13 ] = me[ 13 ];
1054 te[ 14 ] = me[ 14 ];
1055
1056 return this;
1057
1058 },
1059
1060 extractBasis: function ( xAxis, yAxis, zAxis ) {
1061
1062 xAxis.setFromMatrixColumn( this, 0 );
1063 yAxis.setFromMatrixColumn( this, 1 );
1064 zAxis.setFromMatrixColumn( this, 2 );
1065
1066 return this;
1067
1068 },
1069
1070 makeBasis: function ( xAxis, yAxis, zAxis ) {
1071
1072 this.set(
1073 xAxis.x, yAxis.x, zAxis.x, 0,
1074 xAxis.y, yAxis.y, zAxis.y, 0,
1075 xAxis.z, yAxis.z, zAxis.z, 0,
1076 0, 0, 0, 1
1077 );
1078
1079 return this;
1080
1081 },
1082
1083 extractRotation: function () {
1084
1085 var v1 = new Vector3();
1086
1087 return function extractRotation( m ) {
1088
1089 var te = this.elements;
1090 var me = m.elements;
1091
1092 var scaleX = 1 / v1.setFromMatrixColumn( m, 0 ).length();
1093 var scaleY = 1 / v1.setFromMatrixColumn( m, 1 ).length();
1094 var scaleZ = 1 / v1.setFromMatrixColumn( m, 2 ).length();
1095
1096 te[ 0 ] = me[ 0 ] * scaleX;
1097 te[ 1 ] = me[ 1 ] * scaleX;
1098 te[ 2 ] = me[ 2 ] * scaleX;
1099
1100 te[ 4 ] = me[ 4 ] * scaleY;
1101 te[ 5 ] = me[ 5 ] * scaleY;
1102 te[ 6 ] = me[ 6 ] * scaleY;
1103
1104 te[ 8 ] = me[ 8 ] * scaleZ;
1105 te[ 9 ] = me[ 9 ] * scaleZ;
1106 te[ 10 ] = me[ 10 ] * scaleZ;
1107
1108 return this;
1109
1110 };
1111
1112 }(),
1113
1114 makeRotationFromEuler: function ( euler ) {
1115
1116 if ( ! ( euler && euler.isEuler ) ) {
1117
1118 console.error( 'THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.' );
1119
1120 }
1121
1122 var te = this.elements;
1123
1124 var x = euler.x, y = euler.y, z = euler.z;
1125 var a = Math.cos( x ), b = Math.sin( x );
1126 var c = Math.cos( y ), d = Math.sin( y );
1127 var e = Math.cos( z ), f = Math.sin( z );
1128
1129 if ( euler.order === 'XYZ' ) {
1130
1131 var ae = a * e, af = a * f, be = b * e, bf = b * f;
1132
1133 te[ 0 ] = c * e;
1134 te[ 4 ] = - c * f;
1135 te[ 8 ] = d;
1136
1137 te[ 1 ] = af + be * d;
1138 te[ 5 ] = ae - bf * d;
1139 te[ 9 ] = - b * c;
1140
1141 te[ 2 ] = bf - ae * d;
1142 te[ 6 ] = be + af * d;
1143 te[ 10 ] = a * c;
1144
1145 } else if ( euler.order === 'YXZ' ) {
1146
1147 var ce = c * e, cf = c * f, de = d * e, df = d * f;
1148
1149 te[ 0 ] = ce + df * b;
1150 te[ 4 ] = de * b - cf;
1151 te[ 8 ] = a * d;
1152
1153 te[ 1 ] = a * f;
1154 te[ 5 ] = a * e;
1155 te[ 9 ] = - b;
1156
1157 te[ 2 ] = cf * b - de;
1158 te[ 6 ] = df + ce * b;
1159 te[ 10 ] = a * c;
1160
1161 } else if ( euler.order === 'ZXY' ) {
1162
1163 var ce = c * e, cf = c * f, de = d * e, df = d * f;
1164
1165 te[ 0 ] = ce - df * b;
1166 te[ 4 ] = - a * f;
1167 te[ 8 ] = de + cf * b;
1168
1169 te[ 1 ] = cf + de * b;
1170 te[ 5 ] = a * e;
1171 te[ 9 ] = df - ce * b;
1172
1173 te[ 2 ] = - a * d;
1174 te[ 6 ] = b;
1175 te[ 10 ] = a * c;
1176
1177 } else if ( euler.order === 'ZYX' ) {
1178
1179 var ae = a * e, af = a * f, be = b * e, bf = b * f;
1180
1181 te[ 0 ] = c * e;
1182 te[ 4 ] = be * d - af;
1183 te[ 8 ] = ae * d + bf;
1184
1185 te[ 1 ] = c * f;
1186 te[ 5 ] = bf * d + ae;
1187 te[ 9 ] = af * d - be;
1188
1189 te[ 2 ] = - d;
1190 te[ 6 ] = b * c;
1191 te[ 10 ] = a * c;
1192
1193 } else if ( euler.order === 'YZX' ) {
1194
1195 var ac = a * c, ad = a * d, bc = b * c, bd = b * d;
1196
1197 te[ 0 ] = c * e;
1198 te[ 4 ] = bd - ac * f;
1199 te[ 8 ] = bc * f + ad;
1200
1201 te[ 1 ] = f;
1202 te[ 5 ] = a * e;
1203 te[ 9 ] = - b * e;
1204
1205 te[ 2 ] = - d * e;
1206 te[ 6 ] = ad * f + bc;
1207 te[ 10 ] = ac - bd * f;
1208
1209 } else if ( euler.order === 'XZY' ) {
1210
1211 var ac = a * c, ad = a * d, bc = b * c, bd = b * d;
1212
1213 te[ 0 ] = c * e;
1214 te[ 4 ] = - f;
1215 te[ 8 ] = d * e;
1216
1217 te[ 1 ] = ac * f + bd;
1218 te[ 5 ] = a * e;
1219 te[ 9 ] = ad * f - bc;
1220
1221 te[ 2 ] = bc * f - ad;
1222 te[ 6 ] = b * e;
1223 te[ 10 ] = bd * f + ac;
1224
1225 }
1226
1227 // last column
1228 te[ 3 ] = 0;
1229 te[ 7 ] = 0;
1230 te[ 11 ] = 0;
1231
1232 // bottom row
1233 te[ 12 ] = 0;
1234 te[ 13 ] = 0;
1235 te[ 14 ] = 0;
1236 te[ 15 ] = 1;
1237
1238 return this;
1239
1240 },
1241
1242 makeRotationFromQuaternion: function ( q ) {
1243
1244 var te = this.elements;
1245
1246 var x = q._x, y = q._y, z = q._z, w = q._w;
1247 var x2 = x + x, y2 = y + y, z2 = z + z;
1248 var xx = x * x2, xy = x * y2, xz = x * z2;
1249 var yy = y * y2, yz = y * z2, zz = z * z2;
1250 var wx = w * x2, wy = w * y2, wz = w * z2;
1251
1252 te[ 0 ] = 1 - ( yy + zz );
1253 te[ 4 ] = xy - wz;
1254 te[ 8 ] = xz + wy;
1255
1256 te[ 1 ] = xy + wz;
1257 te[ 5 ] = 1 - ( xx + zz );
1258 te[ 9 ] = yz - wx;
1259
1260 te[ 2 ] = xz - wy;
1261 te[ 6 ] = yz + wx;
1262 te[ 10 ] = 1 - ( xx + yy );
1263
1264 // last column
1265 te[ 3 ] = 0;
1266 te[ 7 ] = 0;
1267 te[ 11 ] = 0;
1268
1269 // bottom row
1270 te[ 12 ] = 0;
1271 te[ 13 ] = 0;
1272 te[ 14 ] = 0;
1273 te[ 15 ] = 1;
1274
1275 return this;
1276
1277 },
1278
1279 lookAt: function () {
1280
1281 var x = new Vector3();
1282 var y = new Vector3();
1283 var z = new Vector3();
1284
1285 return function lookAt( eye, target, up ) {
1286
1287 var te = this.elements;
1288
1289 z.subVectors( eye, target );
1290
1291 if ( z.lengthSq() === 0 ) {
1292
1293 // eye and target are in the same position
1294
1295 z.z = 1;
1296
1297 }
1298
1299 z.normalize();
1300 x.crossVectors( up, z );
1301
1302 if ( x.lengthSq() === 0 ) {
1303
1304 // up and z are parallel
1305
1306 if ( Math.abs( up.z ) === 1 ) {
1307
1308 z.x += 0.0001;
1309
1310 } else {
1311
1312 z.z += 0.0001;
1313
1314 }
1315
1316 z.normalize();
1317 x.crossVectors( up, z );
1318
1319 }
1320
1321 x.normalize();
1322 y.crossVectors( z, x );
1323
1324 te[ 0 ] = x.x; te[ 4 ] = y.x; te[ 8 ] = z.x;
1325 te[ 1 ] = x.y; te[ 5 ] = y.y; te[ 9 ] = z.y;
1326 te[ 2 ] = x.z; te[ 6 ] = y.z; te[ 10 ] = z.z;
1327
1328 return this;
1329
1330 };
1331
1332 }(),
1333
1334 multiply: function ( m, n ) {
1335
1336 if ( n !== undefined ) {
1337
1338 console.warn( 'THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead.' );
1339 return this.multiplyMatrices( m, n );
1340
1341 }
1342
1343 return this.multiplyMatrices( this, m );
1344
1345 },
1346
1347 premultiply: function ( m ) {
1348
1349 return this.multiplyMatrices( m, this );
1350
1351 },
1352
1353 multiplyMatrices: function ( a, b ) {
1354
1355 var ae = a.elements;
1356 var be = b.elements;
1357 var te = this.elements;
1358
1359 var a11 = ae[ 0 ], a12 = ae[ 4 ], a13 = ae[ 8 ], a14 = ae[ 12 ];
1360 var a21 = ae[ 1 ], a22 = ae[ 5 ], a23 = ae[ 9 ], a24 = ae[ 13 ];
1361 var a31 = ae[ 2 ], a32 = ae[ 6 ], a33 = ae[ 10 ], a34 = ae[ 14 ];
1362 var a41 = ae[ 3 ], a42 = ae[ 7 ], a43 = ae[ 11 ], a44 = ae[ 15 ];
1363
1364 var b11 = be[ 0 ], b12 = be[ 4 ], b13 = be[ 8 ], b14 = be[ 12 ];
1365 var b21 = be[ 1 ], b22 = be[ 5 ], b23 = be[ 9 ], b24 = be[ 13 ];
1366 var b31 = be[ 2 ], b32 = be[ 6 ], b33 = be[ 10 ], b34 = be[ 14 ];
1367 var b41 = be[ 3 ], b42 = be[ 7 ], b43 = be[ 11 ], b44 = be[ 15 ];
1368
1369 te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
1370 te[ 4 ] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
1371 te[ 8 ] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
1372 te[ 12 ] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
1373
1374 te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
1375 te[ 5 ] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
1376 te[ 9 ] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
1377 te[ 13 ] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
1378
1379 te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
1380 te[ 6 ] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
1381 te[ 10 ] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
1382 te[ 14 ] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
1383
1384 te[ 3 ] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
1385 te[ 7 ] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
1386 te[ 11 ] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
1387 te[ 15 ] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
1388
1389 return this;
1390
1391 },
1392
1393 multiplyScalar: function ( s ) {
1394
1395 var te = this.elements;
1396
1397 te[ 0 ] *= s; te[ 4 ] *= s; te[ 8 ] *= s; te[ 12 ] *= s;
1398 te[ 1 ] *= s; te[ 5 ] *= s; te[ 9 ] *= s; te[ 13 ] *= s;
1399 te[ 2 ] *= s; te[ 6 ] *= s; te[ 10 ] *= s; te[ 14 ] *= s;
1400 te[ 3 ] *= s; te[ 7 ] *= s; te[ 11 ] *= s; te[ 15 ] *= s;
1401
1402 return this;
1403
1404 },
1405
1406 applyToBufferAttribute: function () {
1407
1408 var v1 = new Vector3();
1409
1410 return function applyToBufferAttribute( attribute ) {
1411
1412 for ( var i = 0, l = attribute.count; i < l; i ++ ) {
1413
1414 v1.x = attribute.getX( i );
1415 v1.y = attribute.getY( i );
1416 v1.z = attribute.getZ( i );
1417
1418 v1.applyMatrix4( this );
1419
1420 attribute.setXYZ( i, v1.x, v1.y, v1.z );
1421
1422 }
1423
1424 return attribute;
1425
1426 };
1427
1428 }(),
1429
1430 determinant: function () {
1431
1432 var te = this.elements;
1433
1434 var n11 = te[ 0 ], n12 = te[ 4 ], n13 = te[ 8 ], n14 = te[ 12 ];
1435 var n21 = te[ 1 ], n22 = te[ 5 ], n23 = te[ 9 ], n24 = te[ 13 ];
1436 var n31 = te[ 2 ], n32 = te[ 6 ], n33 = te[ 10 ], n34 = te[ 14 ];
1437 var n41 = te[ 3 ], n42 = te[ 7 ], n43 = te[ 11 ], n44 = te[ 15 ];
1438
1439 //TODO: make this more efficient
1440 //( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm )
1441
1442 return (
1443 n41 * (
1444 + n14 * n23 * n32
1445 - n13 * n24 * n32
1446 - n14 * n22 * n33
1447 + n12 * n24 * n33
1448 + n13 * n22 * n34
1449 - n12 * n23 * n34
1450 ) +
1451 n42 * (
1452 + n11 * n23 * n34
1453 - n11 * n24 * n33
1454 + n14 * n21 * n33
1455 - n13 * n21 * n34
1456 + n13 * n24 * n31
1457 - n14 * n23 * n31
1458 ) +
1459 n43 * (
1460 + n11 * n24 * n32
1461 - n11 * n22 * n34
1462 - n14 * n21 * n32
1463 + n12 * n21 * n34
1464 + n14 * n22 * n31
1465 - n12 * n24 * n31
1466 ) +
1467 n44 * (
1468 - n13 * n22 * n31
1469 - n11 * n23 * n32
1470 + n11 * n22 * n33
1471 + n13 * n21 * n32
1472 - n12 * n21 * n33
1473 + n12 * n23 * n31
1474 )
1475
1476 );
1477
1478 },
1479
1480 transpose: function () {
1481
1482 var te = this.elements;
1483 var tmp;
1484
1485 tmp = te[ 1 ]; te[ 1 ] = te[ 4 ]; te[ 4 ] = tmp;
1486 tmp = te[ 2 ]; te[ 2 ] = te[ 8 ]; te[ 8 ] = tmp;
1487 tmp = te[ 6 ]; te[ 6 ] = te[ 9 ]; te[ 9 ] = tmp;
1488
1489 tmp = te[ 3 ]; te[ 3 ] = te[ 12 ]; te[ 12 ] = tmp;
1490 tmp = te[ 7 ]; te[ 7 ] = te[ 13 ]; te[ 13 ] = tmp;
1491 tmp = te[ 11 ]; te[ 11 ] = te[ 14 ]; te[ 14 ] = tmp;
1492
1493 return this;
1494
1495 },
1496
1497 setPosition: function ( v ) {
1498
1499 var te = this.elements;
1500
1501 te[ 12 ] = v.x;
1502 te[ 13 ] = v.y;
1503 te[ 14 ] = v.z;
1504
1505 return this;
1506
1507 },
1508
1509 getInverse: function ( m, throwOnDegenerate ) {
1510
1511 // based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm
1512 var te = this.elements,
1513 me = m.elements,
1514
1515 n11 = me[ 0 ], n21 = me[ 1 ], n31 = me[ 2 ], n41 = me[ 3 ],
1516 n12 = me[ 4 ], n22 = me[ 5 ], n32 = me[ 6 ], n42 = me[ 7 ],
1517 n13 = me[ 8 ], n23 = me[ 9 ], n33 = me[ 10 ], n43 = me[ 11 ],
1518 n14 = me[ 12 ], n24 = me[ 13 ], n34 = me[ 14 ], n44 = me[ 15 ],
1519
1520 t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44,
1521 t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44,
1522 t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44,
1523 t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34;
1524
1525 var det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14;
1526
1527 if ( det === 0 ) {
1528
1529 var msg = "THREE.Matrix4: .getInverse() can't invert matrix, determinant is 0";
1530
1531 if ( throwOnDegenerate === true ) {
1532
1533 throw new Error( msg );
1534
1535 } else {
1536
1537 console.warn( msg );
1538
1539 }
1540
1541 return this.identity();
1542
1543 }
1544
1545 var detInv = 1 / det;
1546
1547 te[ 0 ] = t11 * detInv;
1548 te[ 1 ] = ( n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44 ) * detInv;
1549 te[ 2 ] = ( n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44 ) * detInv;
1550 te[ 3 ] = ( n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43 ) * detInv;
1551
1552 te[ 4 ] = t12 * detInv;
1553 te[ 5 ] = ( n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44 ) * detInv;
1554 te[ 6 ] = ( n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44 ) * detInv;
1555 te[ 7 ] = ( n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43 ) * detInv;
1556
1557 te[ 8 ] = t13 * detInv;
1558 te[ 9 ] = ( n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44 ) * detInv;
1559 te[ 10 ] = ( n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44 ) * detInv;
1560 te[ 11 ] = ( n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43 ) * detInv;
1561
1562 te[ 12 ] = t14 * detInv;
1563 te[ 13 ] = ( n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34 ) * detInv;
1564 te[ 14 ] = ( n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34 ) * detInv;
1565 te[ 15 ] = ( n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33 ) * detInv;
1566
1567 return this;
1568
1569 },
1570
1571 scale: function ( v ) {
1572
1573 var te = this.elements;
1574 var x = v.x, y = v.y, z = v.z;
1575
1576 te[ 0 ] *= x; te[ 4 ] *= y; te[ 8 ] *= z;
1577 te[ 1 ] *= x; te[ 5 ] *= y; te[ 9 ] *= z;
1578 te[ 2 ] *= x; te[ 6 ] *= y; te[ 10 ] *= z;
1579 te[ 3 ] *= x; te[ 7 ] *= y; te[ 11 ] *= z;
1580
1581 return this;
1582
1583 },
1584
1585 getMaxScaleOnAxis: function () {
1586
1587 var te = this.elements;
1588
1589 var scaleXSq = te[ 0 ] * te[ 0 ] + te[ 1 ] * te[ 1 ] + te[ 2 ] * te[ 2 ];
1590 var scaleYSq = te[ 4 ] * te[ 4 ] + te[ 5 ] * te[ 5 ] + te[ 6 ] * te[ 6 ];
1591 var scaleZSq = te[ 8 ] * te[ 8 ] + te[ 9 ] * te[ 9 ] + te[ 10 ] * te[ 10 ];
1592
1593 return Math.sqrt( Math.max( scaleXSq, scaleYSq, scaleZSq ) );
1594
1595 },
1596
1597 makeTranslation: function ( x, y, z ) {
1598
1599 this.set(
1600
1601 1, 0, 0, x,
1602 0, 1, 0, y,
1603 0, 0, 1, z,
1604 0, 0, 0, 1
1605
1606 );
1607
1608 return this;
1609
1610 },
1611
1612 makeRotationX: function ( theta ) {
1613
1614 var c = Math.cos( theta ), s = Math.sin( theta );
1615
1616 this.set(
1617
1618 1, 0, 0, 0,
1619 0, c, - s, 0,
1620 0, s, c, 0,
1621 0, 0, 0, 1
1622
1623 );
1624
1625 return this;
1626
1627 },
1628
1629 makeRotationY: function ( theta ) {
1630
1631 var c = Math.cos( theta ), s = Math.sin( theta );
1632
1633 this.set(
1634
1635 c, 0, s, 0,
1636 0, 1, 0, 0,
1637 - s, 0, c, 0,
1638 0, 0, 0, 1
1639
1640 );
1641
1642 return this;
1643
1644 },
1645
1646 makeRotationZ: function ( theta ) {
1647
1648 var c = Math.cos( theta ), s = Math.sin( theta );
1649
1650 this.set(
1651
1652 c, - s, 0, 0,
1653 s, c, 0, 0,
1654 0, 0, 1, 0,
1655 0, 0, 0, 1
1656
1657 );
1658
1659 return this;
1660
1661 },
1662
1663 makeRotationAxis: function ( axis, angle ) {
1664
1665 // Based on http://www.gamedev.net/reference/articles/article1199.asp
1666
1667 var c = Math.cos( angle );
1668 var s = Math.sin( angle );
1669 var t = 1 - c;
1670 var x = axis.x, y = axis.y, z = axis.z;
1671 var tx = t * x, ty = t * y;
1672
1673 this.set(
1674
1675 tx * x + c, tx * y - s * z, tx * z + s * y, 0,
1676 tx * y + s * z, ty * y + c, ty * z - s * x, 0,
1677 tx * z - s * y, ty * z + s * x, t * z * z + c, 0,
1678 0, 0, 0, 1
1679
1680 );
1681
1682 return this;
1683
1684 },
1685
1686 makeScale: function ( x, y, z ) {
1687
1688 this.set(
1689
1690 x, 0, 0, 0,
1691 0, y, 0, 0,
1692 0, 0, z, 0,
1693 0, 0, 0, 1
1694
1695 );
1696
1697 return this;
1698
1699 },
1700
1701 makeShear: function ( x, y, z ) {
1702
1703 this.set(
1704
1705 1, y, z, 0,
1706 x, 1, z, 0,
1707 x, y, 1, 0,
1708 0, 0, 0, 1
1709
1710 );
1711
1712 return this;
1713
1714 },
1715
1716 compose: function ( position, quaternion, scale ) {
1717
1718 this.makeRotationFromQuaternion( quaternion );
1719 this.scale( scale );
1720 this.setPosition( position );
1721
1722 return this;
1723
1724 },
1725
1726 decompose: function () {
1727
1728 var vector = new Vector3();
1729 var matrix = new Matrix4();
1730
1731 return function decompose( position, quaternion, scale ) {
1732
1733 var te = this.elements;
1734
1735 var sx = vector.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length();
1736 var sy = vector.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length();
1737 var sz = vector.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length();
1738
1739 // if determine is negative, we need to invert one scale
1740 var det = this.determinant();
1741 if ( det < 0 ) sx = - sx;
1742
1743 position.x = te[ 12 ];
1744 position.y = te[ 13 ];
1745 position.z = te[ 14 ];
1746
1747 // scale the rotation part
1748 matrix.copy( this );
1749
1750 var invSX = 1 / sx;
1751 var invSY = 1 / sy;
1752 var invSZ = 1 / sz;
1753
1754 matrix.elements[ 0 ] *= invSX;
1755 matrix.elements[ 1 ] *= invSX;
1756 matrix.elements[ 2 ] *= invSX;
1757
1758 matrix.elements[ 4 ] *= invSY;
1759 matrix.elements[ 5 ] *= invSY;
1760 matrix.elements[ 6 ] *= invSY;
1761
1762 matrix.elements[ 8 ] *= invSZ;
1763 matrix.elements[ 9 ] *= invSZ;
1764 matrix.elements[ 10 ] *= invSZ;
1765
1766 quaternion.setFromRotationMatrix( matrix );
1767
1768 scale.x = sx;
1769 scale.y = sy;
1770 scale.z = sz;
1771
1772 return this;
1773
1774 };
1775
1776 }(),
1777
1778 makePerspective: function ( left, right, top, bottom, near, far ) {
1779
1780 if ( far === undefined ) {
1781
1782 console.warn( 'THREE.Matrix4: .makePerspective() has been redefined and has a new signature. Please check the docs.' );
1783
1784 }
1785
1786 var te = this.elements;
1787 var x = 2 * near / ( right - left );
1788 var y = 2 * near / ( top - bottom );
1789
1790 var a = ( right + left ) / ( right - left );
1791 var b = ( top + bottom ) / ( top - bottom );
1792 var c = - ( far + near ) / ( far - near );
1793 var d = - 2 * far * near / ( far - near );
1794
1795 te[ 0 ] = x; te[ 4 ] = 0; te[ 8 ] = a; te[ 12 ] = 0;
1796 te[ 1 ] = 0; te[ 5 ] = y; te[ 9 ] = b; te[ 13 ] = 0;
1797 te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = c; te[ 14 ] = d;
1798 te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = - 1; te[ 15 ] = 0;
1799
1800 return this;
1801
1802 },
1803
1804 makeOrthographic: function ( left, right, top, bottom, near, far ) {
1805
1806 var te = this.elements;
1807 var w = 1.0 / ( right - left );
1808 var h = 1.0 / ( top - bottom );
1809 var p = 1.0 / ( far - near );
1810
1811 var x = ( right + left ) * w;
1812 var y = ( top + bottom ) * h;
1813 var z = ( far + near ) * p;
1814
1815 te[ 0 ] = 2 * w; te[ 4 ] = 0; te[ 8 ] = 0; te[ 12 ] = - x;
1816 te[ 1 ] = 0; te[ 5 ] = 2 * h; te[ 9 ] = 0; te[ 13 ] = - y;
1817 te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = - 2 * p; te[ 14 ] = - z;
1818 te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = 0; te[ 15 ] = 1;
1819
1820 return this;
1821
1822 },
1823
1824 equals: function ( matrix ) {
1825
1826 var te = this.elements;
1827 var me = matrix.elements;
1828
1829 for ( var i = 0; i < 16; i ++ ) {
1830
1831 if ( te[ i ] !== me[ i ] ) return false;
1832
1833 }
1834
1835 return true;
1836
1837 },
1838
1839 fromArray: function ( array, offset ) {
1840
1841 if ( offset === undefined ) offset = 0;
1842
1843 for ( var i = 0; i < 16; i ++ ) {
1844
1845 this.elements[ i ] = array[ i + offset ];
1846
1847 }
1848
1849 return this;
1850
1851 },
1852
1853 toArray: function ( array, offset ) {
1854
1855 if ( array === undefined ) array = [];
1856 if ( offset === undefined ) offset = 0;
1857
1858 var te = this.elements;
1859
1860 array[ offset ] = te[ 0 ];
1861 array[ offset + 1 ] = te[ 1 ];
1862 array[ offset + 2 ] = te[ 2 ];
1863 array[ offset + 3 ] = te[ 3 ];
1864
1865 array[ offset + 4 ] = te[ 4 ];
1866 array[ offset + 5 ] = te[ 5 ];
1867 array[ offset + 6 ] = te[ 6 ];
1868 array[ offset + 7 ] = te[ 7 ];
1869
1870 array[ offset + 8 ] = te[ 8 ];
1871 array[ offset + 9 ] = te[ 9 ];
1872 array[ offset + 10 ] = te[ 10 ];
1873 array[ offset + 11 ] = te[ 11 ];
1874
1875 array[ offset + 12 ] = te[ 12 ];
1876 array[ offset + 13 ] = te[ 13 ];
1877 array[ offset + 14 ] = te[ 14 ];
1878 array[ offset + 15 ] = te[ 15 ];
1879
1880 return array;
1881
1882 }
1883
1884} );
1885
1886/**
1887 * @author mikael emtinger / http://gomo.se/
1888 * @author alteredq / http://alteredqualia.com/
1889 * @author WestLangley / http://github.com/WestLangley
1890 * @author bhouston / http://clara.io
1891 */
1892
1893function Quaternion( x, y, z, w ) {
1894
1895 this._x = x || 0;
1896 this._y = y || 0;
1897 this._z = z || 0;
1898 this._w = ( w !== undefined ) ? w : 1;
1899
1900}
1901
1902Object.assign( Quaternion, {
1903
1904 slerp: function ( qa, qb, qm, t ) {
1905
1906 return qm.copy( qa ).slerp( qb, t );
1907
1908 },
1909
1910 slerpFlat: function ( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) {
1911
1912 // fuzz-free, array-based Quaternion SLERP operation
1913
1914 var x0 = src0[ srcOffset0 + 0 ],
1915 y0 = src0[ srcOffset0 + 1 ],
1916 z0 = src0[ srcOffset0 + 2 ],
1917 w0 = src0[ srcOffset0 + 3 ],
1918
1919 x1 = src1[ srcOffset1 + 0 ],
1920 y1 = src1[ srcOffset1 + 1 ],
1921 z1 = src1[ srcOffset1 + 2 ],
1922 w1 = src1[ srcOffset1 + 3 ];
1923
1924 if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) {
1925
1926 var s = 1 - t,
1927
1928 cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1,
1929
1930 dir = ( cos >= 0 ? 1 : - 1 ),
1931 sqrSin = 1 - cos * cos;
1932
1933 // Skip the Slerp for tiny steps to avoid numeric problems:
1934 if ( sqrSin > Number.EPSILON ) {
1935
1936 var sin = Math.sqrt( sqrSin ),
1937 len = Math.atan2( sin, cos * dir );
1938
1939 s = Math.sin( s * len ) / sin;
1940 t = Math.sin( t * len ) / sin;
1941
1942 }
1943
1944 var tDir = t * dir;
1945
1946 x0 = x0 * s + x1 * tDir;
1947 y0 = y0 * s + y1 * tDir;
1948 z0 = z0 * s + z1 * tDir;
1949 w0 = w0 * s + w1 * tDir;
1950
1951 // Normalize in case we just did a lerp:
1952 if ( s === 1 - t ) {
1953
1954 var f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 );
1955
1956 x0 *= f;
1957 y0 *= f;
1958 z0 *= f;
1959 w0 *= f;
1960
1961 }
1962
1963 }
1964
1965 dst[ dstOffset ] = x0;
1966 dst[ dstOffset + 1 ] = y0;
1967 dst[ dstOffset + 2 ] = z0;
1968 dst[ dstOffset + 3 ] = w0;
1969
1970 }
1971
1972} );
1973
1974Object.defineProperties( Quaternion.prototype, {
1975
1976 x: {
1977
1978 get: function () {
1979
1980 return this._x;
1981
1982 },
1983
1984 set: function ( value ) {
1985
1986 this._x = value;
1987 this.onChangeCallback();
1988
1989 }
1990
1991 },
1992
1993 y: {
1994
1995 get: function () {
1996
1997 return this._y;
1998
1999 },
2000
2001 set: function ( value ) {
2002
2003 this._y = value;
2004 this.onChangeCallback();
2005
2006 }
2007
2008 },
2009
2010 z: {
2011
2012 get: function () {
2013
2014 return this._z;
2015
2016 },
2017
2018 set: function ( value ) {
2019
2020 this._z = value;
2021 this.onChangeCallback();
2022
2023 }
2024
2025 },
2026
2027 w: {
2028
2029 get: function () {
2030
2031 return this._w;
2032
2033 },
2034
2035 set: function ( value ) {
2036
2037 this._w = value;
2038 this.onChangeCallback();
2039
2040 }
2041
2042 }
2043
2044} );
2045
2046Object.assign( Quaternion.prototype, {
2047
2048 set: function ( x, y, z, w ) {
2049
2050 this._x = x;
2051 this._y = y;
2052 this._z = z;
2053 this._w = w;
2054
2055 this.onChangeCallback();
2056
2057 return this;
2058
2059 },
2060
2061 clone: function () {
2062
2063 return new this.constructor( this._x, this._y, this._z, this._w );
2064
2065 },
2066
2067 copy: function ( quaternion ) {
2068
2069 this._x = quaternion.x;
2070 this._y = quaternion.y;
2071 this._z = quaternion.z;
2072 this._w = quaternion.w;
2073
2074 this.onChangeCallback();
2075
2076 return this;
2077
2078 },
2079
2080 setFromEuler: function ( euler, update ) {
2081
2082 if ( ! ( euler && euler.isEuler ) ) {
2083
2084 throw new Error( 'THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.' );
2085
2086 }
2087
2088 var x = euler._x, y = euler._y, z = euler._z, order = euler.order;
2089
2090 // http://www.mathworks.com/matlabcentral/fileexchange/
2091 // 20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/
2092 // content/SpinCalc.m
2093
2094 var cos = Math.cos;
2095 var sin = Math.sin;
2096
2097 var c1 = cos( x / 2 );
2098 var c2 = cos( y / 2 );
2099 var c3 = cos( z / 2 );
2100
2101 var s1 = sin( x / 2 );
2102 var s2 = sin( y / 2 );
2103 var s3 = sin( z / 2 );
2104
2105 if ( order === 'XYZ' ) {
2106
2107 this._x = s1 * c2 * c3 + c1 * s2 * s3;
2108 this._y = c1 * s2 * c3 - s1 * c2 * s3;
2109 this._z = c1 * c2 * s3 + s1 * s2 * c3;
2110 this._w = c1 * c2 * c3 - s1 * s2 * s3;
2111
2112 } else if ( order === 'YXZ' ) {
2113
2114 this._x = s1 * c2 * c3 + c1 * s2 * s3;
2115 this._y = c1 * s2 * c3 - s1 * c2 * s3;
2116 this._z = c1 * c2 * s3 - s1 * s2 * c3;
2117 this._w = c1 * c2 * c3 + s1 * s2 * s3;
2118
2119 } else if ( order === 'ZXY' ) {
2120
2121 this._x = s1 * c2 * c3 - c1 * s2 * s3;
2122 this._y = c1 * s2 * c3 + s1 * c2 * s3;
2123 this._z = c1 * c2 * s3 + s1 * s2 * c3;
2124 this._w = c1 * c2 * c3 - s1 * s2 * s3;
2125
2126 } else if ( order === 'ZYX' ) {
2127
2128 this._x = s1 * c2 * c3 - c1 * s2 * s3;
2129 this._y = c1 * s2 * c3 + s1 * c2 * s3;
2130 this._z = c1 * c2 * s3 - s1 * s2 * c3;
2131 this._w = c1 * c2 * c3 + s1 * s2 * s3;
2132
2133 } else if ( order === 'YZX' ) {
2134
2135 this._x = s1 * c2 * c3 + c1 * s2 * s3;
2136 this._y = c1 * s2 * c3 + s1 * c2 * s3;
2137 this._z = c1 * c2 * s3 - s1 * s2 * c3;
2138 this._w = c1 * c2 * c3 - s1 * s2 * s3;
2139
2140 } else if ( order === 'XZY' ) {
2141
2142 this._x = s1 * c2 * c3 - c1 * s2 * s3;
2143 this._y = c1 * s2 * c3 - s1 * c2 * s3;
2144 this._z = c1 * c2 * s3 + s1 * s2 * c3;
2145 this._w = c1 * c2 * c3 + s1 * s2 * s3;
2146
2147 }
2148
2149 if ( update !== false ) this.onChangeCallback();
2150
2151 return this;
2152
2153 },
2154
2155 setFromAxisAngle: function ( axis, angle ) {
2156
2157 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm
2158
2159 // assumes axis is normalized
2160
2161 var halfAngle = angle / 2, s = Math.sin( halfAngle );
2162
2163 this._x = axis.x * s;
2164 this._y = axis.y * s;
2165 this._z = axis.z * s;
2166 this._w = Math.cos( halfAngle );
2167
2168 this.onChangeCallback();
2169
2170 return this;
2171
2172 },
2173
2174 setFromRotationMatrix: function ( m ) {
2175
2176 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
2177
2178 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
2179
2180 var te = m.elements,
2181
2182 m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
2183 m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
2184 m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ],
2185
2186 trace = m11 + m22 + m33,
2187 s;
2188
2189 if ( trace > 0 ) {
2190
2191 s = 0.5 / Math.sqrt( trace + 1.0 );
2192
2193 this._w = 0.25 / s;
2194 this._x = ( m32 - m23 ) * s;
2195 this._y = ( m13 - m31 ) * s;
2196 this._z = ( m21 - m12 ) * s;
2197
2198 } else if ( m11 > m22 && m11 > m33 ) {
2199
2200 s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 );
2201
2202 this._w = ( m32 - m23 ) / s;
2203 this._x = 0.25 * s;
2204 this._y = ( m12 + m21 ) / s;
2205 this._z = ( m13 + m31 ) / s;
2206
2207 } else if ( m22 > m33 ) {
2208
2209 s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 );
2210
2211 this._w = ( m13 - m31 ) / s;
2212 this._x = ( m12 + m21 ) / s;
2213 this._y = 0.25 * s;
2214 this._z = ( m23 + m32 ) / s;
2215
2216 } else {
2217
2218 s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 );
2219
2220 this._w = ( m21 - m12 ) / s;
2221 this._x = ( m13 + m31 ) / s;
2222 this._y = ( m23 + m32 ) / s;
2223 this._z = 0.25 * s;
2224
2225 }
2226
2227 this.onChangeCallback();
2228
2229 return this;
2230
2231 },
2232
2233 setFromUnitVectors: function () {
2234
2235 // assumes direction vectors vFrom and vTo are normalized
2236
2237 var v1 = new Vector3();
2238 var r;
2239
2240 var EPS = 0.000001;
2241
2242 return function setFromUnitVectors( vFrom, vTo ) {
2243
2244 if ( v1 === undefined ) v1 = new Vector3();
2245
2246 r = vFrom.dot( vTo ) + 1;
2247
2248 if ( r < EPS ) {
2249
2250 r = 0;
2251
2252 if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) {
2253
2254 v1.set( - vFrom.y, vFrom.x, 0 );
2255
2256 } else {
2257
2258 v1.set( 0, - vFrom.z, vFrom.y );
2259
2260 }
2261
2262 } else {
2263
2264 v1.crossVectors( vFrom, vTo );
2265
2266 }
2267
2268 this._x = v1.x;
2269 this._y = v1.y;
2270 this._z = v1.z;
2271 this._w = r;
2272
2273 return this.normalize();
2274
2275 };
2276
2277 }(),
2278
2279 inverse: function () {
2280
2281 // quaternion is assumed to have unit length
2282
2283 return this.conjugate();
2284
2285 },
2286
2287 conjugate: function () {
2288
2289 this._x *= - 1;
2290 this._y *= - 1;
2291 this._z *= - 1;
2292
2293 this.onChangeCallback();
2294
2295 return this;
2296
2297 },
2298
2299 dot: function ( v ) {
2300
2301 return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w;
2302
2303 },
2304
2305 lengthSq: function () {
2306
2307 return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w;
2308
2309 },
2310
2311 length: function () {
2312
2313 return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w );
2314
2315 },
2316
2317 normalize: function () {
2318
2319 var l = this.length();
2320
2321 if ( l === 0 ) {
2322
2323 this._x = 0;
2324 this._y = 0;
2325 this._z = 0;
2326 this._w = 1;
2327
2328 } else {
2329
2330 l = 1 / l;
2331
2332 this._x = this._x * l;
2333 this._y = this._y * l;
2334 this._z = this._z * l;
2335 this._w = this._w * l;
2336
2337 }
2338
2339 this.onChangeCallback();
2340
2341 return this;
2342
2343 },
2344
2345 multiply: function ( q, p ) {
2346
2347 if ( p !== undefined ) {
2348
2349 console.warn( 'THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead.' );
2350 return this.multiplyQuaternions( q, p );
2351
2352 }
2353
2354 return this.multiplyQuaternions( this, q );
2355
2356 },
2357
2358 premultiply: function ( q ) {
2359
2360 return this.multiplyQuaternions( q, this );
2361
2362 },
2363
2364 multiplyQuaternions: function ( a, b ) {
2365
2366 // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm
2367
2368 var qax = a._x, qay = a._y, qaz = a._z, qaw = a._w;
2369 var qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w;
2370
2371 this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;
2372 this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;
2373 this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;
2374 this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;
2375
2376 this.onChangeCallback();
2377
2378 return this;
2379
2380 },
2381
2382 slerp: function ( qb, t ) {
2383
2384 if ( t === 0 ) return this;
2385 if ( t === 1 ) return this.copy( qb );
2386
2387 var x = this._x, y = this._y, z = this._z, w = this._w;
2388
2389 // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/
2390
2391 var cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z;
2392
2393 if ( cosHalfTheta < 0 ) {
2394
2395 this._w = - qb._w;
2396 this._x = - qb._x;
2397 this._y = - qb._y;
2398 this._z = - qb._z;
2399
2400 cosHalfTheta = - cosHalfTheta;
2401
2402 } else {
2403
2404 this.copy( qb );
2405
2406 }
2407
2408 if ( cosHalfTheta >= 1.0 ) {
2409
2410 this._w = w;
2411 this._x = x;
2412 this._y = y;
2413 this._z = z;
2414
2415 return this;
2416
2417 }
2418
2419 var sinHalfTheta = Math.sqrt( 1.0 - cosHalfTheta * cosHalfTheta );
2420
2421 if ( Math.abs( sinHalfTheta ) < 0.001 ) {
2422
2423 this._w = 0.5 * ( w + this._w );
2424 this._x = 0.5 * ( x + this._x );
2425 this._y = 0.5 * ( y + this._y );
2426 this._z = 0.5 * ( z + this._z );
2427
2428 return this;
2429
2430 }
2431
2432 var halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta );
2433 var ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta,
2434 ratioB = Math.sin( t * halfTheta ) / sinHalfTheta;
2435
2436 this._w = ( w * ratioA + this._w * ratioB );
2437 this._x = ( x * ratioA + this._x * ratioB );
2438 this._y = ( y * ratioA + this._y * ratioB );
2439 this._z = ( z * ratioA + this._z * ratioB );
2440
2441 this.onChangeCallback();
2442
2443 return this;
2444
2445 },
2446
2447 equals: function ( quaternion ) {
2448
2449 return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w );
2450
2451 },
2452
2453 fromArray: function ( array, offset ) {
2454
2455 if ( offset === undefined ) offset = 0;
2456
2457 this._x = array[ offset ];
2458 this._y = array[ offset + 1 ];
2459 this._z = array[ offset + 2 ];
2460 this._w = array[ offset + 3 ];
2461
2462 this.onChangeCallback();
2463
2464 return this;
2465
2466 },
2467
2468 toArray: function ( array, offset ) {
2469
2470 if ( array === undefined ) array = [];
2471 if ( offset === undefined ) offset = 0;
2472
2473 array[ offset ] = this._x;
2474 array[ offset + 1 ] = this._y;
2475 array[ offset + 2 ] = this._z;
2476 array[ offset + 3 ] = this._w;
2477
2478 return array;
2479
2480 },
2481
2482 onChange: function ( callback ) {
2483
2484 this.onChangeCallback = callback;
2485
2486 return this;
2487
2488 },
2489
2490 onChangeCallback: function () {}
2491
2492} );
2493
2494/**
2495 * @author mrdoob / http://mrdoob.com/
2496 * @author kile / http://kile.stravaganza.org/
2497 * @author philogb / http://blog.thejit.org/
2498 * @author mikael emtinger / http://gomo.se/
2499 * @author egraether / http://egraether.com/
2500 * @author WestLangley / http://github.com/WestLangley
2501 */
2502
2503function Vector3( x, y, z ) {
2504
2505 this.x = x || 0;
2506 this.y = y || 0;
2507 this.z = z || 0;
2508
2509}
2510
2511Object.assign( Vector3.prototype, {
2512
2513 isVector3: true,
2514
2515 set: function ( x, y, z ) {
2516
2517 this.x = x;
2518 this.y = y;
2519 this.z = z;
2520
2521 return this;
2522
2523 },
2524
2525 setScalar: function ( scalar ) {
2526
2527 this.x = scalar;
2528 this.y = scalar;
2529 this.z = scalar;
2530
2531 return this;
2532
2533 },
2534
2535 setX: function ( x ) {
2536
2537 this.x = x;
2538
2539 return this;
2540
2541 },
2542
2543 setY: function ( y ) {
2544
2545 this.y = y;
2546
2547 return this;
2548
2549 },
2550
2551 setZ: function ( z ) {
2552
2553 this.z = z;
2554
2555 return this;
2556
2557 },
2558
2559 setComponent: function ( index, value ) {
2560
2561 switch ( index ) {
2562
2563 case 0: this.x = value; break;
2564 case 1: this.y = value; break;
2565 case 2: this.z = value; break;
2566 default: throw new Error( 'index is out of range: ' + index );
2567
2568 }
2569
2570 return this;
2571
2572 },
2573
2574 getComponent: function ( index ) {
2575
2576 switch ( index ) {
2577
2578 case 0: return this.x;
2579 case 1: return this.y;
2580 case 2: return this.z;
2581 default: throw new Error( 'index is out of range: ' + index );
2582
2583 }
2584
2585 },
2586
2587 clone: function () {
2588
2589 return new this.constructor( this.x, this.y, this.z );
2590
2591 },
2592
2593 copy: function ( v ) {
2594
2595 this.x = v.x;
2596 this.y = v.y;
2597 this.z = v.z;
2598
2599 return this;
2600
2601 },
2602
2603 add: function ( v, w ) {
2604
2605 if ( w !== undefined ) {
2606
2607 console.warn( 'THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
2608 return this.addVectors( v, w );
2609
2610 }
2611
2612 this.x += v.x;
2613 this.y += v.y;
2614 this.z += v.z;
2615
2616 return this;
2617
2618 },
2619
2620 addScalar: function ( s ) {
2621
2622 this.x += s;
2623 this.y += s;
2624 this.z += s;
2625
2626 return this;
2627
2628 },
2629
2630 addVectors: function ( a, b ) {
2631
2632 this.x = a.x + b.x;
2633 this.y = a.y + b.y;
2634 this.z = a.z + b.z;
2635
2636 return this;
2637
2638 },
2639
2640 addScaledVector: function ( v, s ) {
2641
2642 this.x += v.x * s;
2643 this.y += v.y * s;
2644 this.z += v.z * s;
2645
2646 return this;
2647
2648 },
2649
2650 sub: function ( v, w ) {
2651
2652 if ( w !== undefined ) {
2653
2654 console.warn( 'THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
2655 return this.subVectors( v, w );
2656
2657 }
2658
2659 this.x -= v.x;
2660 this.y -= v.y;
2661 this.z -= v.z;
2662
2663 return this;
2664
2665 },
2666
2667 subScalar: function ( s ) {
2668
2669 this.x -= s;
2670 this.y -= s;
2671 this.z -= s;
2672
2673 return this;
2674
2675 },
2676
2677 subVectors: function ( a, b ) {
2678
2679 this.x = a.x - b.x;
2680 this.y = a.y - b.y;
2681 this.z = a.z - b.z;
2682
2683 return this;
2684
2685 },
2686
2687 multiply: function ( v, w ) {
2688
2689 if ( w !== undefined ) {
2690
2691 console.warn( 'THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead.' );
2692 return this.multiplyVectors( v, w );
2693
2694 }
2695
2696 this.x *= v.x;
2697 this.y *= v.y;
2698 this.z *= v.z;
2699
2700 return this;
2701
2702 },
2703
2704 multiplyScalar: function ( scalar ) {
2705
2706 this.x *= scalar;
2707 this.y *= scalar;
2708 this.z *= scalar;
2709
2710 return this;
2711
2712 },
2713
2714 multiplyVectors: function ( a, b ) {
2715
2716 this.x = a.x * b.x;
2717 this.y = a.y * b.y;
2718 this.z = a.z * b.z;
2719
2720 return this;
2721
2722 },
2723
2724 applyEuler: function () {
2725
2726 var quaternion = new Quaternion();
2727
2728 return function applyEuler( euler ) {
2729
2730 if ( ! ( euler && euler.isEuler ) ) {
2731
2732 console.error( 'THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order.' );
2733
2734 }
2735
2736 return this.applyQuaternion( quaternion.setFromEuler( euler ) );
2737
2738 };
2739
2740 }(),
2741
2742 applyAxisAngle: function () {
2743
2744 var quaternion = new Quaternion();
2745
2746 return function applyAxisAngle( axis, angle ) {
2747
2748 return this.applyQuaternion( quaternion.setFromAxisAngle( axis, angle ) );
2749
2750 };
2751
2752 }(),
2753
2754 applyMatrix3: function ( m ) {
2755
2756 var x = this.x, y = this.y, z = this.z;
2757 var e = m.elements;
2758
2759 this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z;
2760 this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z;
2761 this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z;
2762
2763 return this;
2764
2765 },
2766
2767 applyMatrix4: function ( m ) {
2768
2769 var x = this.x, y = this.y, z = this.z;
2770 var e = m.elements;
2771
2772 var w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] );
2773
2774 this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w;
2775 this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w;
2776 this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w;
2777
2778 return this;
2779
2780 },
2781
2782 applyQuaternion: function ( q ) {
2783
2784 var x = this.x, y = this.y, z = this.z;
2785 var qx = q.x, qy = q.y, qz = q.z, qw = q.w;
2786
2787 // calculate quat * vector
2788
2789 var ix = qw * x + qy * z - qz * y;
2790 var iy = qw * y + qz * x - qx * z;
2791 var iz = qw * z + qx * y - qy * x;
2792 var iw = - qx * x - qy * y - qz * z;
2793
2794 // calculate result * inverse quat
2795
2796 this.x = ix * qw + iw * - qx + iy * - qz - iz * - qy;
2797 this.y = iy * qw + iw * - qy + iz * - qx - ix * - qz;
2798 this.z = iz * qw + iw * - qz + ix * - qy - iy * - qx;
2799
2800 return this;
2801
2802 },
2803
2804 project: function () {
2805
2806 var matrix = new Matrix4();
2807
2808 return function project( camera ) {
2809
2810 matrix.multiplyMatrices( camera.projectionMatrix, matrix.getInverse( camera.matrixWorld ) );
2811 return this.applyMatrix4( matrix );
2812
2813 };
2814
2815 }(),
2816
2817 unproject: function () {
2818
2819 var matrix = new Matrix4();
2820
2821 return function unproject( camera ) {
2822
2823 matrix.multiplyMatrices( camera.matrixWorld, matrix.getInverse( camera.projectionMatrix ) );
2824 return this.applyMatrix4( matrix );
2825
2826 };
2827
2828 }(),
2829
2830 transformDirection: function ( m ) {
2831
2832 // input: THREE.Matrix4 affine matrix
2833 // vector interpreted as a direction
2834
2835 var x = this.x, y = this.y, z = this.z;
2836 var e = m.elements;
2837
2838 this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z;
2839 this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z;
2840 this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z;
2841
2842 return this.normalize();
2843
2844 },
2845
2846 divide: function ( v ) {
2847
2848 this.x /= v.x;
2849 this.y /= v.y;
2850 this.z /= v.z;
2851
2852 return this;
2853
2854 },
2855
2856 divideScalar: function ( scalar ) {
2857
2858 return this.multiplyScalar( 1 / scalar );
2859
2860 },
2861
2862 min: function ( v ) {
2863
2864 this.x = Math.min( this.x, v.x );
2865 this.y = Math.min( this.y, v.y );
2866 this.z = Math.min( this.z, v.z );
2867
2868 return this;
2869
2870 },
2871
2872 max: function ( v ) {
2873
2874 this.x = Math.max( this.x, v.x );
2875 this.y = Math.max( this.y, v.y );
2876 this.z = Math.max( this.z, v.z );
2877
2878 return this;
2879
2880 },
2881
2882 clamp: function ( min, max ) {
2883
2884 // assumes min < max, componentwise
2885
2886 this.x = Math.max( min.x, Math.min( max.x, this.x ) );
2887 this.y = Math.max( min.y, Math.min( max.y, this.y ) );
2888 this.z = Math.max( min.z, Math.min( max.z, this.z ) );
2889
2890 return this;
2891
2892 },
2893
2894 clampScalar: function () {
2895
2896 var min = new Vector3();
2897 var max = new Vector3();
2898
2899 return function clampScalar( minVal, maxVal ) {
2900
2901 min.set( minVal, minVal, minVal );
2902 max.set( maxVal, maxVal, maxVal );
2903
2904 return this.clamp( min, max );
2905
2906 };
2907
2908 }(),
2909
2910 clampLength: function ( min, max ) {
2911
2912 var length = this.length();
2913
2914 return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
2915
2916 },
2917
2918 floor: function () {
2919
2920 this.x = Math.floor( this.x );
2921 this.y = Math.floor( this.y );
2922 this.z = Math.floor( this.z );
2923
2924 return this;
2925
2926 },
2927
2928 ceil: function () {
2929
2930 this.x = Math.ceil( this.x );
2931 this.y = Math.ceil( this.y );
2932 this.z = Math.ceil( this.z );
2933
2934 return this;
2935
2936 },
2937
2938 round: function () {
2939
2940 this.x = Math.round( this.x );
2941 this.y = Math.round( this.y );
2942 this.z = Math.round( this.z );
2943
2944 return this;
2945
2946 },
2947
2948 roundToZero: function () {
2949
2950 this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
2951 this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
2952 this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );
2953
2954 return this;
2955
2956 },
2957
2958 negate: function () {
2959
2960 this.x = - this.x;
2961 this.y = - this.y;
2962 this.z = - this.z;
2963
2964 return this;
2965
2966 },
2967
2968 dot: function ( v ) {
2969
2970 return this.x * v.x + this.y * v.y + this.z * v.z;
2971
2972 },
2973
2974 // TODO lengthSquared?
2975
2976 lengthSq: function () {
2977
2978 return this.x * this.x + this.y * this.y + this.z * this.z;
2979
2980 },
2981
2982 length: function () {
2983
2984 return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z );
2985
2986 },
2987
2988 manhattanLength: function () {
2989
2990 return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z );
2991
2992 },
2993
2994 normalize: function () {
2995
2996 return this.divideScalar( this.length() || 1 );
2997
2998 },
2999
3000 setLength: function ( length ) {
3001
3002 return this.normalize().multiplyScalar( length );
3003
3004 },
3005
3006 lerp: function ( v, alpha ) {
3007
3008 this.x += ( v.x - this.x ) * alpha;
3009 this.y += ( v.y - this.y ) * alpha;
3010 this.z += ( v.z - this.z ) * alpha;
3011
3012 return this;
3013
3014 },
3015
3016 lerpVectors: function ( v1, v2, alpha ) {
3017
3018 return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );
3019
3020 },
3021
3022 cross: function ( v, w ) {
3023
3024 if ( w !== undefined ) {
3025
3026 console.warn( 'THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead.' );
3027 return this.crossVectors( v, w );
3028
3029 }
3030
3031 return this.crossVectors( this, v );
3032
3033 },
3034
3035 crossVectors: function ( a, b ) {
3036
3037 var ax = a.x, ay = a.y, az = a.z;
3038 var bx = b.x, by = b.y, bz = b.z;
3039
3040 this.x = ay * bz - az * by;
3041 this.y = az * bx - ax * bz;
3042 this.z = ax * by - ay * bx;
3043
3044 return this;
3045
3046 },
3047
3048 projectOnVector: function ( vector ) {
3049
3050 var scalar = vector.dot( this ) / vector.lengthSq();
3051
3052 return this.copy( vector ).multiplyScalar( scalar );
3053
3054 },
3055
3056 projectOnPlane: function () {
3057
3058 var v1 = new Vector3();
3059
3060 return function projectOnPlane( planeNormal ) {
3061
3062 v1.copy( this ).projectOnVector( planeNormal );
3063
3064 return this.sub( v1 );
3065
3066 };
3067
3068 }(),
3069
3070 reflect: function () {
3071
3072 // reflect incident vector off plane orthogonal to normal
3073 // normal is assumed to have unit length
3074
3075 var v1 = new Vector3();
3076
3077 return function reflect( normal ) {
3078
3079 return this.sub( v1.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) );
3080
3081 };
3082
3083 }(),
3084
3085 angleTo: function ( v ) {
3086
3087 var theta = this.dot( v ) / ( Math.sqrt( this.lengthSq() * v.lengthSq() ) );
3088
3089 // clamp, to handle numerical problems
3090
3091 return Math.acos( _Math.clamp( theta, - 1, 1 ) );
3092
3093 },
3094
3095 distanceTo: function ( v ) {
3096
3097 return Math.sqrt( this.distanceToSquared( v ) );
3098
3099 },
3100
3101 distanceToSquared: function ( v ) {
3102
3103 var dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z;
3104
3105 return dx * dx + dy * dy + dz * dz;
3106
3107 },
3108
3109 manhattanDistanceTo: function ( v ) {
3110
3111 return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ) + Math.abs( this.z - v.z );
3112
3113 },
3114
3115 setFromSpherical: function ( s ) {
3116
3117 var sinPhiRadius = Math.sin( s.phi ) * s.radius;
3118
3119 this.x = sinPhiRadius * Math.sin( s.theta );
3120 this.y = Math.cos( s.phi ) * s.radius;
3121 this.z = sinPhiRadius * Math.cos( s.theta );
3122
3123 return this;
3124
3125 },
3126
3127 setFromCylindrical: function ( c ) {
3128
3129 this.x = c.radius * Math.sin( c.theta );
3130 this.y = c.y;
3131 this.z = c.radius * Math.cos( c.theta );
3132
3133 return this;
3134
3135 },
3136
3137 setFromMatrixPosition: function ( m ) {
3138
3139 var e = m.elements;
3140
3141 this.x = e[ 12 ];
3142 this.y = e[ 13 ];
3143 this.z = e[ 14 ];
3144
3145 return this;
3146
3147 },
3148
3149 setFromMatrixScale: function ( m ) {
3150
3151 var sx = this.setFromMatrixColumn( m, 0 ).length();
3152 var sy = this.setFromMatrixColumn( m, 1 ).length();
3153 var sz = this.setFromMatrixColumn( m, 2 ).length();
3154
3155 this.x = sx;
3156 this.y = sy;
3157 this.z = sz;
3158
3159 return this;
3160
3161 },
3162
3163 setFromMatrixColumn: function ( m, index ) {
3164
3165 return this.fromArray( m.elements, index * 4 );
3166
3167 },
3168
3169 equals: function ( v ) {
3170
3171 return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) );
3172
3173 },
3174
3175 fromArray: function ( array, offset ) {
3176
3177 if ( offset === undefined ) offset = 0;
3178
3179 this.x = array[ offset ];
3180 this.y = array[ offset + 1 ];
3181 this.z = array[ offset + 2 ];
3182
3183 return this;
3184
3185 },
3186
3187 toArray: function ( array, offset ) {
3188
3189 if ( array === undefined ) array = [];
3190 if ( offset === undefined ) offset = 0;
3191
3192 array[ offset ] = this.x;
3193 array[ offset + 1 ] = this.y;
3194 array[ offset + 2 ] = this.z;
3195
3196 return array;
3197
3198 },
3199
3200 fromBufferAttribute: function ( attribute, index, offset ) {
3201
3202 if ( offset !== undefined ) {
3203
3204 console.warn( 'THREE.Vector3: offset has been removed from .fromBufferAttribute().' );
3205
3206 }
3207
3208 this.x = attribute.getX( index );
3209 this.y = attribute.getY( index );
3210 this.z = attribute.getZ( index );
3211
3212 return this;
3213
3214 }
3215
3216} );
3217
3218/**
3219 * @author alteredq / http://alteredqualia.com/
3220 * @author WestLangley / http://github.com/WestLangley
3221 * @author bhouston / http://clara.io
3222 * @author tschw
3223 */
3224
3225function Matrix3() {
3226
3227 this.elements = [
3228
3229 1, 0, 0,
3230 0, 1, 0,
3231 0, 0, 1
3232
3233 ];
3234
3235 if ( arguments.length > 0 ) {
3236
3237 console.error( 'THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.' );
3238
3239 }
3240
3241}
3242
3243Object.assign( Matrix3.prototype, {
3244
3245 isMatrix3: true,
3246
3247 set: function ( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) {
3248
3249 var te = this.elements;
3250
3251 te[ 0 ] = n11; te[ 1 ] = n21; te[ 2 ] = n31;
3252 te[ 3 ] = n12; te[ 4 ] = n22; te[ 5 ] = n32;
3253 te[ 6 ] = n13; te[ 7 ] = n23; te[ 8 ] = n33;
3254
3255 return this;
3256
3257 },
3258
3259 identity: function () {
3260
3261 this.set(
3262
3263 1, 0, 0,
3264 0, 1, 0,
3265 0, 0, 1
3266
3267 );
3268
3269 return this;
3270
3271 },
3272
3273 clone: function () {
3274
3275 return new this.constructor().fromArray( this.elements );
3276
3277 },
3278
3279 copy: function ( m ) {
3280
3281 var te = this.elements;
3282 var me = m.elements;
3283
3284 te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ];
3285 te[ 3 ] = me[ 3 ]; te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ];
3286 te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ]; te[ 8 ] = me[ 8 ];
3287
3288 return this;
3289
3290 },
3291
3292 setFromMatrix4: function ( m ) {
3293
3294 var me = m.elements;
3295
3296 this.set(
3297
3298 me[ 0 ], me[ 4 ], me[ 8 ],
3299 me[ 1 ], me[ 5 ], me[ 9 ],
3300 me[ 2 ], me[ 6 ], me[ 10 ]
3301
3302 );
3303
3304 return this;
3305
3306 },
3307
3308 applyToBufferAttribute: function () {
3309
3310 var v1 = new Vector3();
3311
3312 return function applyToBufferAttribute( attribute ) {
3313
3314 for ( var i = 0, l = attribute.count; i < l; i ++ ) {
3315
3316 v1.x = attribute.getX( i );
3317 v1.y = attribute.getY( i );
3318 v1.z = attribute.getZ( i );
3319
3320 v1.applyMatrix3( this );
3321
3322 attribute.setXYZ( i, v1.x, v1.y, v1.z );
3323
3324 }
3325
3326 return attribute;
3327
3328 };
3329
3330 }(),
3331
3332 multiply: function ( m ) {
3333
3334 return this.multiplyMatrices( this, m );
3335
3336 },
3337
3338 premultiply: function ( m ) {
3339
3340 return this.multiplyMatrices( m, this );
3341
3342 },
3343
3344 multiplyMatrices: function ( a, b ) {
3345
3346 var ae = a.elements;
3347 var be = b.elements;
3348 var te = this.elements;
3349
3350 var a11 = ae[ 0 ], a12 = ae[ 3 ], a13 = ae[ 6 ];
3351 var a21 = ae[ 1 ], a22 = ae[ 4 ], a23 = ae[ 7 ];
3352 var a31 = ae[ 2 ], a32 = ae[ 5 ], a33 = ae[ 8 ];
3353
3354 var b11 = be[ 0 ], b12 = be[ 3 ], b13 = be[ 6 ];
3355 var b21 = be[ 1 ], b22 = be[ 4 ], b23 = be[ 7 ];
3356 var b31 = be[ 2 ], b32 = be[ 5 ], b33 = be[ 8 ];
3357
3358 te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31;
3359 te[ 3 ] = a11 * b12 + a12 * b22 + a13 * b32;
3360 te[ 6 ] = a11 * b13 + a12 * b23 + a13 * b33;
3361
3362 te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31;
3363 te[ 4 ] = a21 * b12 + a22 * b22 + a23 * b32;
3364 te[ 7 ] = a21 * b13 + a22 * b23 + a23 * b33;
3365
3366 te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31;
3367 te[ 5 ] = a31 * b12 + a32 * b22 + a33 * b32;
3368 te[ 8 ] = a31 * b13 + a32 * b23 + a33 * b33;
3369
3370 return this;
3371
3372 },
3373
3374 multiplyScalar: function ( s ) {
3375
3376 var te = this.elements;
3377
3378 te[ 0 ] *= s; te[ 3 ] *= s; te[ 6 ] *= s;
3379 te[ 1 ] *= s; te[ 4 ] *= s; te[ 7 ] *= s;
3380 te[ 2 ] *= s; te[ 5 ] *= s; te[ 8 ] *= s;
3381
3382 return this;
3383
3384 },
3385
3386 determinant: function () {
3387
3388 var te = this.elements;
3389
3390 var a = te[ 0 ], b = te[ 1 ], c = te[ 2 ],
3391 d = te[ 3 ], e = te[ 4 ], f = te[ 5 ],
3392 g = te[ 6 ], h = te[ 7 ], i = te[ 8 ];
3393
3394 return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g;
3395
3396 },
3397
3398 getInverse: function ( matrix, throwOnDegenerate ) {
3399
3400 if ( matrix && matrix.isMatrix4 ) {
3401
3402 console.error( "THREE.Matrix3: .getInverse() no longer takes a Matrix4 argument." );
3403
3404 }
3405
3406 var me = matrix.elements,
3407 te = this.elements,
3408
3409 n11 = me[ 0 ], n21 = me[ 1 ], n31 = me[ 2 ],
3410 n12 = me[ 3 ], n22 = me[ 4 ], n32 = me[ 5 ],
3411 n13 = me[ 6 ], n23 = me[ 7 ], n33 = me[ 8 ],
3412
3413 t11 = n33 * n22 - n32 * n23,
3414 t12 = n32 * n13 - n33 * n12,
3415 t13 = n23 * n12 - n22 * n13,
3416
3417 det = n11 * t11 + n21 * t12 + n31 * t13;
3418
3419 if ( det === 0 ) {
3420
3421 var msg = "THREE.Matrix3: .getInverse() can't invert matrix, determinant is 0";
3422
3423 if ( throwOnDegenerate === true ) {
3424
3425 throw new Error( msg );
3426
3427 } else {
3428
3429 console.warn( msg );
3430
3431 }
3432
3433 return this.identity();
3434
3435 }
3436
3437 var detInv = 1 / det;
3438
3439 te[ 0 ] = t11 * detInv;
3440 te[ 1 ] = ( n31 * n23 - n33 * n21 ) * detInv;
3441 te[ 2 ] = ( n32 * n21 - n31 * n22 ) * detInv;
3442
3443 te[ 3 ] = t12 * detInv;
3444 te[ 4 ] = ( n33 * n11 - n31 * n13 ) * detInv;
3445 te[ 5 ] = ( n31 * n12 - n32 * n11 ) * detInv;
3446
3447 te[ 6 ] = t13 * detInv;
3448 te[ 7 ] = ( n21 * n13 - n23 * n11 ) * detInv;
3449 te[ 8 ] = ( n22 * n11 - n21 * n12 ) * detInv;
3450
3451 return this;
3452
3453 },
3454
3455 transpose: function () {
3456
3457 var tmp, m = this.elements;
3458
3459 tmp = m[ 1 ]; m[ 1 ] = m[ 3 ]; m[ 3 ] = tmp;
3460 tmp = m[ 2 ]; m[ 2 ] = m[ 6 ]; m[ 6 ] = tmp;
3461 tmp = m[ 5 ]; m[ 5 ] = m[ 7 ]; m[ 7 ] = tmp;
3462
3463 return this;
3464
3465 },
3466
3467 getNormalMatrix: function ( matrix4 ) {
3468
3469 return this.setFromMatrix4( matrix4 ).getInverse( this ).transpose();
3470
3471 },
3472
3473 transposeIntoArray: function ( r ) {
3474
3475 var m = this.elements;
3476
3477 r[ 0 ] = m[ 0 ];
3478 r[ 1 ] = m[ 3 ];
3479 r[ 2 ] = m[ 6 ];
3480 r[ 3 ] = m[ 1 ];
3481 r[ 4 ] = m[ 4 ];
3482 r[ 5 ] = m[ 7 ];
3483 r[ 6 ] = m[ 2 ];
3484 r[ 7 ] = m[ 5 ];
3485 r[ 8 ] = m[ 8 ];
3486
3487 return this;
3488
3489 },
3490
3491 setUvTransform: function ( tx, ty, sx, sy, rotation, cx, cy ) {
3492
3493 var c = Math.cos( rotation );
3494 var s = Math.sin( rotation );
3495
3496 this.set(
3497 sx * c, sx * s, - sx * ( c * cx + s * cy ) + cx + tx,
3498 - sy * s, sy * c, - sy * ( - s * cx + c * cy ) + cy + ty,
3499 0, 0, 1
3500 );
3501
3502 },
3503
3504 scale: function ( sx, sy ) {
3505
3506 var te = this.elements;
3507
3508 te[ 0 ] *= sx; te[ 3 ] *= sx; te[ 6 ] *= sx;
3509 te[ 1 ] *= sy; te[ 4 ] *= sy; te[ 7 ] *= sy;
3510
3511 return this;
3512
3513 },
3514
3515 rotate: function ( theta ) {
3516
3517 var c = Math.cos( theta );
3518 var s = Math.sin( theta );
3519
3520 var te = this.elements;
3521
3522 var a11 = te[ 0 ], a12 = te[ 3 ], a13 = te[ 6 ];
3523 var a21 = te[ 1 ], a22 = te[ 4 ], a23 = te[ 7 ];
3524
3525 te[ 0 ] = c * a11 + s * a21;
3526 te[ 3 ] = c * a12 + s * a22;
3527 te[ 6 ] = c * a13 + s * a23;
3528
3529 te[ 1 ] = - s * a11 + c * a21;
3530 te[ 4 ] = - s * a12 + c * a22;
3531 te[ 7 ] = - s * a13 + c * a23;
3532
3533 return this;
3534
3535 },
3536
3537 translate: function ( tx, ty ) {
3538
3539 var te = this.elements;
3540
3541 te[ 0 ] += tx * te[ 2 ]; te[ 3 ] += tx * te[ 5 ]; te[ 6 ] += tx * te[ 8 ];
3542 te[ 1 ] += ty * te[ 2 ]; te[ 4 ] += ty * te[ 5 ]; te[ 7 ] += ty * te[ 8 ];
3543
3544 return this;
3545
3546 },
3547
3548 equals: function ( matrix ) {
3549
3550 var te = this.elements;
3551 var me = matrix.elements;
3552
3553 for ( var i = 0; i < 9; i ++ ) {
3554
3555 if ( te[ i ] !== me[ i ] ) return false;
3556
3557 }
3558
3559 return true;
3560
3561 },
3562
3563 fromArray: function ( array, offset ) {
3564
3565 if ( offset === undefined ) offset = 0;
3566
3567 for ( var i = 0; i < 9; i ++ ) {
3568
3569 this.elements[ i ] = array[ i + offset ];
3570
3571 }
3572
3573 return this;
3574
3575 },
3576
3577 toArray: function ( array, offset ) {
3578
3579 if ( array === undefined ) array = [];
3580 if ( offset === undefined ) offset = 0;
3581
3582 var te = this.elements;
3583
3584 array[ offset ] = te[ 0 ];
3585 array[ offset + 1 ] = te[ 1 ];
3586 array[ offset + 2 ] = te[ 2 ];
3587
3588 array[ offset + 3 ] = te[ 3 ];
3589 array[ offset + 4 ] = te[ 4 ];
3590 array[ offset + 5 ] = te[ 5 ];
3591
3592 array[ offset + 6 ] = te[ 6 ];
3593 array[ offset + 7 ] = te[ 7 ];
3594 array[ offset + 8 ] = te[ 8 ];
3595
3596 return array;
3597
3598 }
3599
3600} );
3601
3602/**
3603 * @author mrdoob / http://mrdoob.com/
3604 * @author alteredq / http://alteredqualia.com/
3605 * @author szimek / https://github.com/szimek/
3606 */
3607
3608var textureId = 0;
3609
3610function Texture( image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) {
3611
3612 Object.defineProperty( this, 'id', { value: textureId ++ } );
3613
3614 this.uuid = _Math.generateUUID();
3615
3616 this.name = '';
3617
3618 this.image = image !== undefined ? image : Texture.DEFAULT_IMAGE;
3619 this.mipmaps = [];
3620
3621 this.mapping = mapping !== undefined ? mapping : Texture.DEFAULT_MAPPING;
3622
3623 this.wrapS = wrapS !== undefined ? wrapS : ClampToEdgeWrapping;
3624 this.wrapT = wrapT !== undefined ? wrapT : ClampToEdgeWrapping;
3625
3626 this.magFilter = magFilter !== undefined ? magFilter : LinearFilter;
3627 this.minFilter = minFilter !== undefined ? minFilter : LinearMipMapLinearFilter;
3628
3629 this.anisotropy = anisotropy !== undefined ? anisotropy : 1;
3630
3631 this.format = format !== undefined ? format : RGBAFormat;
3632 this.type = type !== undefined ? type : UnsignedByteType;
3633
3634 this.offset = new Vector2( 0, 0 );
3635 this.repeat = new Vector2( 1, 1 );
3636 this.center = new Vector2( 0, 0 );
3637 this.rotation = 0;
3638
3639 this.matrixAutoUpdate = true;
3640 this.matrix = new Matrix3();
3641
3642 this.generateMipmaps = true;
3643 this.premultiplyAlpha = false;
3644 this.flipY = true;
3645 this.unpackAlignment = 4; // valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml)
3646
3647 // Values of encoding !== THREE.LinearEncoding only supported on map, envMap and emissiveMap.
3648 //
3649 // Also changing the encoding after already used by a Material will not automatically make the Material
3650 // update. You need to explicitly call Material.needsUpdate to trigger it to recompile.
3651 this.encoding = encoding !== undefined ? encoding : LinearEncoding;
3652
3653 this.version = 0;
3654 this.onUpdate = null;
3655
3656}
3657
3658Texture.DEFAULT_IMAGE = undefined;
3659Texture.DEFAULT_MAPPING = UVMapping;
3660
3661Texture.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
3662
3663 constructor: Texture,
3664
3665 isTexture: true,
3666
3667 updateMatrix: function () {
3668
3669 this.matrix.setUvTransform( this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y );
3670
3671 },
3672
3673 clone: function () {
3674
3675 return new this.constructor().copy( this );
3676
3677 },
3678
3679 copy: function ( source ) {
3680
3681 this.name = source.name;
3682
3683 this.image = source.image;
3684 this.mipmaps = source.mipmaps.slice( 0 );
3685
3686 this.mapping = source.mapping;
3687
3688 this.wrapS = source.wrapS;
3689 this.wrapT = source.wrapT;
3690
3691 this.magFilter = source.magFilter;
3692 this.minFilter = source.minFilter;
3693
3694 this.anisotropy = source.anisotropy;
3695
3696 this.format = source.format;
3697 this.type = source.type;
3698
3699 this.offset.copy( source.offset );
3700 this.repeat.copy( source.repeat );
3701 this.center.copy( source.center );
3702 this.rotation = source.rotation;
3703
3704 this.matrixAutoUpdate = source.matrixAutoUpdate;
3705 this.matrix.copy( source.matrix );
3706
3707 this.generateMipmaps = source.generateMipmaps;
3708 this.premultiplyAlpha = source.premultiplyAlpha;
3709 this.flipY = source.flipY;
3710 this.unpackAlignment = source.unpackAlignment;
3711 this.encoding = source.encoding;
3712
3713 return this;
3714
3715 },
3716
3717 toJSON: function ( meta ) {
3718
3719 var isRootObject = ( meta === undefined || typeof meta === 'string' );
3720
3721 if ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) {
3722
3723 return meta.textures[ this.uuid ];
3724
3725 }
3726
3727 function getDataURL( image ) {
3728
3729 var canvas;
3730
3731 if ( image instanceof HTMLCanvasElement ) {
3732
3733 canvas = image;
3734
3735 } else {
3736
3737 canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
3738 canvas.width = image.width;
3739 canvas.height = image.height;
3740
3741 var context = canvas.getContext( '2d' );
3742
3743 if ( image instanceof ImageData ) {
3744
3745 context.putImageData( image, 0, 0 );
3746
3747 } else {
3748
3749 context.drawImage( image, 0, 0, image.width, image.height );
3750
3751 }
3752
3753 }
3754
3755 if ( canvas.width > 2048 || canvas.height > 2048 ) {
3756
3757 return canvas.toDataURL( 'image/jpeg', 0.6 );
3758
3759 } else {
3760
3761 return canvas.toDataURL( 'image/png' );
3762
3763 }
3764
3765 }
3766
3767 var output = {
3768
3769 metadata: {
3770 version: 4.5,
3771 type: 'Texture',
3772 generator: 'Texture.toJSON'
3773 },
3774
3775 uuid: this.uuid,
3776 name: this.name,
3777
3778 mapping: this.mapping,
3779
3780 repeat: [ this.repeat.x, this.repeat.y ],
3781 offset: [ this.offset.x, this.offset.y ],
3782 center: [ this.center.x, this.center.y ],
3783 rotation: this.rotation,
3784
3785 wrap: [ this.wrapS, this.wrapT ],
3786
3787 format: this.format,
3788 minFilter: this.minFilter,
3789 magFilter: this.magFilter,
3790 anisotropy: this.anisotropy,
3791
3792 flipY: this.flipY
3793
3794 };
3795
3796 if ( this.image !== undefined ) {
3797
3798 // TODO: Move to THREE.Image
3799
3800 var image = this.image;
3801
3802 if ( image.uuid === undefined ) {
3803
3804 image.uuid = _Math.generateUUID(); // UGH
3805
3806 }
3807
3808 if ( ! isRootObject && meta.images[ image.uuid ] === undefined ) {
3809
3810 meta.images[ image.uuid ] = {
3811 uuid: image.uuid,
3812 url: getDataURL( image )
3813 };
3814
3815 }
3816
3817 output.image = image.uuid;
3818
3819 }
3820
3821 if ( ! isRootObject ) {
3822
3823 meta.textures[ this.uuid ] = output;
3824
3825 }
3826
3827 return output;
3828
3829 },
3830
3831 dispose: function () {
3832
3833 this.dispatchEvent( { type: 'dispose' } );
3834
3835 },
3836
3837 transformUv: function ( uv ) {
3838
3839 if ( this.mapping !== UVMapping ) return;
3840
3841 uv.applyMatrix3( this.matrix );
3842
3843 if ( uv.x < 0 || uv.x > 1 ) {
3844
3845 switch ( this.wrapS ) {
3846
3847 case RepeatWrapping:
3848
3849 uv.x = uv.x - Math.floor( uv.x );
3850 break;
3851
3852 case ClampToEdgeWrapping:
3853
3854 uv.x = uv.x < 0 ? 0 : 1;
3855 break;
3856
3857 case MirroredRepeatWrapping:
3858
3859 if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) {
3860
3861 uv.x = Math.ceil( uv.x ) - uv.x;
3862
3863 } else {
3864
3865 uv.x = uv.x - Math.floor( uv.x );
3866
3867 }
3868 break;
3869
3870 }
3871
3872 }
3873
3874 if ( uv.y < 0 || uv.y > 1 ) {
3875
3876 switch ( this.wrapT ) {
3877
3878 case RepeatWrapping:
3879
3880 uv.y = uv.y - Math.floor( uv.y );
3881 break;
3882
3883 case ClampToEdgeWrapping:
3884
3885 uv.y = uv.y < 0 ? 0 : 1;
3886 break;
3887
3888 case MirroredRepeatWrapping:
3889
3890 if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) {
3891
3892 uv.y = Math.ceil( uv.y ) - uv.y;
3893
3894 } else {
3895
3896 uv.y = uv.y - Math.floor( uv.y );
3897
3898 }
3899 break;
3900
3901 }
3902
3903 }
3904
3905 if ( this.flipY ) {
3906
3907 uv.y = 1 - uv.y;
3908
3909 }
3910
3911 }
3912
3913} );
3914
3915Object.defineProperty( Texture.prototype, "needsUpdate", {
3916
3917 set: function ( value ) {
3918
3919 if ( value === true ) this.version ++;
3920
3921 }
3922
3923} );
3924
3925/**
3926 * @author supereggbert / http://www.paulbrunt.co.uk/
3927 * @author philogb / http://blog.thejit.org/
3928 * @author mikael emtinger / http://gomo.se/
3929 * @author egraether / http://egraether.com/
3930 * @author WestLangley / http://github.com/WestLangley
3931 */
3932
3933function Vector4( x, y, z, w ) {
3934
3935 this.x = x || 0;
3936 this.y = y || 0;
3937 this.z = z || 0;
3938 this.w = ( w !== undefined ) ? w : 1;
3939
3940}
3941
3942Object.assign( Vector4.prototype, {
3943
3944 isVector4: true,
3945
3946 set: function ( x, y, z, w ) {
3947
3948 this.x = x;
3949 this.y = y;
3950 this.z = z;
3951 this.w = w;
3952
3953 return this;
3954
3955 },
3956
3957 setScalar: function ( scalar ) {
3958
3959 this.x = scalar;
3960 this.y = scalar;
3961 this.z = scalar;
3962 this.w = scalar;
3963
3964 return this;
3965
3966 },
3967
3968 setX: function ( x ) {
3969
3970 this.x = x;
3971
3972 return this;
3973
3974 },
3975
3976 setY: function ( y ) {
3977
3978 this.y = y;
3979
3980 return this;
3981
3982 },
3983
3984 setZ: function ( z ) {
3985
3986 this.z = z;
3987
3988 return this;
3989
3990 },
3991
3992 setW: function ( w ) {
3993
3994 this.w = w;
3995
3996 return this;
3997
3998 },
3999
4000 setComponent: function ( index, value ) {
4001
4002 switch ( index ) {
4003
4004 case 0: this.x = value; break;
4005 case 1: this.y = value; break;
4006 case 2: this.z = value; break;
4007 case 3: this.w = value; break;
4008 default: throw new Error( 'index is out of range: ' + index );
4009
4010 }
4011
4012 return this;
4013
4014 },
4015
4016 getComponent: function ( index ) {
4017
4018 switch ( index ) {
4019
4020 case 0: return this.x;
4021 case 1: return this.y;
4022 case 2: return this.z;
4023 case 3: return this.w;
4024 default: throw new Error( 'index is out of range: ' + index );
4025
4026 }
4027
4028 },
4029
4030 clone: function () {
4031
4032 return new this.constructor( this.x, this.y, this.z, this.w );
4033
4034 },
4035
4036 copy: function ( v ) {
4037
4038 this.x = v.x;
4039 this.y = v.y;
4040 this.z = v.z;
4041 this.w = ( v.w !== undefined ) ? v.w : 1;
4042
4043 return this;
4044
4045 },
4046
4047 add: function ( v, w ) {
4048
4049 if ( w !== undefined ) {
4050
4051 console.warn( 'THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
4052 return this.addVectors( v, w );
4053
4054 }
4055
4056 this.x += v.x;
4057 this.y += v.y;
4058 this.z += v.z;
4059 this.w += v.w;
4060
4061 return this;
4062
4063 },
4064
4065 addScalar: function ( s ) {
4066
4067 this.x += s;
4068 this.y += s;
4069 this.z += s;
4070 this.w += s;
4071
4072 return this;
4073
4074 },
4075
4076 addVectors: function ( a, b ) {
4077
4078 this.x = a.x + b.x;
4079 this.y = a.y + b.y;
4080 this.z = a.z + b.z;
4081 this.w = a.w + b.w;
4082
4083 return this;
4084
4085 },
4086
4087 addScaledVector: function ( v, s ) {
4088
4089 this.x += v.x * s;
4090 this.y += v.y * s;
4091 this.z += v.z * s;
4092 this.w += v.w * s;
4093
4094 return this;
4095
4096 },
4097
4098 sub: function ( v, w ) {
4099
4100 if ( w !== undefined ) {
4101
4102 console.warn( 'THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
4103 return this.subVectors( v, w );
4104
4105 }
4106
4107 this.x -= v.x;
4108 this.y -= v.y;
4109 this.z -= v.z;
4110 this.w -= v.w;
4111
4112 return this;
4113
4114 },
4115
4116 subScalar: function ( s ) {
4117
4118 this.x -= s;
4119 this.y -= s;
4120 this.z -= s;
4121 this.w -= s;
4122
4123 return this;
4124
4125 },
4126
4127 subVectors: function ( a, b ) {
4128
4129 this.x = a.x - b.x;
4130 this.y = a.y - b.y;
4131 this.z = a.z - b.z;
4132 this.w = a.w - b.w;
4133
4134 return this;
4135
4136 },
4137
4138 multiplyScalar: function ( scalar ) {
4139
4140 this.x *= scalar;
4141 this.y *= scalar;
4142 this.z *= scalar;
4143 this.w *= scalar;
4144
4145 return this;
4146
4147 },
4148
4149 applyMatrix4: function ( m ) {
4150
4151 var x = this.x, y = this.y, z = this.z, w = this.w;
4152 var e = m.elements;
4153
4154 this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w;
4155 this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w;
4156 this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w;
4157 this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w;
4158
4159 return this;
4160
4161 },
4162
4163 divideScalar: function ( scalar ) {
4164
4165 return this.multiplyScalar( 1 / scalar );
4166
4167 },
4168
4169 setAxisAngleFromQuaternion: function ( q ) {
4170
4171 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm
4172
4173 // q is assumed to be normalized
4174
4175 this.w = 2 * Math.acos( q.w );
4176
4177 var s = Math.sqrt( 1 - q.w * q.w );
4178
4179 if ( s < 0.0001 ) {
4180
4181 this.x = 1;
4182 this.y = 0;
4183 this.z = 0;
4184
4185 } else {
4186
4187 this.x = q.x / s;
4188 this.y = q.y / s;
4189 this.z = q.z / s;
4190
4191 }
4192
4193 return this;
4194
4195 },
4196
4197 setAxisAngleFromRotationMatrix: function ( m ) {
4198
4199 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm
4200
4201 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
4202
4203 var angle, x, y, z, // variables for result
4204 epsilon = 0.01, // margin to allow for rounding errors
4205 epsilon2 = 0.1, // margin to distinguish between 0 and 180 degrees
4206
4207 te = m.elements,
4208
4209 m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
4210 m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
4211 m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
4212
4213 if ( ( Math.abs( m12 - m21 ) < epsilon ) &&
4214 ( Math.abs( m13 - m31 ) < epsilon ) &&
4215 ( Math.abs( m23 - m32 ) < epsilon ) ) {
4216
4217 // singularity found
4218 // first check for identity matrix which must have +1 for all terms
4219 // in leading diagonal and zero in other terms
4220
4221 if ( ( Math.abs( m12 + m21 ) < epsilon2 ) &&
4222 ( Math.abs( m13 + m31 ) < epsilon2 ) &&
4223 ( Math.abs( m23 + m32 ) < epsilon2 ) &&
4224 ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) {
4225
4226 // this singularity is identity matrix so angle = 0
4227
4228 this.set( 1, 0, 0, 0 );
4229
4230 return this; // zero angle, arbitrary axis
4231
4232 }
4233
4234 // otherwise this singularity is angle = 180
4235
4236 angle = Math.PI;
4237
4238 var xx = ( m11 + 1 ) / 2;
4239 var yy = ( m22 + 1 ) / 2;
4240 var zz = ( m33 + 1 ) / 2;
4241 var xy = ( m12 + m21 ) / 4;
4242 var xz = ( m13 + m31 ) / 4;
4243 var yz = ( m23 + m32 ) / 4;
4244
4245 if ( ( xx > yy ) && ( xx > zz ) ) {
4246
4247 // m11 is the largest diagonal term
4248
4249 if ( xx < epsilon ) {
4250
4251 x = 0;
4252 y = 0.707106781;
4253 z = 0.707106781;
4254
4255 } else {
4256
4257 x = Math.sqrt( xx );
4258 y = xy / x;
4259 z = xz / x;
4260
4261 }
4262
4263 } else if ( yy > zz ) {
4264
4265 // m22 is the largest diagonal term
4266
4267 if ( yy < epsilon ) {
4268
4269 x = 0.707106781;
4270 y = 0;
4271 z = 0.707106781;
4272
4273 } else {
4274
4275 y = Math.sqrt( yy );
4276 x = xy / y;
4277 z = yz / y;
4278
4279 }
4280
4281 } else {
4282
4283 // m33 is the largest diagonal term so base result on this
4284
4285 if ( zz < epsilon ) {
4286
4287 x = 0.707106781;
4288 y = 0.707106781;
4289 z = 0;
4290
4291 } else {
4292
4293 z = Math.sqrt( zz );
4294 x = xz / z;
4295 y = yz / z;
4296
4297 }
4298
4299 }
4300
4301 this.set( x, y, z, angle );
4302
4303 return this; // return 180 deg rotation
4304
4305 }
4306
4307 // as we have reached here there are no singularities so we can handle normally
4308
4309 var s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) +
4310 ( m13 - m31 ) * ( m13 - m31 ) +
4311 ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize
4312
4313 if ( Math.abs( s ) < 0.001 ) s = 1;
4314
4315 // prevent divide by zero, should not happen if matrix is orthogonal and should be
4316 // caught by singularity test above, but I've left it in just in case
4317
4318 this.x = ( m32 - m23 ) / s;
4319 this.y = ( m13 - m31 ) / s;
4320 this.z = ( m21 - m12 ) / s;
4321 this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 );
4322
4323 return this;
4324
4325 },
4326
4327 min: function ( v ) {
4328
4329 this.x = Math.min( this.x, v.x );
4330 this.y = Math.min( this.y, v.y );
4331 this.z = Math.min( this.z, v.z );
4332 this.w = Math.min( this.w, v.w );
4333
4334 return this;
4335
4336 },
4337
4338 max: function ( v ) {
4339
4340 this.x = Math.max( this.x, v.x );
4341 this.y = Math.max( this.y, v.y );
4342 this.z = Math.max( this.z, v.z );
4343 this.w = Math.max( this.w, v.w );
4344
4345 return this;
4346
4347 },
4348
4349 clamp: function ( min, max ) {
4350
4351 // assumes min < max, componentwise
4352
4353 this.x = Math.max( min.x, Math.min( max.x, this.x ) );
4354 this.y = Math.max( min.y, Math.min( max.y, this.y ) );
4355 this.z = Math.max( min.z, Math.min( max.z, this.z ) );
4356 this.w = Math.max( min.w, Math.min( max.w, this.w ) );
4357
4358 return this;
4359
4360 },
4361
4362 clampScalar: function () {
4363
4364 var min, max;
4365
4366 return function clampScalar( minVal, maxVal ) {
4367
4368 if ( min === undefined ) {
4369
4370 min = new Vector4();
4371 max = new Vector4();
4372
4373 }
4374
4375 min.set( minVal, minVal, minVal, minVal );
4376 max.set( maxVal, maxVal, maxVal, maxVal );
4377
4378 return this.clamp( min, max );
4379
4380 };
4381
4382 }(),
4383
4384 clampLength: function ( min, max ) {
4385
4386 var length = this.length();
4387
4388 return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
4389
4390 },
4391
4392 floor: function () {
4393
4394 this.x = Math.floor( this.x );
4395 this.y = Math.floor( this.y );
4396 this.z = Math.floor( this.z );
4397 this.w = Math.floor( this.w );
4398
4399 return this;
4400
4401 },
4402
4403 ceil: function () {
4404
4405 this.x = Math.ceil( this.x );
4406 this.y = Math.ceil( this.y );
4407 this.z = Math.ceil( this.z );
4408 this.w = Math.ceil( this.w );
4409
4410 return this;
4411
4412 },
4413
4414 round: function () {
4415
4416 this.x = Math.round( this.x );
4417 this.y = Math.round( this.y );
4418 this.z = Math.round( this.z );
4419 this.w = Math.round( this.w );
4420
4421 return this;
4422
4423 },
4424
4425 roundToZero: function () {
4426
4427 this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
4428 this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
4429 this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );
4430 this.w = ( this.w < 0 ) ? Math.ceil( this.w ) : Math.floor( this.w );
4431
4432 return this;
4433
4434 },
4435
4436 negate: function () {
4437
4438 this.x = - this.x;
4439 this.y = - this.y;
4440 this.z = - this.z;
4441 this.w = - this.w;
4442
4443 return this;
4444
4445 },
4446
4447 dot: function ( v ) {
4448
4449 return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;
4450
4451 },
4452
4453 lengthSq: function () {
4454
4455 return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
4456
4457 },
4458
4459 length: function () {
4460
4461 return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w );
4462
4463 },
4464
4465 manhattanLength: function () {
4466
4467 return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w );
4468
4469 },
4470
4471 normalize: function () {
4472
4473 return this.divideScalar( this.length() || 1 );
4474
4475 },
4476
4477 setLength: function ( length ) {
4478
4479 return this.normalize().multiplyScalar( length );
4480
4481 },
4482
4483 lerp: function ( v, alpha ) {
4484
4485 this.x += ( v.x - this.x ) * alpha;
4486 this.y += ( v.y - this.y ) * alpha;
4487 this.z += ( v.z - this.z ) * alpha;
4488 this.w += ( v.w - this.w ) * alpha;
4489
4490 return this;
4491
4492 },
4493
4494 lerpVectors: function ( v1, v2, alpha ) {
4495
4496 return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );
4497
4498 },
4499
4500 equals: function ( v ) {
4501
4502 return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) );
4503
4504 },
4505
4506 fromArray: function ( array, offset ) {
4507
4508 if ( offset === undefined ) offset = 0;
4509
4510 this.x = array[ offset ];
4511 this.y = array[ offset + 1 ];
4512 this.z = array[ offset + 2 ];
4513 this.w = array[ offset + 3 ];
4514
4515 return this;
4516
4517 },
4518
4519 toArray: function ( array, offset ) {
4520
4521 if ( array === undefined ) array = [];
4522 if ( offset === undefined ) offset = 0;
4523
4524 array[ offset ] = this.x;
4525 array[ offset + 1 ] = this.y;
4526 array[ offset + 2 ] = this.z;
4527 array[ offset + 3 ] = this.w;
4528
4529 return array;
4530
4531 },
4532
4533 fromBufferAttribute: function ( attribute, index, offset ) {
4534
4535 if ( offset !== undefined ) {
4536
4537 console.warn( 'THREE.Vector4: offset has been removed from .fromBufferAttribute().' );
4538
4539 }
4540
4541 this.x = attribute.getX( index );
4542 this.y = attribute.getY( index );
4543 this.z = attribute.getZ( index );
4544 this.w = attribute.getW( index );
4545
4546 return this;
4547
4548 }
4549
4550} );
4551
4552/**
4553 * @author szimek / https://github.com/szimek/
4554 * @author alteredq / http://alteredqualia.com/
4555 * @author Marius Kintel / https://github.com/kintel
4556 */
4557
4558/*
4559 In options, we can specify:
4560 * Texture parameters for an auto-generated target texture
4561 * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers
4562*/
4563function WebGLRenderTarget( width, height, options ) {
4564
4565 this.width = width;
4566 this.height = height;
4567
4568 this.scissor = new Vector4( 0, 0, width, height );
4569 this.scissorTest = false;
4570
4571 this.viewport = new Vector4( 0, 0, width, height );
4572
4573 options = options || {};
4574
4575 if ( options.minFilter === undefined ) options.minFilter = LinearFilter;
4576
4577 this.texture = new Texture( undefined, undefined, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding );
4578
4579 this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true;
4580 this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : true;
4581 this.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null;
4582
4583}
4584
4585WebGLRenderTarget.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
4586
4587 constructor: WebGLRenderTarget,
4588
4589 isWebGLRenderTarget: true,
4590
4591 setSize: function ( width, height ) {
4592
4593 if ( this.width !== width || this.height !== height ) {
4594
4595 this.width = width;
4596 this.height = height;
4597
4598 this.dispose();
4599
4600 }
4601
4602 this.viewport.set( 0, 0, width, height );
4603 this.scissor.set( 0, 0, width, height );
4604
4605 },
4606
4607 clone: function () {
4608
4609 return new this.constructor().copy( this );
4610
4611 },
4612
4613 copy: function ( source ) {
4614
4615 this.width = source.width;
4616 this.height = source.height;
4617
4618 this.viewport.copy( source.viewport );
4619
4620 this.texture = source.texture.clone();
4621
4622 this.depthBuffer = source.depthBuffer;
4623 this.stencilBuffer = source.stencilBuffer;
4624 this.depthTexture = source.depthTexture;
4625
4626 return this;
4627
4628 },
4629
4630 dispose: function () {
4631
4632 this.dispatchEvent( { type: 'dispose' } );
4633
4634 }
4635
4636} );
4637
4638/**
4639 * @author alteredq / http://alteredqualia.com
4640 */
4641
4642function WebGLRenderTargetCube( width, height, options ) {
4643
4644 WebGLRenderTarget.call( this, width, height, options );
4645
4646 this.activeCubeFace = 0; // PX 0, NX 1, PY 2, NY 3, PZ 4, NZ 5
4647 this.activeMipMapLevel = 0;
4648
4649}
4650
4651WebGLRenderTargetCube.prototype = Object.create( WebGLRenderTarget.prototype );
4652WebGLRenderTargetCube.prototype.constructor = WebGLRenderTargetCube;
4653
4654WebGLRenderTargetCube.prototype.isWebGLRenderTargetCube = true;
4655
4656/**
4657 * @author alteredq / http://alteredqualia.com/
4658 */
4659
4660function DataTexture( data, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) {
4661
4662 Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
4663
4664 this.image = { data: data, width: width, height: height };
4665
4666 this.magFilter = magFilter !== undefined ? magFilter : NearestFilter;
4667 this.minFilter = minFilter !== undefined ? minFilter : NearestFilter;
4668
4669 this.generateMipmaps = false;
4670 this.flipY = false;
4671 this.unpackAlignment = 1;
4672
4673}
4674
4675DataTexture.prototype = Object.create( Texture.prototype );
4676DataTexture.prototype.constructor = DataTexture;
4677
4678DataTexture.prototype.isDataTexture = true;
4679
4680/**
4681 * @author bhouston / http://clara.io
4682 * @author WestLangley / http://github.com/WestLangley
4683 */
4684
4685function Box3( min, max ) {
4686
4687 this.min = ( min !== undefined ) ? min : new Vector3( + Infinity, + Infinity, + Infinity );
4688 this.max = ( max !== undefined ) ? max : new Vector3( - Infinity, - Infinity, - Infinity );
4689
4690}
4691
4692Object.assign( Box3.prototype, {
4693
4694 isBox3: true,
4695
4696 set: function ( min, max ) {
4697
4698 this.min.copy( min );
4699 this.max.copy( max );
4700
4701 return this;
4702
4703 },
4704
4705 setFromArray: function ( array ) {
4706
4707 var minX = + Infinity;
4708 var minY = + Infinity;
4709 var minZ = + Infinity;
4710
4711 var maxX = - Infinity;
4712 var maxY = - Infinity;
4713 var maxZ = - Infinity;
4714
4715 for ( var i = 0, l = array.length; i < l; i += 3 ) {
4716
4717 var x = array[ i ];
4718 var y = array[ i + 1 ];
4719 var z = array[ i + 2 ];
4720
4721 if ( x < minX ) minX = x;
4722 if ( y < minY ) minY = y;
4723 if ( z < minZ ) minZ = z;
4724
4725 if ( x > maxX ) maxX = x;
4726 if ( y > maxY ) maxY = y;
4727 if ( z > maxZ ) maxZ = z;
4728
4729 }
4730
4731 this.min.set( minX, minY, minZ );
4732 this.max.set( maxX, maxY, maxZ );
4733
4734 return this;
4735
4736 },
4737
4738 setFromBufferAttribute: function ( attribute ) {
4739
4740 var minX = + Infinity;
4741 var minY = + Infinity;
4742 var minZ = + Infinity;
4743
4744 var maxX = - Infinity;
4745 var maxY = - Infinity;
4746 var maxZ = - Infinity;
4747
4748 for ( var i = 0, l = attribute.count; i < l; i ++ ) {
4749
4750 var x = attribute.getX( i );
4751 var y = attribute.getY( i );
4752 var z = attribute.getZ( i );
4753
4754 if ( x < minX ) minX = x;
4755 if ( y < minY ) minY = y;
4756 if ( z < minZ ) minZ = z;
4757
4758 if ( x > maxX ) maxX = x;
4759 if ( y > maxY ) maxY = y;
4760 if ( z > maxZ ) maxZ = z;
4761
4762 }
4763
4764 this.min.set( minX, minY, minZ );
4765 this.max.set( maxX, maxY, maxZ );
4766
4767 return this;
4768
4769 },
4770
4771 setFromPoints: function ( points ) {
4772
4773 this.makeEmpty();
4774
4775 for ( var i = 0, il = points.length; i < il; i ++ ) {
4776
4777 this.expandByPoint( points[ i ] );
4778
4779 }
4780
4781 return this;
4782
4783 },
4784
4785 setFromCenterAndSize: function () {
4786
4787 var v1 = new Vector3();
4788
4789 return function setFromCenterAndSize( center, size ) {
4790
4791 var halfSize = v1.copy( size ).multiplyScalar( 0.5 );
4792
4793 this.min.copy( center ).sub( halfSize );
4794 this.max.copy( center ).add( halfSize );
4795
4796 return this;
4797
4798 };
4799
4800 }(),
4801
4802 setFromObject: function ( object ) {
4803
4804 this.makeEmpty();
4805
4806 return this.expandByObject( object );
4807
4808 },
4809
4810 clone: function () {
4811
4812 return new this.constructor().copy( this );
4813
4814 },
4815
4816 copy: function ( box ) {
4817
4818 this.min.copy( box.min );
4819 this.max.copy( box.max );
4820
4821 return this;
4822
4823 },
4824
4825 makeEmpty: function () {
4826
4827 this.min.x = this.min.y = this.min.z = + Infinity;
4828 this.max.x = this.max.y = this.max.z = - Infinity;
4829
4830 return this;
4831
4832 },
4833
4834 isEmpty: function () {
4835
4836 // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
4837
4838 return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ) || ( this.max.z < this.min.z );
4839
4840 },
4841
4842 getCenter: function ( target ) {
4843
4844 if ( target === undefined ) {
4845
4846 console.warn( 'THREE.Box3: .getCenter() target is now required' );
4847 target = new Vector3();
4848
4849 }
4850
4851 return this.isEmpty() ? target.set( 0, 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 );
4852
4853 },
4854
4855 getSize: function ( target ) {
4856
4857 if ( target === undefined ) {
4858
4859 console.warn( 'THREE.Box3: .getSize() target is now required' );
4860 target = new Vector3();
4861
4862 }
4863
4864 return this.isEmpty() ? target.set( 0, 0, 0 ) : target.subVectors( this.max, this.min );
4865
4866 },
4867
4868 expandByPoint: function ( point ) {
4869
4870 this.min.min( point );
4871 this.max.max( point );
4872
4873 return this;
4874
4875 },
4876
4877 expandByVector: function ( vector ) {
4878
4879 this.min.sub( vector );
4880 this.max.add( vector );
4881
4882 return this;
4883
4884 },
4885
4886 expandByScalar: function ( scalar ) {
4887
4888 this.min.addScalar( - scalar );
4889 this.max.addScalar( scalar );
4890
4891 return this;
4892
4893 },
4894
4895 expandByObject: function () {
4896
4897 // Computes the world-axis-aligned bounding box of an object (including its children),
4898 // accounting for both the object's, and children's, world transforms
4899
4900 var scope, i, l;
4901
4902 var v1 = new Vector3();
4903
4904 function traverse( node ) {
4905
4906 var geometry = node.geometry;
4907
4908 if ( geometry !== undefined ) {
4909
4910 if ( geometry.isGeometry ) {
4911
4912 var vertices = geometry.vertices;
4913
4914 for ( i = 0, l = vertices.length; i < l; i ++ ) {
4915
4916 v1.copy( vertices[ i ] );
4917 v1.applyMatrix4( node.matrixWorld );
4918
4919 scope.expandByPoint( v1 );
4920
4921 }
4922
4923 } else if ( geometry.isBufferGeometry ) {
4924
4925 var attribute = geometry.attributes.position;
4926
4927 if ( attribute !== undefined ) {
4928
4929 for ( i = 0, l = attribute.count; i < l; i ++ ) {
4930
4931 v1.fromBufferAttribute( attribute, i ).applyMatrix4( node.matrixWorld );
4932
4933 scope.expandByPoint( v1 );
4934
4935 }
4936
4937 }
4938
4939 }
4940
4941 }
4942
4943 }
4944
4945 return function expandByObject( object ) {
4946
4947 scope = this;
4948
4949 object.updateMatrixWorld( true );
4950
4951 object.traverse( traverse );
4952
4953 return this;
4954
4955 };
4956
4957 }(),
4958
4959 containsPoint: function ( point ) {
4960
4961 return point.x < this.min.x || point.x > this.max.x ||
4962 point.y < this.min.y || point.y > this.max.y ||
4963 point.z < this.min.z || point.z > this.max.z ? false : true;
4964
4965 },
4966
4967 containsBox: function ( box ) {
4968
4969 return this.min.x <= box.min.x && box.max.x <= this.max.x &&
4970 this.min.y <= box.min.y && box.max.y <= this.max.y &&
4971 this.min.z <= box.min.z && box.max.z <= this.max.z;
4972
4973 },
4974
4975 getParameter: function ( point, target ) {
4976
4977 // This can potentially have a divide by zero if the box
4978 // has a size dimension of 0.
4979
4980 if ( target === undefined ) {
4981
4982 console.warn( 'THREE.Box3: .getParameter() target is now required' );
4983 target = new Vector3();
4984
4985 }
4986
4987 return target.set(
4988 ( point.x - this.min.x ) / ( this.max.x - this.min.x ),
4989 ( point.y - this.min.y ) / ( this.max.y - this.min.y ),
4990 ( point.z - this.min.z ) / ( this.max.z - this.min.z )
4991 );
4992
4993 },
4994
4995 intersectsBox: function ( box ) {
4996
4997 // using 6 splitting planes to rule out intersections.
4998 return box.max.x < this.min.x || box.min.x > this.max.x ||
4999 box.max.y < this.min.y || box.min.y > this.max.y ||
5000 box.max.z < this.min.z || box.min.z > this.max.z ? false : true;
5001
5002 },
5003
5004 intersectsSphere: ( function () {
5005
5006 var closestPoint = new Vector3();
5007
5008 return function intersectsSphere( sphere ) {
5009
5010 // Find the point on the AABB closest to the sphere center.
5011 this.clampPoint( sphere.center, closestPoint );
5012
5013 // If that point is inside the sphere, the AABB and sphere intersect.
5014 return closestPoint.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius );
5015
5016 };
5017
5018 } )(),
5019
5020 intersectsPlane: function ( plane ) {
5021
5022 // We compute the minimum and maximum dot product values. If those values
5023 // are on the same side (back or front) of the plane, then there is no intersection.
5024
5025 var min, max;
5026
5027 if ( plane.normal.x > 0 ) {
5028
5029 min = plane.normal.x * this.min.x;
5030 max = plane.normal.x * this.max.x;
5031
5032 } else {
5033
5034 min = plane.normal.x * this.max.x;
5035 max = plane.normal.x * this.min.x;
5036
5037 }
5038
5039 if ( plane.normal.y > 0 ) {
5040
5041 min += plane.normal.y * this.min.y;
5042 max += plane.normal.y * this.max.y;
5043
5044 } else {
5045
5046 min += plane.normal.y * this.max.y;
5047 max += plane.normal.y * this.min.y;
5048
5049 }
5050
5051 if ( plane.normal.z > 0 ) {
5052
5053 min += plane.normal.z * this.min.z;
5054 max += plane.normal.z * this.max.z;
5055
5056 } else {
5057
5058 min += plane.normal.z * this.max.z;
5059 max += plane.normal.z * this.min.z;
5060
5061 }
5062
5063 return ( min <= plane.constant && max >= plane.constant );
5064
5065 },
5066
5067 intersectsTriangle: ( function () {
5068
5069 // triangle centered vertices
5070 var v0 = new Vector3();
5071 var v1 = new Vector3();
5072 var v2 = new Vector3();
5073
5074 // triangle edge vectors
5075 var f0 = new Vector3();
5076 var f1 = new Vector3();
5077 var f2 = new Vector3();
5078
5079 var testAxis = new Vector3();
5080
5081 var center = new Vector3();
5082 var extents = new Vector3();
5083
5084 var triangleNormal = new Vector3();
5085
5086 function satForAxes( axes ) {
5087
5088 var i, j;
5089
5090 for ( i = 0, j = axes.length - 3; i <= j; i += 3 ) {
5091
5092 testAxis.fromArray( axes, i );
5093 // project the aabb onto the seperating axis
5094 var r = extents.x * Math.abs( testAxis.x ) + extents.y * Math.abs( testAxis.y ) + extents.z * Math.abs( testAxis.z );
5095 // project all 3 vertices of the triangle onto the seperating axis
5096 var p0 = v0.dot( testAxis );
5097 var p1 = v1.dot( testAxis );
5098 var p2 = v2.dot( testAxis );
5099 // actual test, basically see if either of the most extreme of the triangle points intersects r
5100 if ( Math.max( - Math.max( p0, p1, p2 ), Math.min( p0, p1, p2 ) ) > r ) {
5101
5102 // points of the projected triangle are outside the projected half-length of the aabb
5103 // the axis is seperating and we can exit
5104 return false;
5105
5106 }
5107
5108 }
5109
5110 return true;
5111
5112 }
5113
5114 return function intersectsTriangle( triangle ) {
5115
5116 if ( this.isEmpty() ) {
5117
5118 return false;
5119
5120 }
5121
5122 // compute box center and extents
5123 this.getCenter( center );
5124 extents.subVectors( this.max, center );
5125
5126 // translate triangle to aabb origin
5127 v0.subVectors( triangle.a, center );
5128 v1.subVectors( triangle.b, center );
5129 v2.subVectors( triangle.c, center );
5130
5131 // compute edge vectors for triangle
5132 f0.subVectors( v1, v0 );
5133 f1.subVectors( v2, v1 );
5134 f2.subVectors( v0, v2 );
5135
5136 // test against axes that are given by cross product combinations of the edges of the triangle and the edges of the aabb
5137 // 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
5138 // axis_ij = u_i x f_j (u0, u1, u2 = face normals of aabb = x,y,z axes vectors since aabb is axis aligned)
5139 var axes = [
5140 0, - f0.z, f0.y, 0, - f1.z, f1.y, 0, - f2.z, f2.y,
5141 f0.z, 0, - f0.x, f1.z, 0, - f1.x, f2.z, 0, - f2.x,
5142 - f0.y, f0.x, 0, - f1.y, f1.x, 0, - f2.y, f2.x, 0
5143 ];
5144 if ( ! satForAxes( axes ) ) {
5145
5146 return false;
5147
5148 }
5149
5150 // test 3 face normals from the aabb
5151 axes = [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ];
5152 if ( ! satForAxes( axes ) ) {
5153
5154 return false;
5155
5156 }
5157
5158 // finally testing the face normal of the triangle
5159 // use already existing triangle edge vectors here
5160 triangleNormal.crossVectors( f0, f1 );
5161 axes = [ triangleNormal.x, triangleNormal.y, triangleNormal.z ];
5162 return satForAxes( axes );
5163
5164 };
5165
5166 } )(),
5167
5168 clampPoint: function ( point, target ) {
5169
5170 if ( target === undefined ) {
5171
5172 console.warn( 'THREE.Box3: .clampPoint() target is now required' );
5173 target = new Vector3();
5174
5175 }
5176
5177 return target.copy( point ).clamp( this.min, this.max );
5178
5179 },
5180
5181 distanceToPoint: function () {
5182
5183 var v1 = new Vector3();
5184
5185 return function distanceToPoint( point ) {
5186
5187 var clampedPoint = v1.copy( point ).clamp( this.min, this.max );
5188 return clampedPoint.sub( point ).length();
5189
5190 };
5191
5192 }(),
5193
5194 getBoundingSphere: function () {
5195
5196 var v1 = new Vector3();
5197
5198 return function getBoundingSphere( target ) {
5199
5200 if ( target === undefined ) {
5201
5202 console.warn( 'THREE.Box3: .getBoundingSphere() target is now required' );
5203 target = new Sphere();
5204
5205 }
5206
5207 this.getCenter( target.center );
5208
5209 target.radius = this.getSize( v1 ).length() * 0.5;
5210
5211 return target;
5212
5213 };
5214
5215 }(),
5216
5217 intersect: function ( box ) {
5218
5219 this.min.max( box.min );
5220 this.max.min( box.max );
5221
5222 // 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.
5223 if ( this.isEmpty() ) this.makeEmpty();
5224
5225 return this;
5226
5227 },
5228
5229 union: function ( box ) {
5230
5231 this.min.min( box.min );
5232 this.max.max( box.max );
5233
5234 return this;
5235
5236 },
5237
5238 applyMatrix4: function () {
5239
5240 var points = [
5241 new Vector3(),
5242 new Vector3(),
5243 new Vector3(),
5244 new Vector3(),
5245 new Vector3(),
5246 new Vector3(),
5247 new Vector3(),
5248 new Vector3()
5249 ];
5250
5251 return function applyMatrix4( matrix ) {
5252
5253 // transform of empty box is an empty box.
5254 if ( this.isEmpty() ) return this;
5255
5256 // NOTE: I am using a binary pattern to specify all 2^3 combinations below
5257 points[ 0 ].set( this.min.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 000
5258 points[ 1 ].set( this.min.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 001
5259 points[ 2 ].set( this.min.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 010
5260 points[ 3 ].set( this.min.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 011
5261 points[ 4 ].set( this.max.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 100
5262 points[ 5 ].set( this.max.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 101
5263 points[ 6 ].set( this.max.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 110
5264 points[ 7 ].set( this.max.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 111
5265
5266 this.setFromPoints( points );
5267
5268 return this;
5269
5270 };
5271
5272 }(),
5273
5274 translate: function ( offset ) {
5275
5276 this.min.add( offset );
5277 this.max.add( offset );
5278
5279 return this;
5280
5281 },
5282
5283 equals: function ( box ) {
5284
5285 return box.min.equals( this.min ) && box.max.equals( this.max );
5286
5287 }
5288
5289} );
5290
5291/**
5292 * @author bhouston / http://clara.io
5293 * @author mrdoob / http://mrdoob.com/
5294 */
5295
5296function Sphere( center, radius ) {
5297
5298 this.center = ( center !== undefined ) ? center : new Vector3();
5299 this.radius = ( radius !== undefined ) ? radius : 0;
5300
5301}
5302
5303Object.assign( Sphere.prototype, {
5304
5305 set: function ( center, radius ) {
5306
5307 this.center.copy( center );
5308 this.radius = radius;
5309
5310 return this;
5311
5312 },
5313
5314 setFromPoints: function () {
5315
5316 var box = new Box3();
5317
5318 return function setFromPoints( points, optionalCenter ) {
5319
5320 var center = this.center;
5321
5322 if ( optionalCenter !== undefined ) {
5323
5324 center.copy( optionalCenter );
5325
5326 } else {
5327
5328 box.setFromPoints( points ).getCenter( center );
5329
5330 }
5331
5332 var maxRadiusSq = 0;
5333
5334 for ( var i = 0, il = points.length; i < il; i ++ ) {
5335
5336 maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( points[ i ] ) );
5337
5338 }
5339
5340 this.radius = Math.sqrt( maxRadiusSq );
5341
5342 return this;
5343
5344 };
5345
5346 }(),
5347
5348 clone: function () {
5349
5350 return new this.constructor().copy( this );
5351
5352 },
5353
5354 copy: function ( sphere ) {
5355
5356 this.center.copy( sphere.center );
5357 this.radius = sphere.radius;
5358
5359 return this;
5360
5361 },
5362
5363 empty: function () {
5364
5365 return ( this.radius <= 0 );
5366
5367 },
5368
5369 containsPoint: function ( point ) {
5370
5371 return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) );
5372
5373 },
5374
5375 distanceToPoint: function ( point ) {
5376
5377 return ( point.distanceTo( this.center ) - this.radius );
5378
5379 },
5380
5381 intersectsSphere: function ( sphere ) {
5382
5383 var radiusSum = this.radius + sphere.radius;
5384
5385 return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum );
5386
5387 },
5388
5389 intersectsBox: function ( box ) {
5390
5391 return box.intersectsSphere( this );
5392
5393 },
5394
5395 intersectsPlane: function ( plane ) {
5396
5397 return Math.abs( plane.distanceToPoint( this.center ) ) <= this.radius;
5398
5399 },
5400
5401 clampPoint: function ( point, target ) {
5402
5403 var deltaLengthSq = this.center.distanceToSquared( point );
5404
5405 if ( target === undefined ) {
5406
5407 console.warn( 'THREE.Sphere: .clampPoint() target is now required' );
5408 target = new Vector3();
5409
5410 }
5411
5412 target.copy( point );
5413
5414 if ( deltaLengthSq > ( this.radius * this.radius ) ) {
5415
5416 target.sub( this.center ).normalize();
5417 target.multiplyScalar( this.radius ).add( this.center );
5418
5419 }
5420
5421 return target;
5422
5423 },
5424
5425 getBoundingBox: function ( target ) {
5426
5427 if ( target === undefined ) {
5428
5429 console.warn( 'THREE.Sphere: .getBoundingBox() target is now required' );
5430 target = new Box3();
5431
5432 }
5433
5434 target.set( this.center, this.center );
5435 target.expandByScalar( this.radius );
5436
5437 return target;
5438
5439 },
5440
5441 applyMatrix4: function ( matrix ) {
5442
5443 this.center.applyMatrix4( matrix );
5444 this.radius = this.radius * matrix.getMaxScaleOnAxis();
5445
5446 return this;
5447
5448 },
5449
5450 translate: function ( offset ) {
5451
5452 this.center.add( offset );
5453
5454 return this;
5455
5456 },
5457
5458 equals: function ( sphere ) {
5459
5460 return sphere.center.equals( this.center ) && ( sphere.radius === this.radius );
5461
5462 }
5463
5464} );
5465
5466/**
5467 * @author bhouston / http://clara.io
5468 */
5469
5470function Plane( normal, constant ) {
5471
5472 // normal is assumed to be normalized
5473
5474 this.normal = ( normal !== undefined ) ? normal : new Vector3( 1, 0, 0 );
5475 this.constant = ( constant !== undefined ) ? constant : 0;
5476
5477}
5478
5479Object.assign( Plane.prototype, {
5480
5481 set: function ( normal, constant ) {
5482
5483 this.normal.copy( normal );
5484 this.constant = constant;
5485
5486 return this;
5487
5488 },
5489
5490 setComponents: function ( x, y, z, w ) {
5491
5492 this.normal.set( x, y, z );
5493 this.constant = w;
5494
5495 return this;
5496
5497 },
5498
5499 setFromNormalAndCoplanarPoint: function ( normal, point ) {
5500
5501 this.normal.copy( normal );
5502 this.constant = - point.dot( this.normal );
5503
5504 return this;
5505
5506 },
5507
5508 setFromCoplanarPoints: function () {
5509
5510 var v1 = new Vector3();
5511 var v2 = new Vector3();
5512
5513 return function setFromCoplanarPoints( a, b, c ) {
5514
5515 var normal = v1.subVectors( c, b ).cross( v2.subVectors( a, b ) ).normalize();
5516
5517 // Q: should an error be thrown if normal is zero (e.g. degenerate plane)?
5518
5519 this.setFromNormalAndCoplanarPoint( normal, a );
5520
5521 return this;
5522
5523 };
5524
5525 }(),
5526
5527 clone: function () {
5528
5529 return new this.constructor().copy( this );
5530
5531 },
5532
5533 copy: function ( plane ) {
5534
5535 this.normal.copy( plane.normal );
5536 this.constant = plane.constant;
5537
5538 return this;
5539
5540 },
5541
5542 normalize: function () {
5543
5544 // Note: will lead to a divide by zero if the plane is invalid.
5545
5546 var inverseNormalLength = 1.0 / this.normal.length();
5547 this.normal.multiplyScalar( inverseNormalLength );
5548 this.constant *= inverseNormalLength;
5549
5550 return this;
5551
5552 },
5553
5554 negate: function () {
5555
5556 this.constant *= - 1;
5557 this.normal.negate();
5558
5559 return this;
5560
5561 },
5562
5563 distanceToPoint: function ( point ) {
5564
5565 return this.normal.dot( point ) + this.constant;
5566
5567 },
5568
5569 distanceToSphere: function ( sphere ) {
5570
5571 return this.distanceToPoint( sphere.center ) - sphere.radius;
5572
5573 },
5574
5575 projectPoint: function ( point, target ) {
5576
5577 if ( target === undefined ) {
5578
5579 console.warn( 'THREE.Plane: .projectPoint() target is now required' );
5580 target = new Vector3();
5581
5582 }
5583
5584 return target.copy( this.normal ).multiplyScalar( - this.distanceToPoint( point ) ).add( point );
5585
5586 },
5587
5588 intersectLine: function () {
5589
5590 var v1 = new Vector3();
5591
5592 return function intersectLine( line, target ) {
5593
5594 if ( target === undefined ) {
5595
5596 console.warn( 'THREE.Plane: .intersectLine() target is now required' );
5597 target = new Vector3();
5598
5599 }
5600
5601 var direction = line.delta( v1 );
5602
5603 var denominator = this.normal.dot( direction );
5604
5605 if ( denominator === 0 ) {
5606
5607 // line is coplanar, return origin
5608 if ( this.distanceToPoint( line.start ) === 0 ) {
5609
5610 return target.copy( line.start );
5611
5612 }
5613
5614 // Unsure if this is the correct method to handle this case.
5615 return undefined;
5616
5617 }
5618
5619 var t = - ( line.start.dot( this.normal ) + this.constant ) / denominator;
5620
5621 if ( t < 0 || t > 1 ) {
5622
5623 return undefined;
5624
5625 }
5626
5627 return target.copy( direction ).multiplyScalar( t ).add( line.start );
5628
5629 };
5630
5631 }(),
5632
5633 intersectsLine: function ( line ) {
5634
5635 // Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it.
5636
5637 var startSign = this.distanceToPoint( line.start );
5638 var endSign = this.distanceToPoint( line.end );
5639
5640 return ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 );
5641
5642 },
5643
5644 intersectsBox: function ( box ) {
5645
5646 return box.intersectsPlane( this );
5647
5648 },
5649
5650 intersectsSphere: function ( sphere ) {
5651
5652 return sphere.intersectsPlane( this );
5653
5654 },
5655
5656 coplanarPoint: function ( target ) {
5657
5658 if ( target === undefined ) {
5659
5660 console.warn( 'THREE.Plane: .coplanarPoint() target is now required' );
5661 target = new Vector3();
5662
5663 }
5664
5665 return target.copy( this.normal ).multiplyScalar( - this.constant );
5666
5667 },
5668
5669 applyMatrix4: function () {
5670
5671 var v1 = new Vector3();
5672 var m1 = new Matrix3();
5673
5674 return function applyMatrix4( matrix, optionalNormalMatrix ) {
5675
5676 var normalMatrix = optionalNormalMatrix || m1.getNormalMatrix( matrix );
5677
5678 var referencePoint = this.coplanarPoint( v1 ).applyMatrix4( matrix );
5679
5680 var normal = this.normal.applyMatrix3( normalMatrix ).normalize();
5681
5682 this.constant = - referencePoint.dot( normal );
5683
5684 return this;
5685
5686 };
5687
5688 }(),
5689
5690 translate: function ( offset ) {
5691
5692 this.constant -= offset.dot( this.normal );
5693
5694 return this;
5695
5696 },
5697
5698 equals: function ( plane ) {
5699
5700 return plane.normal.equals( this.normal ) && ( plane.constant === this.constant );
5701
5702 }
5703
5704} );
5705
5706/**
5707 * @author mrdoob / http://mrdoob.com/
5708 * @author alteredq / http://alteredqualia.com/
5709 * @author bhouston / http://clara.io
5710 */
5711
5712function Frustum( p0, p1, p2, p3, p4, p5 ) {
5713
5714 this.planes = [
5715
5716 ( p0 !== undefined ) ? p0 : new Plane(),
5717 ( p1 !== undefined ) ? p1 : new Plane(),
5718 ( p2 !== undefined ) ? p2 : new Plane(),
5719 ( p3 !== undefined ) ? p3 : new Plane(),
5720 ( p4 !== undefined ) ? p4 : new Plane(),
5721 ( p5 !== undefined ) ? p5 : new Plane()
5722
5723 ];
5724
5725}
5726
5727Object.assign( Frustum.prototype, {
5728
5729 set: function ( p0, p1, p2, p3, p4, p5 ) {
5730
5731 var planes = this.planes;
5732
5733 planes[ 0 ].copy( p0 );
5734 planes[ 1 ].copy( p1 );
5735 planes[ 2 ].copy( p2 );
5736 planes[ 3 ].copy( p3 );
5737 planes[ 4 ].copy( p4 );
5738 planes[ 5 ].copy( p5 );
5739
5740 return this;
5741
5742 },
5743
5744 clone: function () {
5745
5746 return new this.constructor().copy( this );
5747
5748 },
5749
5750 copy: function ( frustum ) {
5751
5752 var planes = this.planes;
5753
5754 for ( var i = 0; i < 6; i ++ ) {
5755
5756 planes[ i ].copy( frustum.planes[ i ] );
5757
5758 }
5759
5760 return this;
5761
5762 },
5763
5764 setFromMatrix: function ( m ) {
5765
5766 var planes = this.planes;
5767 var me = m.elements;
5768 var me0 = me[ 0 ], me1 = me[ 1 ], me2 = me[ 2 ], me3 = me[ 3 ];
5769 var me4 = me[ 4 ], me5 = me[ 5 ], me6 = me[ 6 ], me7 = me[ 7 ];
5770 var me8 = me[ 8 ], me9 = me[ 9 ], me10 = me[ 10 ], me11 = me[ 11 ];
5771 var me12 = me[ 12 ], me13 = me[ 13 ], me14 = me[ 14 ], me15 = me[ 15 ];
5772
5773 planes[ 0 ].setComponents( me3 - me0, me7 - me4, me11 - me8, me15 - me12 ).normalize();
5774 planes[ 1 ].setComponents( me3 + me0, me7 + me4, me11 + me8, me15 + me12 ).normalize();
5775 planes[ 2 ].setComponents( me3 + me1, me7 + me5, me11 + me9, me15 + me13 ).normalize();
5776 planes[ 3 ].setComponents( me3 - me1, me7 - me5, me11 - me9, me15 - me13 ).normalize();
5777 planes[ 4 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize();
5778 planes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize();
5779
5780 return this;
5781
5782 },
5783
5784 intersectsObject: function () {
5785
5786 var sphere = new Sphere();
5787
5788 return function intersectsObject( object ) {
5789
5790 var geometry = object.geometry;
5791
5792 if ( geometry.boundingSphere === null )
5793 geometry.computeBoundingSphere();
5794
5795 sphere.copy( geometry.boundingSphere )
5796 .applyMatrix4( object.matrixWorld );
5797
5798 return this.intersectsSphere( sphere );
5799
5800 };
5801
5802 }(),
5803
5804 intersectsSprite: function () {
5805
5806 var sphere = new Sphere();
5807
5808 return function intersectsSprite( sprite ) {
5809
5810 sphere.center.set( 0, 0, 0 );
5811 sphere.radius = 0.7071067811865476;
5812 sphere.applyMatrix4( sprite.matrixWorld );
5813
5814 return this.intersectsSphere( sphere );
5815
5816 };
5817
5818 }(),
5819
5820 intersectsSphere: function ( sphere ) {
5821
5822 var planes = this.planes;
5823 var center = sphere.center;
5824 var negRadius = - sphere.radius;
5825
5826 for ( var i = 0; i < 6; i ++ ) {
5827
5828 var distance = planes[ i ].distanceToPoint( center );
5829
5830 if ( distance < negRadius ) {
5831
5832 return false;
5833
5834 }
5835
5836 }
5837
5838 return true;
5839
5840 },
5841
5842 intersectsBox: function () {
5843
5844 var p1 = new Vector3(),
5845 p2 = new Vector3();
5846
5847 return function intersectsBox( box ) {
5848
5849 var planes = this.planes;
5850
5851 for ( var i = 0; i < 6; i ++ ) {
5852
5853 var plane = planes[ i ];
5854
5855 p1.x = plane.normal.x > 0 ? box.min.x : box.max.x;
5856 p2.x = plane.normal.x > 0 ? box.max.x : box.min.x;
5857 p1.y = plane.normal.y > 0 ? box.min.y : box.max.y;
5858 p2.y = plane.normal.y > 0 ? box.max.y : box.min.y;
5859 p1.z = plane.normal.z > 0 ? box.min.z : box.max.z;
5860 p2.z = plane.normal.z > 0 ? box.max.z : box.min.z;
5861
5862 var d1 = plane.distanceToPoint( p1 );
5863 var d2 = plane.distanceToPoint( p2 );
5864
5865 // if both outside plane, no intersection
5866
5867 if ( d1 < 0 && d2 < 0 ) {
5868
5869 return false;
5870
5871 }
5872
5873 }
5874
5875 return true;
5876
5877 };
5878
5879 }(),
5880
5881 containsPoint: function ( point ) {
5882
5883 var planes = this.planes;
5884
5885 for ( var i = 0; i < 6; i ++ ) {
5886
5887 if ( planes[ i ].distanceToPoint( point ) < 0 ) {
5888
5889 return false;
5890
5891 }
5892
5893 }
5894
5895 return true;
5896
5897 }
5898
5899} );
5900
5901var alphamap_fragment = "#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vUv ).g;\n#endif\n";
5902
5903var alphamap_pars_fragment = "#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif\n";
5904
5905var alphatest_fragment = "#ifdef ALPHATEST\n\tif ( diffuseColor.a < ALPHATEST ) discard;\n#endif\n";
5906
5907var aomap_fragment = "#ifdef USE_AOMAP\n\tfloat ambientOcclusion = ( texture2D( aoMap, vUv2 ).r - 1.0 ) * aoMapIntensity + 1.0;\n\treflectedLight.indirectDiffuse *= ambientOcclusion;\n\t#if defined( USE_ENVMAP ) && defined( PHYSICAL )\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\treflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.specularRoughness );\n\t#endif\n#endif\n";
5908
5909var aomap_pars_fragment = "#ifdef USE_AOMAP\n\tuniform sampler2D aoMap;\n\tuniform float aoMapIntensity;\n#endif";
5910
5911var begin_vertex = "\nvec3 transformed = vec3( position );\n";
5912
5913var beginnormal_vertex = "\nvec3 objectNormal = vec3( normal );\n";
5914
5915var bsdfs = "float punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\tif( decayExponent > 0.0 ) {\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tfloat maxDistanceCutoffFactor = pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\treturn distanceFalloff * maxDistanceCutoffFactor;\n#else\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n#endif\n\t}\n\treturn 1.0;\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\treturn 1.0 / ( gl * gv );\n}\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( G * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\nvec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;\n\treturn specularColor * AB.x + AB.y;\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n";
5916
5917var bumpmap_pars_fragment = "#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\n\t\tvec3 vSigmaX = vec3( dFdx( surf_pos.x ), dFdx( surf_pos.y ), dFdx( surf_pos.z ) );\n\t\tvec3 vSigmaY = vec3( dFdy( surf_pos.x ), dFdy( surf_pos.y ), dFdy( surf_pos.z ) );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 );\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif\n";
5918
5919var clipping_planes_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tvec4 plane;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\tplane = clippingPlanes[ i ];\n\t\tif ( dot( vViewPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\t#pragma unroll_loop\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vViewPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\tif ( clipped ) discard;\n\t#endif\n#endif\n";
5920
5921var clipping_planes_pars_fragment = "#if NUM_CLIPPING_PLANES > 0\n\t#if ! defined( PHYSICAL ) && ! defined( PHONG )\n\t\tvarying vec3 vViewPosition;\n\t#endif\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif\n";
5922
5923var clipping_planes_pars_vertex = "#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n\tvarying vec3 vViewPosition;\n#endif\n";
5924
5925var clipping_planes_vertex = "#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n";
5926
5927var color_fragment = "#ifdef USE_COLOR\n\tdiffuseColor.rgb *= vColor;\n#endif";
5928
5929var color_pars_fragment = "#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif\n";
5930
5931var color_pars_vertex = "#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif";
5932
5933var color_vertex = "#ifdef USE_COLOR\n\tvColor.xyz = color.xyz;\n#endif";
5934
5935var common = "#define PI 3.14159265359\n#define PI2 6.28318530718\n#define PI_HALF 1.5707963267949\n#define RECIPROCAL_PI 0.31830988618\n#define RECIPROCAL_PI2 0.15915494\n#define LOG2 1.442695\n#define EPSILON 1e-6\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#define whiteCompliment(a) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract(sin(sn) * c);\n}\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\tfloat distance = dot( planeNormal, point - pointOnPlane );\n\treturn - distance * planeNormal + point;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat linearToRelativeLuminance( const in vec3 color ) {\n\tvec3 weights = vec3( 0.2126, 0.7152, 0.0722 );\n\treturn dot( weights, color.rgb );\n}\n";
5936
5937var cube_uv_reflection_fragment = "#ifdef ENVMAP_TYPE_CUBE_UV\n#define cubeUV_textureSize (1024.0)\nint getFaceFromDirection(vec3 direction) {\n\tvec3 absDirection = abs(direction);\n\tint face = -1;\n\tif( absDirection.x > absDirection.z ) {\n\t\tif(absDirection.x > absDirection.y )\n\t\t\tface = direction.x > 0.0 ? 0 : 3;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\telse {\n\t\tif(absDirection.z > absDirection.y )\n\t\t\tface = direction.z > 0.0 ? 2 : 5;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\treturn face;\n}\n#define cubeUV_maxLods1 (log2(cubeUV_textureSize*0.25) - 1.0)\n#define cubeUV_rangeClamp (exp2((6.0 - 1.0) * 2.0))\nvec2 MipLevelInfo( vec3 vec, float roughnessLevel, float roughness ) {\n\tfloat scale = exp2(cubeUV_maxLods1 - roughnessLevel);\n\tfloat dxRoughness = dFdx(roughness);\n\tfloat dyRoughness = dFdy(roughness);\n\tvec3 dx = dFdx( vec * scale * dxRoughness );\n\tvec3 dy = dFdy( vec * scale * dyRoughness );\n\tfloat d = max( dot( dx, dx ), dot( dy, dy ) );\n\td = clamp(d, 1.0, cubeUV_rangeClamp);\n\tfloat mipLevel = 0.5 * log2(d);\n\treturn vec2(floor(mipLevel), fract(mipLevel));\n}\n#define cubeUV_maxLods2 (log2(cubeUV_textureSize*0.25) - 2.0)\n#define cubeUV_rcpTextureSize (1.0 / cubeUV_textureSize)\nvec2 getCubeUV(vec3 direction, float roughnessLevel, float mipLevel) {\n\tmipLevel = roughnessLevel > cubeUV_maxLods2 - 3.0 ? 0.0 : mipLevel;\n\tfloat a = 16.0 * cubeUV_rcpTextureSize;\n\tvec2 exp2_packed = exp2( vec2( roughnessLevel, mipLevel ) );\n\tvec2 rcp_exp2_packed = vec2( 1.0 ) / exp2_packed;\n\tfloat powScale = exp2_packed.x * exp2_packed.y;\n\tfloat scale = rcp_exp2_packed.x * rcp_exp2_packed.y * 0.25;\n\tfloat mipOffset = 0.75*(1.0 - rcp_exp2_packed.y) * rcp_exp2_packed.x;\n\tbool bRes = mipLevel == 0.0;\n\tscale = bRes && (scale < a) ? a : scale;\n\tvec3 r;\n\tvec2 offset;\n\tint face = getFaceFromDirection(direction);\n\tfloat rcpPowScale = 1.0 / powScale;\n\tif( face == 0) {\n\t\tr = vec3(direction.x, -direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 1) {\n\t\tr = vec3(direction.y, direction.x, direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 2) {\n\t\tr = vec3(direction.z, direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 3) {\n\t\tr = vec3(direction.x, direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse if( face == 4) {\n\t\tr = vec3(direction.y, direction.x, -direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse {\n\t\tr = vec3(direction.z, -direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\tr = normalize(r);\n\tfloat texelOffset = 0.5 * cubeUV_rcpTextureSize;\n\tvec2 s = ( r.yz / abs( r.x ) + vec2( 1.0 ) ) * 0.5;\n\tvec2 base = offset + vec2( texelOffset );\n\treturn base + s * ( scale - 2.0 * texelOffset );\n}\n#define cubeUV_maxLods3 (log2(cubeUV_textureSize*0.25) - 3.0)\nvec4 textureCubeUV(vec3 reflectedDirection, float roughness ) {\n\tfloat roughnessVal = roughness* cubeUV_maxLods3;\n\tfloat r1 = floor(roughnessVal);\n\tfloat r2 = r1 + 1.0;\n\tfloat t = fract(roughnessVal);\n\tvec2 mipInfo = MipLevelInfo(reflectedDirection, r1, roughness);\n\tfloat s = mipInfo.y;\n\tfloat level0 = mipInfo.x;\n\tfloat level1 = level0 + 1.0;\n\tlevel1 = level1 > 5.0 ? 5.0 : level1;\n\tlevel0 += min( floor( s + 0.5 ), 5.0 );\n\tvec2 uv_10 = getCubeUV(reflectedDirection, r1, level0);\n\tvec4 color10 = envMapTexelToLinear(texture2D(envMap, uv_10));\n\tvec2 uv_20 = getCubeUV(reflectedDirection, r2, level0);\n\tvec4 color20 = envMapTexelToLinear(texture2D(envMap, uv_20));\n\tvec4 result = mix(color10, color20, t);\n\treturn vec4(result.rgb, 1.0);\n}\n#endif\n";
5938
5939var defaultnormal_vertex = "vec3 transformedNormal = normalMatrix * objectNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n";
5940
5941var displacementmap_pars_vertex = "#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif\n";
5942
5943var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, uv ).x * displacementScale + displacementBias );\n#endif\n";
5944
5945var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif\n";
5946
5947var emissivemap_pars_fragment = "#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif\n";
5948
5949var encodings_fragment = " gl_FragColor = linearToOutputTexel( gl_FragColor );\n";
5950
5951var encodings_pars_fragment = "\nvec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 GammaToLinear( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.xyz, vec3( gammaFactor ) ), value.w );\n}\nvec4 LinearToGamma( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.xyz, vec3( 1.0 / gammaFactor ) ), value.w );\n}\nvec4 sRGBToLinear( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.w );\n}\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.w );\n}\nvec4 RGBEToLinear( in vec4 value ) {\n\treturn vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 );\n}\nvec4 LinearToRGBE( in vec4 value ) {\n\tfloat maxComponent = max( max( value.r, value.g ), value.b );\n\tfloat fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 );\n\treturn vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 );\n}\nvec4 RGBMToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.xyz * value.w * maxRange, 1.0 );\n}\nvec4 LinearToRGBM( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.x, max( value.g, value.b ) );\n\tfloat M = clamp( maxRGB / maxRange, 0.0, 1.0 );\n\tM = ceil( M * 255.0 ) / 255.0;\n\treturn vec4( value.rgb / ( M * maxRange ), M );\n}\nvec4 RGBDToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 );\n}\nvec4 LinearToRGBD( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.x, max( value.g, value.b ) );\n\tfloat D = max( maxRange / maxRGB, 1.0 );\n\tD = min( floor( D ) / 255.0, 1.0 );\n\treturn vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D );\n}\nconst mat3 cLogLuvM = mat3( 0.2209, 0.3390, 0.4184, 0.1138, 0.6780, 0.7319, 0.0102, 0.1130, 0.2969 );\nvec4 LinearToLogLuv( in vec4 value ) {\n\tvec3 Xp_Y_XYZp = value.rgb * cLogLuvM;\n\tXp_Y_XYZp = max(Xp_Y_XYZp, vec3(1e-6, 1e-6, 1e-6));\n\tvec4 vResult;\n\tvResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;\n\tfloat Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;\n\tvResult.w = fract(Le);\n\tvResult.z = (Le - (floor(vResult.w*255.0))/255.0)/255.0;\n\treturn vResult;\n}\nconst mat3 cLogLuvInverseM = mat3( 6.0014, -2.7008, -1.7996, -1.3320, 3.1029, -5.7721, 0.3008, -1.0882, 5.6268 );\nvec4 LogLuvToLinear( in vec4 value ) {\n\tfloat Le = value.z * 255.0 + value.w;\n\tvec3 Xp_Y_XYZp;\n\tXp_Y_XYZp.y = exp2((Le - 127.0) / 2.0);\n\tXp_Y_XYZp.z = Xp_Y_XYZp.y / value.y;\n\tXp_Y_XYZp.x = value.x * Xp_Y_XYZp.z;\n\tvec3 vRGB = Xp_Y_XYZp.rgb * cLogLuvInverseM;\n\treturn vec4( max(vRGB, 0.0), 1.0 );\n}\n";
5952
5953var envmap_fragment = "#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\tvec2 sampleUV;\n\t\treflectVec = normalize( reflectVec );\n\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\tvec4 envColor = texture2D( envMap, sampleUV );\n\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\treflectVec = normalize( reflectVec );\n\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0, 0.0, 1.0 ) );\n\t\tvec4 envColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5 );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\tenvColor = envMapTexelToLinear( envColor );\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif\n";
5954
5955var envmap_pars_fragment = "#if defined( USE_ENVMAP ) || defined( PHYSICAL )\n\tuniform float reflectivity;\n\tuniform float envMapIntensity;\n#endif\n#ifdef USE_ENVMAP\n\t#if ! defined( PHYSICAL ) && ( defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) )\n\t\tvarying vec3 vWorldPosition;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\tuniform float flipEnvMap;\n\tuniform int maxMipLevel;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( PHYSICAL )\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif\n";
5956
5957var envmap_pars_vertex = "#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif\n";
5958
5959var envmap_vertex = "#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif\n";
5960
5961var fog_vertex = "\n#ifdef USE_FOG\nfogDepth = -mvPosition.z;\n#endif";
5962
5963var fog_pars_vertex = "#ifdef USE_FOG\n varying float fogDepth;\n#endif\n";
5964
5965var fog_fragment = "#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 ) );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, fogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif\n";
5966
5967var fog_pars_fragment = "#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float fogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif\n";
5968
5969var gradientmap_pars_fragment = "#ifdef TOON\n\tuniform sampler2D gradientMap;\n\tvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\t\tfloat dotNL = dot( normal, lightDirection );\n\t\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t\t#ifdef USE_GRADIENTMAP\n\t\t\treturn texture2D( gradientMap, coord ).rgb;\n\t\t#else\n\t\t\treturn ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );\n\t\t#endif\n\t}\n#endif\n";
5970
5971var lightmap_fragment = "#ifdef USE_LIGHTMAP\n\treflectedLight.indirectDiffuse += PI * texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n#endif\n";
5972
5973var lightmap_pars_fragment = "#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif";
5974
5975var lights_lambert_vertex = "vec3 diffuse = vec3( 1.0 );\nGeometricContext geometry;\ngeometry.position = mvPosition.xyz;\ngeometry.normal = normalize( transformedNormal );\ngeometry.viewDir = normalize( -mvPosition.xyz );\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\nvLightFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n\tvLightBack = vec3( 0.0 );\n#endif\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\n#if NUM_POINT_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tgetPointDirectLightIrradiance( pointLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tgetSpotDirectLightIrradiance( spotLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_DIR_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tgetDirectionalDirectLightIrradiance( directionalLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\tvLightFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\n\t\t#endif\n\t}\n#endif\n";
5976
5977var lights_pars_begin = "uniform vec3 ambientLightColor;\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treturn irradiance;\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tdirectLight.color = directionalLight.color;\n\t\tdirectLight.direction = directionalLight.direction;\n\t\tdirectLight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t\tfloat shadowCameraNear;\n\t\tfloat shadowCameraFar;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tdirectLight.color = pointLight.color;\n\t\tdirectLight.color *= punctualLightIntensityToIrradianceFactor( lightDistance, pointLight.distance, pointLight.decay );\n\t\tdirectLight.visible = ( directLight.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tfloat angleCos = dot( directLight.direction, spotLight.direction );\n\t\tif ( angleCos > spotLight.coneCos ) {\n\t\t\tfloat spotEffect = smoothstep( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\t\tdirectLight.color = spotLight.color;\n\t\t\tdirectLight.color *= spotEffect * punctualLightIntensityToIrradianceFactor( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tdirectLight.visible = true;\n\t\t} else {\n\t\t\tdirectLight.color = vec3( 0.0 );\n\t\t\tdirectLight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in GeometricContext geometry ) {\n\t\tfloat dotNL = dot( geometry.normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tirradiance *= PI;\n\t\t#endif\n\t\treturn irradiance;\n\t}\n#endif\n";
5978
5979var lights_pars_maps = "#if defined( USE_ENVMAP ) && defined( PHYSICAL )\n\tvec3 getLightProbeIndirectIrradiance( const in GeometricContext geometry, const in int maxMIPLevel ) {\n\t\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\tvec4 envMapColor = textureCubeUV( queryVec, 1.0 );\n\t\t#else\n\t\t\tvec4 envMapColor = vec4( 0.0 );\n\t\t#endif\n\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t}\n\tfloat getSpecularMIPLevel( const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\tfloat maxMIPLevelScalar = float( maxMIPLevel );\n\t\tfloat desiredMIPLevel = maxMIPLevelScalar + 0.79248 - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );\n\t\treturn clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );\n\t}\n\tvec3 getLightProbeIndirectRadiance( const in GeometricContext geometry, const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( -geometry.viewDir, geometry.normal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( -geometry.viewDir, geometry.normal, refractionRatio );\n\t\t#endif\n\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\tfloat specularMIPLevel = getSpecularMIPLevel( blinnShininessExponent, maxMIPLevel );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\tvec4 envMapColor = textureCubeUV(queryReflectVec, BlinnExponentToGGXRoughness(blinnShininessExponent));\n\t\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\t\tvec2 sampleUV;\n\t\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, sampleUV, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, sampleUV, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0,0.0,1.0 ) );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#endif\n\t\treturn envMapColor.rgb * envMapIntensity;\n\t}\n#endif\n";
5980
5981var lights_phong_fragment = "BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;\n";
5982
5983var lights_phong_pars_fragment = "varying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\nstruct BlinnPhongMaterial {\n\tvec3\tdiffuseColor;\n\tvec3\tspecularColor;\n\tfloat\tspecularShininess;\n\tfloat\tspecularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifdef TOON\n\t\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n\t#else\n\t\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\t\tvec3 irradiance = dotNL * directLight.color;\n\t#endif\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong\n#define Material_LightProbeLOD( material )\t(0)\n";
5984
5985var lights_physical_fragment = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nmaterial.specularRoughness = clamp( roughnessFactor, 0.04, 1.0 );\n#ifdef STANDARD\n\tmaterial.specularColor = mix( vec3( DEFAULT_SPECULAR_COEFFICIENT ), diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( MAXIMUM_SPECULAR_COEFFICIENT * pow2( reflectivity ) ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.clearCoat = saturate( clearCoat );\tmaterial.clearCoatRoughness = clamp( clearCoatRoughness, 0.04, 1.0 );\n#endif\n";
5986
5987var lights_physical_pars_fragment = "struct PhysicalMaterial {\n\tvec3\tdiffuseColor;\n\tfloat\tspecularRoughness;\n\tvec3\tspecularColor;\n\t#ifndef STANDARD\n\t\tfloat clearCoat;\n\t\tfloat clearCoatRoughness;\n\t#endif\n};\n#define MAXIMUM_SPECULAR_COEFFICIENT 0.16\n#define DEFAULT_SPECULAR_COEFFICIENT 0.04\nfloat clearCoatDHRApprox( const in float roughness, const in float dotNL ) {\n\treturn DEFAULT_SPECULAR_COEFFICIENT + ( 1.0 - DEFAULT_SPECULAR_COEFFICIENT ) * ( pow( 1.0 - dotNL, 5.0 ) * pow( 1.0 - roughness, 2.0 ) );\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.specularRoughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos - halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos + halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos + halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos - halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\t#ifndef STANDARD\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.directSpecular += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Specular_GGX( directLight, geometry, material.specularColor, material.specularRoughness );\n\treflectedLight.directDiffuse += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\t#ifndef STANDARD\n\t\treflectedLight.directSpecular += irradiance * material.clearCoat * BRDF_Specular_GGX( directLight, geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 clearCoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifndef STANDARD\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\tfloat dotNL = dotNV;\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.indirectSpecular += ( 1.0 - clearCoatDHR ) * radiance * BRDF_Specular_GGX_Environment( geometry, material.specularColor, material.specularRoughness );\n\t#ifndef STANDARD\n\t\treflectedLight.indirectSpecular += clearCoatRadiance * material.clearCoat * BRDF_Specular_GGX_Environment( geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\n#define Material_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.specularRoughness )\n#define Material_ClearCoat_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.clearCoatRoughness )\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}\n";
5988
5989var lights_fragment_begin = "\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = normalize( vViewPosition );\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointDirectLightIrradiance( pointLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( pointLight.shadow, directLight.visible ) ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotDirectLightIrradiance( spotLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( spotLight.shadow, directLight.visible ) ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( directionalLight.shadow, directLight.visible ) ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t}\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearCoatRadiance = vec3( 0.0 );\n#endif\n";
5990
5991var lights_fragment_maps = "#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec3 lightMapIrradiance = texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tlightMapIrradiance *= PI;\n\t\t#endif\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( PHYSICAL ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tirradiance += getLightProbeIndirectIrradiance( geometry, maxMipLevel );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tradiance += getLightProbeIndirectRadiance( geometry, Material_BlinnShininessExponent( material ), maxMipLevel );\n\t#ifndef STANDARD\n\t\tclearCoatRadiance += getLightProbeIndirectRadiance( geometry, Material_ClearCoat_BlinnShininessExponent( material ), maxMipLevel );\n\t#endif\n#endif\n";
5992
5993var lights_fragment_end = "#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, clearCoatRadiance, geometry, material, reflectedLight );\n#endif\n";
5994
5995var logdepthbuf_fragment = "#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif";
5996
5997var logdepthbuf_pars_fragment = "#ifdef USE_LOGDEPTHBUF\n\tuniform float logDepthBufFC;\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n#endif\n";
5998
5999var logdepthbuf_pars_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n\tuniform float logDepthBufFC;\n#endif";
6000
6001var logdepthbuf_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t#else\n\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\tgl_Position.z *= gl_Position.w;\n\t#endif\n#endif\n";
6002
6003var map_fragment = "#ifdef USE_MAP\n\tvec4 texelColor = texture2D( map, vUv );\n\ttexelColor = mapTexelToLinear( texelColor );\n\tdiffuseColor *= texelColor;\n#endif\n";
6004
6005var map_pars_fragment = "#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n";
6006
6007var map_particle_fragment = "#ifdef USE_MAP\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\tvec4 mapTexel = texture2D( map, uv );\n\tdiffuseColor *= mapTexelToLinear( mapTexel );\n#endif\n";
6008
6009var map_particle_pars_fragment = "#ifdef USE_MAP\n\tuniform mat3 uvTransform;\n\tuniform sampler2D map;\n#endif\n";
6010
6011var metalnessmap_fragment = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif\n";
6012
6013var metalnessmap_pars_fragment = "#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif";
6014
6015var morphnormal_vertex = "#ifdef USE_MORPHNORMALS\n\tobjectNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];\n\tobjectNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];\n\tobjectNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];\n\tobjectNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];\n#endif\n";
6016
6017var morphtarget_pars_vertex = "#ifdef USE_MORPHTARGETS\n\t#ifndef USE_MORPHNORMALS\n\tuniform float morphTargetInfluences[ 8 ];\n\t#else\n\tuniform float morphTargetInfluences[ 4 ];\n\t#endif\n#endif";
6018
6019var morphtarget_vertex = "#ifdef USE_MORPHTARGETS\n\ttransformed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];\n\ttransformed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];\n\ttransformed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];\n\ttransformed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];\n\t#ifndef USE_MORPHNORMALS\n\ttransformed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];\n\ttransformed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];\n\ttransformed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];\n\ttransformed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];\n\t#endif\n#endif\n";
6020
6021var normal_fragment_begin = "#ifdef FLAT_SHADED\n\tvec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );\n\tvec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t#endif\n#endif\n";
6022
6023var normal_fragment_maps = "#ifdef USE_NORMALMAP\n\tnormal = perturbNormal2Arb( -vViewPosition, normal );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n#endif\n";
6024
6025var normalmap_pars_fragment = "#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {\n\t\tvec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );\n\t\tvec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\t\tfloat scale = sign( st1.t * st0.s - st0.t * st1.s );\t\tscale *= float( gl_FrontFacing ) * 2.0 - 1.0;\n\t\tvec3 S = normalize( ( q0 * st1.t - q1 * st0.t ) * scale );\n\t\tvec3 T = normalize( ( - q0 * st1.s + q1 * st0.s ) * scale );\n\t\tvec3 N = normalize( surf_norm );\n\t\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t\tmapN.xy = normalScale * mapN.xy;\n\t\tmat3 tsn = mat3( S, T, N );\n\t\treturn normalize( tsn * mapN );\n\t}\n#endif\n";
6026
6027var packing = "vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\nconst float ShiftRight8 = 1. / 256.;\nvec4 packDepthToRGBA( const in float v ) {\n\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n\treturn linearClipZ * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn (( near + viewZ ) * far ) / (( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * invClipZ - far );\n}\n";
6028
6029var premultiplied_alpha_fragment = "#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif\n";
6030
6031var project_vertex = "vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );\ngl_Position = projectionMatrix * mvPosition;\n";
6032
6033var dithering_fragment = "#if defined( DITHERING )\n gl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif\n";
6034
6035var dithering_pars_fragment = "#if defined( DITHERING )\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif\n";
6036
6037var roughnessmap_fragment = "float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif\n";
6038
6039var roughnessmap_pars_fragment = "#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif";
6040
6041var shadowmap_pars_fragment = "#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tfloat texture2DShadowLerp( sampler2D depths, vec2 size, vec2 uv, float compare ) {\n\t\tconst vec2 offset = vec2( 0.0, 1.0 );\n\t\tvec2 texelSize = vec2( 1.0 ) / size;\n\t\tvec2 centroidUV = floor( uv * size + 0.5 ) / size;\n\t\tfloat lb = texture2DCompare( depths, centroidUV + texelSize * offset.xx, compare );\n\t\tfloat lt = texture2DCompare( depths, centroidUV + texelSize * offset.xy, compare );\n\t\tfloat rb = texture2DCompare( depths, centroidUV + texelSize * offset.yx, compare );\n\t\tfloat rt = texture2DCompare( depths, centroidUV + texelSize * offset.yy, compare );\n\t\tvec2 f = fract( uv * size + 0.5 );\n\t\tfloat a = mix( lb, lt, f.y );\n\t\tfloat b = mix( rb, rt, f.y );\n\t\tfloat c = mix( a, b, f.x );\n\t\treturn c;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n\t\tbool inFrustum = all( inFrustumVec );\n\t\tbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n\t\tbool frustumTest = all( frustumTestVec );\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tshadow = (\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif\n";
6042
6043var shadowmap_pars_vertex = "#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n#endif\n";
6044
6045var shadowmap_vertex = "#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tvSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n#endif\n";
6046
6047var shadowmask_pars_fragment = "float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\tDirectionalLight directionalLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tshadow *= bool( directionalLight.shadow ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\tSpotLight spotLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tshadow *= bool( spotLight.shadow ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\tPointLight pointLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tshadow *= bool( pointLight.shadow ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#endif\n\t#endif\n\treturn shadow;\n}\n";
6048
6049var skinbase_vertex = "#ifdef USE_SKINNING\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif";
6050
6051var skinning_pars_vertex = "#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\t#ifdef BONE_TEXTURE\n\t\tuniform sampler2D boneTexture;\n\t\tuniform int boneTextureSize;\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tfloat j = i * 4.0;\n\t\t\tfloat x = mod( j, float( boneTextureSize ) );\n\t\t\tfloat y = floor( j / float( boneTextureSize ) );\n\t\t\tfloat dx = 1.0 / float( boneTextureSize );\n\t\t\tfloat dy = 1.0 / float( boneTextureSize );\n\t\t\ty = dy * ( y + 0.5 );\n\t\t\tvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n\t\t\tvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n\t\t\tvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n\t\t\tvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\t\t\tmat4 bone = mat4( v1, v2, v3, v4 );\n\t\t\treturn bone;\n\t\t}\n\t#else\n\t\tuniform mat4 boneMatrices[ MAX_BONES ];\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tmat4 bone = boneMatrices[ int(i) ];\n\t\t\treturn bone;\n\t\t}\n\t#endif\n#endif\n";
6052
6053var skinning_vertex = "#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n#endif\n";
6054
6055var skinnormal_vertex = "#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n#endif\n";
6056
6057var specularmap_fragment = "float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif";
6058
6059var specularmap_pars_fragment = "#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif";
6060
6061var tonemapping_fragment = "#if defined( TONE_MAPPING )\n gl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif\n";
6062
6063var tonemapping_pars_fragment = "#ifndef saturate\n\t#define saturate(a) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nuniform float toneMappingWhitePoint;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn toneMappingExposure * color;\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\n#define Uncharted2Helper( x ) max( ( ( x * ( 0.15 * x + 0.10 * 0.50 ) + 0.20 * 0.02 ) / ( x * ( 0.15 * x + 0.50 ) + 0.20 * 0.30 ) ) - 0.02 / 0.30, vec3( 0.0 ) )\nvec3 Uncharted2ToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( Uncharted2Helper( color ) / Uncharted2Helper( vec3( toneMappingWhitePoint ) ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\n";
6064
6065var uv_pars_fragment = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n#endif";
6066
6067var uv_pars_vertex = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\n";
6068
6069var uv_vertex = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif";
6070
6071var uv2_pars_fragment = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif";
6072
6073var uv2_pars_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tattribute vec2 uv2;\n\tvarying vec2 vUv2;\n#endif";
6074
6075var uv2_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = uv2;\n#endif";
6076
6077var worldpos_vertex = "#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )\n\tvec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );\n#endif\n";
6078
6079var cube_frag = "uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldPosition;\nvoid main() {\n\tgl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );\n\tgl_FragColor.a *= opacity;\n}\n";
6080
6081var cube_vert = "varying vec3 vWorldPosition;\n#include <common>\nvoid main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\t#include <begin_vertex>\n\t#include <project_vertex>\n\tgl_Position.z = gl_Position.w;\n}\n";
6082
6083var depth_frag = "#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include <common>\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <logdepthbuf_fragment>\n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( 1.0 - gl_FragCoord.z ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( gl_FragCoord.z );\n\t#endif\n}\n";
6084
6085var depth_vert = "#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinnormal_vertex>\n\t#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n}\n";
6086
6087var distanceRGBA_frag = "#define DISTANCE\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n#include <common>\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main () {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}\n";
6088
6089var distanceRGBA_vert = "#define DISTANCE\nvarying vec3 vWorldPosition;\n#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinnormal_vertex>\n\t#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <worldpos_vertex>\n\t#include <clipping_planes_vertex>\n\tvWorldPosition = worldPosition.xyz;\n}\n";
6090
6091var equirect_frag = "uniform sampler2D tEquirect;\nvarying vec3 vWorldPosition;\n#include <common>\nvoid main() {\n\tvec3 direction = normalize( vWorldPosition );\n\tvec2 sampleUV;\n\tsampleUV.y = asin( clamp( direction.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\tsampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n}\n";
6092
6093var equirect_vert = "varying vec3 vWorldPosition;\n#include <common>\nvoid main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\t#include <begin_vertex>\n\t#include <project_vertex>\n}\n";
6094
6095var linedashed_frag = "uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include <common>\n#include <color_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <color_fragment>\n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <premultiplied_alpha_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n}\n";
6096
6097var linedashed_vert = "uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include <common>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <color_vertex>\n\tvLineDistance = scale * lineDistance;\n\tvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n}\n";
6098
6099var meshbasic_frag = "uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <envmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <specularmap_fragment>\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\treflectedLight.indirectDiffuse += texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include <aomap_fragment>\n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include <envmap_fragment>\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <premultiplied_alpha_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n}\n";
6100
6101var meshbasic_vert = "#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <envmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_ENVMAP\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <worldpos_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <envmap_vertex>\n\t#include <fog_vertex>\n}\n";
6102
6103var meshlambert_frag = "uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n#endif\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <envmap_pars_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <lights_pars_maps>\n#include <fog_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <shadowmask_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <specularmap_fragment>\n\t#include <emissivemap_fragment>\n\treflectedLight.indirectDiffuse = getAmbientLightIrradiance( ambientLightColor );\n\t#include <lightmap_fragment>\n\treflectedLight.indirectDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb );\n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\n\t#else\n\t\treflectedLight.directDiffuse = vLightFront;\n\t#endif\n\treflectedLight.directDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb ) * getShadowMask();\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include <envmap_fragment>\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}\n";
6104
6105var meshlambert_vert = "#define LAMBERT\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <envmap_pars_vertex>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <lights_pars_maps>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <worldpos_vertex>\n\t#include <envmap_vertex>\n\t#include <lights_lambert_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}\n";
6106
6107var meshphong_frag = "#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <envmap_pars_fragment>\n#include <gradientmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <lights_pars_maps>\n#include <lights_phong_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <specularmap_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\t#include <emissivemap_fragment>\n\t#include <lights_phong_fragment>\n\t#include <lights_fragment_begin>\n\t#include <lights_fragment_maps>\n\t#include <lights_fragment_end>\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include <envmap_fragment>\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}\n";
6108
6109var meshphong_vert = "#define PHONG\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <envmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvViewPosition = - mvPosition.xyz;\n\t#include <worldpos_vertex>\n\t#include <envmap_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}\n";
6110
6111var meshphysical_frag = "#define PHYSICAL\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifndef STANDARD\n\tuniform float clearCoat;\n\tuniform float clearCoatRoughness;\n#endif\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <envmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <cube_uv_reflection_fragment>\n#include <lights_pars_begin>\n#include <lights_pars_maps>\n#include <lights_physical_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <roughnessmap_pars_fragment>\n#include <metalnessmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <roughnessmap_fragment>\n\t#include <metalnessmap_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\t#include <emissivemap_fragment>\n\t#include <lights_physical_fragment>\n\t#include <lights_fragment_begin>\n\t#include <lights_fragment_maps>\n\t#include <lights_fragment_end>\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}\n";
6112
6113var meshphysical_vert = "#define PHYSICAL\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvViewPosition = - mvPosition.xyz;\n\t#include <worldpos_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}\n";
6114
6115var normal_frag = "#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <packing>\n#include <uv_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\nvoid main() {\n\t#include <logdepthbuf_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n}\n";
6116
6117var normal_vert = "#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}\n";
6118
6119var points_frag = "uniform vec3 diffuse;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <color_pars_fragment>\n#include <map_particle_pars_fragment>\n#include <fog_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_particle_fragment>\n\t#include <color_fragment>\n\t#include <alphatest_fragment>\n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <premultiplied_alpha_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n}\n";
6120
6121var points_vert = "uniform float size;\nuniform float scale;\n#include <common>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <color_vertex>\n\t#include <begin_vertex>\n\t#include <project_vertex>\n\t#ifdef USE_SIZEATTENUATION\n\t\tgl_PointSize = size * ( scale / - mvPosition.z );\n\t#else\n\t\tgl_PointSize = size;\n\t#endif\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <worldpos_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}\n";
6122
6123var shadow_frag = "uniform vec3 color;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <shadowmap_pars_fragment>\n#include <shadowmask_pars_fragment>\nvoid main() {\n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include <fog_fragment>\n}\n";
6124
6125var shadow_vert = "#include <fog_pars_vertex>\n#include <shadowmap_pars_vertex>\nvoid main() {\n\t#include <begin_vertex>\n\t#include <project_vertex>\n\t#include <worldpos_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}\n";
6126
6127var ShaderChunk = {
6128 alphamap_fragment: alphamap_fragment,
6129 alphamap_pars_fragment: alphamap_pars_fragment,
6130 alphatest_fragment: alphatest_fragment,
6131 aomap_fragment: aomap_fragment,
6132 aomap_pars_fragment: aomap_pars_fragment,
6133 begin_vertex: begin_vertex,
6134 beginnormal_vertex: beginnormal_vertex,
6135 bsdfs: bsdfs,
6136 bumpmap_pars_fragment: bumpmap_pars_fragment,
6137 clipping_planes_fragment: clipping_planes_fragment,
6138 clipping_planes_pars_fragment: clipping_planes_pars_fragment,
6139 clipping_planes_pars_vertex: clipping_planes_pars_vertex,
6140 clipping_planes_vertex: clipping_planes_vertex,
6141 color_fragment: color_fragment,
6142 color_pars_fragment: color_pars_fragment,
6143 color_pars_vertex: color_pars_vertex,
6144 color_vertex: color_vertex,
6145 common: common,
6146 cube_uv_reflection_fragment: cube_uv_reflection_fragment,
6147 defaultnormal_vertex: defaultnormal_vertex,
6148 displacementmap_pars_vertex: displacementmap_pars_vertex,
6149 displacementmap_vertex: displacementmap_vertex,
6150 emissivemap_fragment: emissivemap_fragment,
6151 emissivemap_pars_fragment: emissivemap_pars_fragment,
6152 encodings_fragment: encodings_fragment,
6153 encodings_pars_fragment: encodings_pars_fragment,
6154 envmap_fragment: envmap_fragment,
6155 envmap_pars_fragment: envmap_pars_fragment,
6156 envmap_pars_vertex: envmap_pars_vertex,
6157 envmap_vertex: envmap_vertex,
6158 fog_vertex: fog_vertex,
6159 fog_pars_vertex: fog_pars_vertex,
6160 fog_fragment: fog_fragment,
6161 fog_pars_fragment: fog_pars_fragment,
6162 gradientmap_pars_fragment: gradientmap_pars_fragment,
6163 lightmap_fragment: lightmap_fragment,
6164 lightmap_pars_fragment: lightmap_pars_fragment,
6165 lights_lambert_vertex: lights_lambert_vertex,
6166 lights_pars_begin: lights_pars_begin,
6167 lights_pars_maps: lights_pars_maps,
6168 lights_phong_fragment: lights_phong_fragment,
6169 lights_phong_pars_fragment: lights_phong_pars_fragment,
6170 lights_physical_fragment: lights_physical_fragment,
6171 lights_physical_pars_fragment: lights_physical_pars_fragment,
6172 lights_fragment_begin: lights_fragment_begin,
6173 lights_fragment_maps: lights_fragment_maps,
6174 lights_fragment_end: lights_fragment_end,
6175 logdepthbuf_fragment: logdepthbuf_fragment,
6176 logdepthbuf_pars_fragment: logdepthbuf_pars_fragment,
6177 logdepthbuf_pars_vertex: logdepthbuf_pars_vertex,
6178 logdepthbuf_vertex: logdepthbuf_vertex,
6179 map_fragment: map_fragment,
6180 map_pars_fragment: map_pars_fragment,
6181 map_particle_fragment: map_particle_fragment,
6182 map_particle_pars_fragment: map_particle_pars_fragment,
6183 metalnessmap_fragment: metalnessmap_fragment,
6184 metalnessmap_pars_fragment: metalnessmap_pars_fragment,
6185 morphnormal_vertex: morphnormal_vertex,
6186 morphtarget_pars_vertex: morphtarget_pars_vertex,
6187 morphtarget_vertex: morphtarget_vertex,
6188 normal_fragment_begin: normal_fragment_begin,
6189 normal_fragment_maps: normal_fragment_maps,
6190 normalmap_pars_fragment: normalmap_pars_fragment,
6191 packing: packing,
6192 premultiplied_alpha_fragment: premultiplied_alpha_fragment,
6193 project_vertex: project_vertex,
6194 dithering_fragment: dithering_fragment,
6195 dithering_pars_fragment: dithering_pars_fragment,
6196 roughnessmap_fragment: roughnessmap_fragment,
6197 roughnessmap_pars_fragment: roughnessmap_pars_fragment,
6198 shadowmap_pars_fragment: shadowmap_pars_fragment,
6199 shadowmap_pars_vertex: shadowmap_pars_vertex,
6200 shadowmap_vertex: shadowmap_vertex,
6201 shadowmask_pars_fragment: shadowmask_pars_fragment,
6202 skinbase_vertex: skinbase_vertex,
6203 skinning_pars_vertex: skinning_pars_vertex,
6204 skinning_vertex: skinning_vertex,
6205 skinnormal_vertex: skinnormal_vertex,
6206 specularmap_fragment: specularmap_fragment,
6207 specularmap_pars_fragment: specularmap_pars_fragment,
6208 tonemapping_fragment: tonemapping_fragment,
6209 tonemapping_pars_fragment: tonemapping_pars_fragment,
6210 uv_pars_fragment: uv_pars_fragment,
6211 uv_pars_vertex: uv_pars_vertex,
6212 uv_vertex: uv_vertex,
6213 uv2_pars_fragment: uv2_pars_fragment,
6214 uv2_pars_vertex: uv2_pars_vertex,
6215 uv2_vertex: uv2_vertex,
6216 worldpos_vertex: worldpos_vertex,
6217
6218 cube_frag: cube_frag,
6219 cube_vert: cube_vert,
6220 depth_frag: depth_frag,
6221 depth_vert: depth_vert,
6222 distanceRGBA_frag: distanceRGBA_frag,
6223 distanceRGBA_vert: distanceRGBA_vert,
6224 equirect_frag: equirect_frag,
6225 equirect_vert: equirect_vert,
6226 linedashed_frag: linedashed_frag,
6227 linedashed_vert: linedashed_vert,
6228 meshbasic_frag: meshbasic_frag,
6229 meshbasic_vert: meshbasic_vert,
6230 meshlambert_frag: meshlambert_frag,
6231 meshlambert_vert: meshlambert_vert,
6232 meshphong_frag: meshphong_frag,
6233 meshphong_vert: meshphong_vert,
6234 meshphysical_frag: meshphysical_frag,
6235 meshphysical_vert: meshphysical_vert,
6236 normal_frag: normal_frag,
6237 normal_vert: normal_vert,
6238 points_frag: points_frag,
6239 points_vert: points_vert,
6240 shadow_frag: shadow_frag,
6241 shadow_vert: shadow_vert
6242};
6243
6244/**
6245 * Uniform Utilities
6246 */
6247
6248var UniformsUtils = {
6249
6250 merge: function ( uniforms ) {
6251
6252 var merged = {};
6253
6254 for ( var u = 0; u < uniforms.length; u ++ ) {
6255
6256 var tmp = this.clone( uniforms[ u ] );
6257
6258 for ( var p in tmp ) {
6259
6260 merged[ p ] = tmp[ p ];
6261
6262 }
6263
6264 }
6265
6266 return merged;
6267
6268 },
6269
6270 clone: function ( uniforms_src ) {
6271
6272 var uniforms_dst = {};
6273
6274 for ( var u in uniforms_src ) {
6275
6276 uniforms_dst[ u ] = {};
6277
6278 for ( var p in uniforms_src[ u ] ) {
6279
6280 var parameter_src = uniforms_src[ u ][ p ];
6281
6282 if ( parameter_src && ( parameter_src.isColor ||
6283 parameter_src.isMatrix3 || parameter_src.isMatrix4 ||
6284 parameter_src.isVector2 || parameter_src.isVector3 || parameter_src.isVector4 ||
6285 parameter_src.isTexture ) ) {
6286
6287 uniforms_dst[ u ][ p ] = parameter_src.clone();
6288
6289 } else if ( Array.isArray( parameter_src ) ) {
6290
6291 uniforms_dst[ u ][ p ] = parameter_src.slice();
6292
6293 } else {
6294
6295 uniforms_dst[ u ][ p ] = parameter_src;
6296
6297 }
6298
6299 }
6300
6301 }
6302
6303 return uniforms_dst;
6304
6305 }
6306
6307};
6308
6309/**
6310 * @author mrdoob / http://mrdoob.com/
6311 */
6312
6313var ColorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF,
6314 'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2,
6315 'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50,
6316 'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B,
6317 'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B,
6318 'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F,
6319 'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3,
6320 'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222,
6321 'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700,
6322 'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4,
6323 'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00,
6324 'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3,
6325 'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA,
6326 'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32,
6327 'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3,
6328 'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC,
6329 'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD,
6330 'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6,
6331 'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9,
6332 'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F,
6333 'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE,
6334 'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA,
6335 'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0,
6336 'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 };
6337
6338function Color( r, g, b ) {
6339
6340 if ( g === undefined && b === undefined ) {
6341
6342 // r is THREE.Color, hex or string
6343 return this.set( r );
6344
6345 }
6346
6347 return this.setRGB( r, g, b );
6348
6349}
6350
6351Object.assign( Color.prototype, {
6352
6353 isColor: true,
6354
6355 r: 1, g: 1, b: 1,
6356
6357 set: function ( value ) {
6358
6359 if ( value && value.isColor ) {
6360
6361 this.copy( value );
6362
6363 } else if ( typeof value === 'number' ) {
6364
6365 this.setHex( value );
6366
6367 } else if ( typeof value === 'string' ) {
6368
6369 this.setStyle( value );
6370
6371 }
6372
6373 return this;
6374
6375 },
6376
6377 setScalar: function ( scalar ) {
6378
6379 this.r = scalar;
6380 this.g = scalar;
6381 this.b = scalar;
6382
6383 return this;
6384
6385 },
6386
6387 setHex: function ( hex ) {
6388
6389 hex = Math.floor( hex );
6390
6391 this.r = ( hex >> 16 & 255 ) / 255;
6392 this.g = ( hex >> 8 & 255 ) / 255;
6393 this.b = ( hex & 255 ) / 255;
6394
6395 return this;
6396
6397 },
6398
6399 setRGB: function ( r, g, b ) {
6400
6401 this.r = r;
6402 this.g = g;
6403 this.b = b;
6404
6405 return this;
6406
6407 },
6408
6409 setHSL: function () {
6410
6411 function hue2rgb( p, q, t ) {
6412
6413 if ( t < 0 ) t += 1;
6414 if ( t > 1 ) t -= 1;
6415 if ( t < 1 / 6 ) return p + ( q - p ) * 6 * t;
6416 if ( t < 1 / 2 ) return q;
6417 if ( t < 2 / 3 ) return p + ( q - p ) * 6 * ( 2 / 3 - t );
6418 return p;
6419
6420 }
6421
6422 return function setHSL( h, s, l ) {
6423
6424 // h,s,l ranges are in 0.0 - 1.0
6425 h = _Math.euclideanModulo( h, 1 );
6426 s = _Math.clamp( s, 0, 1 );
6427 l = _Math.clamp( l, 0, 1 );
6428
6429 if ( s === 0 ) {
6430
6431 this.r = this.g = this.b = l;
6432
6433 } else {
6434
6435 var p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s );
6436 var q = ( 2 * l ) - p;
6437
6438 this.r = hue2rgb( q, p, h + 1 / 3 );
6439 this.g = hue2rgb( q, p, h );
6440 this.b = hue2rgb( q, p, h - 1 / 3 );
6441
6442 }
6443
6444 return this;
6445
6446 };
6447
6448 }(),
6449
6450 setStyle: function ( style ) {
6451
6452 function handleAlpha( string ) {
6453
6454 if ( string === undefined ) return;
6455
6456 if ( parseFloat( string ) < 1 ) {
6457
6458 console.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' );
6459
6460 }
6461
6462 }
6463
6464
6465 var m;
6466
6467 if ( m = /^((?:rgb|hsl)a?)\(\s*([^\)]*)\)/.exec( style ) ) {
6468
6469 // rgb / hsl
6470
6471 var color;
6472 var name = m[ 1 ];
6473 var components = m[ 2 ];
6474
6475 switch ( name ) {
6476
6477 case 'rgb':
6478 case 'rgba':
6479
6480 if ( color = /^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) {
6481
6482 // rgb(255,0,0) rgba(255,0,0,0.5)
6483 this.r = Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255;
6484 this.g = Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255;
6485 this.b = Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255;
6486
6487 handleAlpha( color[ 5 ] );
6488
6489 return this;
6490
6491 }
6492
6493 if ( color = /^(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) {
6494
6495 // rgb(100%,0%,0%) rgba(100%,0%,0%,0.5)
6496 this.r = Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100;
6497 this.g = Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100;
6498 this.b = Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100;
6499
6500 handleAlpha( color[ 5 ] );
6501
6502 return this;
6503
6504 }
6505
6506 break;
6507
6508 case 'hsl':
6509 case 'hsla':
6510
6511 if ( color = /^([0-9]*\.?[0-9]+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) {
6512
6513 // hsl(120,50%,50%) hsla(120,50%,50%,0.5)
6514 var h = parseFloat( color[ 1 ] ) / 360;
6515 var s = parseInt( color[ 2 ], 10 ) / 100;
6516 var l = parseInt( color[ 3 ], 10 ) / 100;
6517
6518 handleAlpha( color[ 5 ] );
6519
6520 return this.setHSL( h, s, l );
6521
6522 }
6523
6524 break;
6525
6526 }
6527
6528 } else if ( m = /^\#([A-Fa-f0-9]+)$/.exec( style ) ) {
6529
6530 // hex color
6531
6532 var hex = m[ 1 ];
6533 var size = hex.length;
6534
6535 if ( size === 3 ) {
6536
6537 // #ff0
6538 this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 0 ), 16 ) / 255;
6539 this.g = parseInt( hex.charAt( 1 ) + hex.charAt( 1 ), 16 ) / 255;
6540 this.b = parseInt( hex.charAt( 2 ) + hex.charAt( 2 ), 16 ) / 255;
6541
6542 return this;
6543
6544 } else if ( size === 6 ) {
6545
6546 // #ff0000
6547 this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 1 ), 16 ) / 255;
6548 this.g = parseInt( hex.charAt( 2 ) + hex.charAt( 3 ), 16 ) / 255;
6549 this.b = parseInt( hex.charAt( 4 ) + hex.charAt( 5 ), 16 ) / 255;
6550
6551 return this;
6552
6553 }
6554
6555 }
6556
6557 if ( style && style.length > 0 ) {
6558
6559 // color keywords
6560 var hex = ColorKeywords[ style ];
6561
6562 if ( hex !== undefined ) {
6563
6564 // red
6565 this.setHex( hex );
6566
6567 } else {
6568
6569 // unknown color
6570 console.warn( 'THREE.Color: Unknown color ' + style );
6571
6572 }
6573
6574 }
6575
6576 return this;
6577
6578 },
6579
6580 clone: function () {
6581
6582 return new this.constructor( this.r, this.g, this.b );
6583
6584 },
6585
6586 copy: function ( color ) {
6587
6588 this.r = color.r;
6589 this.g = color.g;
6590 this.b = color.b;
6591
6592 return this;
6593
6594 },
6595
6596 copyGammaToLinear: function ( color, gammaFactor ) {
6597
6598 if ( gammaFactor === undefined ) gammaFactor = 2.0;
6599
6600 this.r = Math.pow( color.r, gammaFactor );
6601 this.g = Math.pow( color.g, gammaFactor );
6602 this.b = Math.pow( color.b, gammaFactor );
6603
6604 return this;
6605
6606 },
6607
6608 copyLinearToGamma: function ( color, gammaFactor ) {
6609
6610 if ( gammaFactor === undefined ) gammaFactor = 2.0;
6611
6612 var safeInverse = ( gammaFactor > 0 ) ? ( 1.0 / gammaFactor ) : 1.0;
6613
6614 this.r = Math.pow( color.r, safeInverse );
6615 this.g = Math.pow( color.g, safeInverse );
6616 this.b = Math.pow( color.b, safeInverse );
6617
6618 return this;
6619
6620 },
6621
6622 convertGammaToLinear: function () {
6623
6624 var r = this.r, g = this.g, b = this.b;
6625
6626 this.r = r * r;
6627 this.g = g * g;
6628 this.b = b * b;
6629
6630 return this;
6631
6632 },
6633
6634 convertLinearToGamma: function () {
6635
6636 this.r = Math.sqrt( this.r );
6637 this.g = Math.sqrt( this.g );
6638 this.b = Math.sqrt( this.b );
6639
6640 return this;
6641
6642 },
6643
6644 getHex: function () {
6645
6646 return ( this.r * 255 ) << 16 ^ ( this.g * 255 ) << 8 ^ ( this.b * 255 ) << 0;
6647
6648 },
6649
6650 getHexString: function () {
6651
6652 return ( '000000' + this.getHex().toString( 16 ) ).slice( - 6 );
6653
6654 },
6655
6656 getHSL: function ( target ) {
6657
6658 // h,s,l ranges are in 0.0 - 1.0
6659
6660 if ( target === undefined ) {
6661
6662 console.warn( 'THREE.Color: .getHSL() target is now required' );
6663 target = { h: 0, s: 0, l: 0 };
6664
6665 }
6666
6667 var r = this.r, g = this.g, b = this.b;
6668
6669 var max = Math.max( r, g, b );
6670 var min = Math.min( r, g, b );
6671
6672 var hue, saturation;
6673 var lightness = ( min + max ) / 2.0;
6674
6675 if ( min === max ) {
6676
6677 hue = 0;
6678 saturation = 0;
6679
6680 } else {
6681
6682 var delta = max - min;
6683
6684 saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min );
6685
6686 switch ( max ) {
6687
6688 case r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break;
6689 case g: hue = ( b - r ) / delta + 2; break;
6690 case b: hue = ( r - g ) / delta + 4; break;
6691
6692 }
6693
6694 hue /= 6;
6695
6696 }
6697
6698 target.h = hue;
6699 target.s = saturation;
6700 target.l = lightness;
6701
6702 return target;
6703
6704 },
6705
6706 getStyle: function () {
6707
6708 return 'rgb(' + ( ( this.r * 255 ) | 0 ) + ',' + ( ( this.g * 255 ) | 0 ) + ',' + ( ( this.b * 255 ) | 0 ) + ')';
6709
6710 },
6711
6712 offsetHSL: function () {
6713
6714 var hsl = {};
6715
6716 return function ( h, s, l ) {
6717
6718 this.getHSL( hsl );
6719
6720 hsl.h += h; hsl.s += s; hsl.l += l;
6721
6722 this.setHSL( hsl.h, hsl.s, hsl.l );
6723
6724 return this;
6725
6726 };
6727
6728 }(),
6729
6730 add: function ( color ) {
6731
6732 this.r += color.r;
6733 this.g += color.g;
6734 this.b += color.b;
6735
6736 return this;
6737
6738 },
6739
6740 addColors: function ( color1, color2 ) {
6741
6742 this.r = color1.r + color2.r;
6743 this.g = color1.g + color2.g;
6744 this.b = color1.b + color2.b;
6745
6746 return this;
6747
6748 },
6749
6750 addScalar: function ( s ) {
6751
6752 this.r += s;
6753 this.g += s;
6754 this.b += s;
6755
6756 return this;
6757
6758 },
6759
6760 sub: function ( color ) {
6761
6762 this.r = Math.max( 0, this.r - color.r );
6763 this.g = Math.max( 0, this.g - color.g );
6764 this.b = Math.max( 0, this.b - color.b );
6765
6766 return this;
6767
6768 },
6769
6770 multiply: function ( color ) {
6771
6772 this.r *= color.r;
6773 this.g *= color.g;
6774 this.b *= color.b;
6775
6776 return this;
6777
6778 },
6779
6780 multiplyScalar: function ( s ) {
6781
6782 this.r *= s;
6783 this.g *= s;
6784 this.b *= s;
6785
6786 return this;
6787
6788 },
6789
6790 lerp: function ( color, alpha ) {
6791
6792 this.r += ( color.r - this.r ) * alpha;
6793 this.g += ( color.g - this.g ) * alpha;
6794 this.b += ( color.b - this.b ) * alpha;
6795
6796 return this;
6797
6798 },
6799
6800 equals: function ( c ) {
6801
6802 return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b );
6803
6804 },
6805
6806 fromArray: function ( array, offset ) {
6807
6808 if ( offset === undefined ) offset = 0;
6809
6810 this.r = array[ offset ];
6811 this.g = array[ offset + 1 ];
6812 this.b = array[ offset + 2 ];
6813
6814 return this;
6815
6816 },
6817
6818 toArray: function ( array, offset ) {
6819
6820 if ( array === undefined ) array = [];
6821 if ( offset === undefined ) offset = 0;
6822
6823 array[ offset ] = this.r;
6824 array[ offset + 1 ] = this.g;
6825 array[ offset + 2 ] = this.b;
6826
6827 return array;
6828
6829 },
6830
6831 toJSON: function () {
6832
6833 return this.getHex();
6834
6835 }
6836
6837} );
6838
6839/**
6840 * Uniforms library for shared webgl shaders
6841 */
6842
6843var UniformsLib = {
6844
6845 common: {
6846
6847 diffuse: { value: new Color( 0xeeeeee ) },
6848 opacity: { value: 1.0 },
6849
6850 map: { value: null },
6851 uvTransform: { value: new Matrix3() },
6852
6853 alphaMap: { value: null },
6854
6855 },
6856
6857 specularmap: {
6858
6859 specularMap: { value: null },
6860
6861 },
6862
6863 envmap: {
6864
6865 envMap: { value: null },
6866 flipEnvMap: { value: - 1 },
6867 reflectivity: { value: 1.0 },
6868 refractionRatio: { value: 0.98 },
6869 maxMipLevel: { value: 0 }
6870
6871 },
6872
6873 aomap: {
6874
6875 aoMap: { value: null },
6876 aoMapIntensity: { value: 1 }
6877
6878 },
6879
6880 lightmap: {
6881
6882 lightMap: { value: null },
6883 lightMapIntensity: { value: 1 }
6884
6885 },
6886
6887 emissivemap: {
6888
6889 emissiveMap: { value: null }
6890
6891 },
6892
6893 bumpmap: {
6894
6895 bumpMap: { value: null },
6896 bumpScale: { value: 1 }
6897
6898 },
6899
6900 normalmap: {
6901
6902 normalMap: { value: null },
6903 normalScale: { value: new Vector2( 1, 1 ) }
6904
6905 },
6906
6907 displacementmap: {
6908
6909 displacementMap: { value: null },
6910 displacementScale: { value: 1 },
6911 displacementBias: { value: 0 }
6912
6913 },
6914
6915 roughnessmap: {
6916
6917 roughnessMap: { value: null }
6918
6919 },
6920
6921 metalnessmap: {
6922
6923 metalnessMap: { value: null }
6924
6925 },
6926
6927 gradientmap: {
6928
6929 gradientMap: { value: null }
6930
6931 },
6932
6933 fog: {
6934
6935 fogDensity: { value: 0.00025 },
6936 fogNear: { value: 1 },
6937 fogFar: { value: 2000 },
6938 fogColor: { value: new Color( 0xffffff ) }
6939
6940 },
6941
6942 lights: {
6943
6944 ambientLightColor: { value: [] },
6945
6946 directionalLights: { value: [], properties: {
6947 direction: {},
6948 color: {},
6949
6950 shadow: {},
6951 shadowBias: {},
6952 shadowRadius: {},
6953 shadowMapSize: {}
6954 } },
6955
6956 directionalShadowMap: { value: [] },
6957 directionalShadowMatrix: { value: [] },
6958
6959 spotLights: { value: [], properties: {
6960 color: {},
6961 position: {},
6962 direction: {},
6963 distance: {},
6964 coneCos: {},
6965 penumbraCos: {},
6966 decay: {},
6967
6968 shadow: {},
6969 shadowBias: {},
6970 shadowRadius: {},
6971 shadowMapSize: {}
6972 } },
6973
6974 spotShadowMap: { value: [] },
6975 spotShadowMatrix: { value: [] },
6976
6977 pointLights: { value: [], properties: {
6978 color: {},
6979 position: {},
6980 decay: {},
6981 distance: {},
6982
6983 shadow: {},
6984 shadowBias: {},
6985 shadowRadius: {},
6986 shadowMapSize: {},
6987 shadowCameraNear: {},
6988 shadowCameraFar: {}
6989 } },
6990
6991 pointShadowMap: { value: [] },
6992 pointShadowMatrix: { value: [] },
6993
6994 hemisphereLights: { value: [], properties: {
6995 direction: {},
6996 skyColor: {},
6997 groundColor: {}
6998 } },
6999
7000 // TODO (abelnation): RectAreaLight BRDF data needs to be moved from example to main src
7001 rectAreaLights: { value: [], properties: {
7002 color: {},
7003 position: {},
7004 width: {},
7005 height: {}
7006 } }
7007
7008 },
7009
7010 points: {
7011
7012 diffuse: { value: new Color( 0xeeeeee ) },
7013 opacity: { value: 1.0 },
7014 size: { value: 1.0 },
7015 scale: { value: 1.0 },
7016 map: { value: null },
7017 uvTransform: { value: new Matrix3() }
7018
7019 }
7020
7021};
7022
7023/**
7024 * @author alteredq / http://alteredqualia.com/
7025 * @author mrdoob / http://mrdoob.com/
7026 * @author mikael emtinger / http://gomo.se/
7027 */
7028
7029var ShaderLib = {
7030
7031 basic: {
7032
7033 uniforms: UniformsUtils.merge( [
7034 UniformsLib.common,
7035 UniformsLib.specularmap,
7036 UniformsLib.envmap,
7037 UniformsLib.aomap,
7038 UniformsLib.lightmap,
7039 UniformsLib.fog
7040 ] ),
7041
7042 vertexShader: ShaderChunk.meshbasic_vert,
7043 fragmentShader: ShaderChunk.meshbasic_frag
7044
7045 },
7046
7047 lambert: {
7048
7049 uniforms: UniformsUtils.merge( [
7050 UniformsLib.common,
7051 UniformsLib.specularmap,
7052 UniformsLib.envmap,
7053 UniformsLib.aomap,
7054 UniformsLib.lightmap,
7055 UniformsLib.emissivemap,
7056 UniformsLib.fog,
7057 UniformsLib.lights,
7058 {
7059 emissive: { value: new Color( 0x000000 ) }
7060 }
7061 ] ),
7062
7063 vertexShader: ShaderChunk.meshlambert_vert,
7064 fragmentShader: ShaderChunk.meshlambert_frag
7065
7066 },
7067
7068 phong: {
7069
7070 uniforms: UniformsUtils.merge( [
7071 UniformsLib.common,
7072 UniformsLib.specularmap,
7073 UniformsLib.envmap,
7074 UniformsLib.aomap,
7075 UniformsLib.lightmap,
7076 UniformsLib.emissivemap,
7077 UniformsLib.bumpmap,
7078 UniformsLib.normalmap,
7079 UniformsLib.displacementmap,
7080 UniformsLib.gradientmap,
7081 UniformsLib.fog,
7082 UniformsLib.lights,
7083 {
7084 emissive: { value: new Color( 0x000000 ) },
7085 specular: { value: new Color( 0x111111 ) },
7086 shininess: { value: 30 }
7087 }
7088 ] ),
7089
7090 vertexShader: ShaderChunk.meshphong_vert,
7091 fragmentShader: ShaderChunk.meshphong_frag
7092
7093 },
7094
7095 standard: {
7096
7097 uniforms: UniformsUtils.merge( [
7098 UniformsLib.common,
7099 UniformsLib.envmap,
7100 UniformsLib.aomap,
7101 UniformsLib.lightmap,
7102 UniformsLib.emissivemap,
7103 UniformsLib.bumpmap,
7104 UniformsLib.normalmap,
7105 UniformsLib.displacementmap,
7106 UniformsLib.roughnessmap,
7107 UniformsLib.metalnessmap,
7108 UniformsLib.fog,
7109 UniformsLib.lights,
7110 {
7111 emissive: { value: new Color( 0x000000 ) },
7112 roughness: { value: 0.5 },
7113 metalness: { value: 0.5 },
7114 envMapIntensity: { value: 1 } // temporary
7115 }
7116 ] ),
7117
7118 vertexShader: ShaderChunk.meshphysical_vert,
7119 fragmentShader: ShaderChunk.meshphysical_frag
7120
7121 },
7122
7123 points: {
7124
7125 uniforms: UniformsUtils.merge( [
7126 UniformsLib.points,
7127 UniformsLib.fog
7128 ] ),
7129
7130 vertexShader: ShaderChunk.points_vert,
7131 fragmentShader: ShaderChunk.points_frag
7132
7133 },
7134
7135 dashed: {
7136
7137 uniforms: UniformsUtils.merge( [
7138 UniformsLib.common,
7139 UniformsLib.fog,
7140 {
7141 scale: { value: 1 },
7142 dashSize: { value: 1 },
7143 totalSize: { value: 2 }
7144 }
7145 ] ),
7146
7147 vertexShader: ShaderChunk.linedashed_vert,
7148 fragmentShader: ShaderChunk.linedashed_frag
7149
7150 },
7151
7152 depth: {
7153
7154 uniforms: UniformsUtils.merge( [
7155 UniformsLib.common,
7156 UniformsLib.displacementmap
7157 ] ),
7158
7159 vertexShader: ShaderChunk.depth_vert,
7160 fragmentShader: ShaderChunk.depth_frag
7161
7162 },
7163
7164 normal: {
7165
7166 uniforms: UniformsUtils.merge( [
7167 UniformsLib.common,
7168 UniformsLib.bumpmap,
7169 UniformsLib.normalmap,
7170 UniformsLib.displacementmap,
7171 {
7172 opacity: { value: 1.0 }
7173 }
7174 ] ),
7175
7176 vertexShader: ShaderChunk.normal_vert,
7177 fragmentShader: ShaderChunk.normal_frag
7178
7179 },
7180
7181 /* -------------------------------------------------------------------------
7182 // Cube map shader
7183 ------------------------------------------------------------------------- */
7184
7185 cube: {
7186
7187 uniforms: {
7188 tCube: { value: null },
7189 tFlip: { value: - 1 },
7190 opacity: { value: 1.0 }
7191 },
7192
7193 vertexShader: ShaderChunk.cube_vert,
7194 fragmentShader: ShaderChunk.cube_frag
7195
7196 },
7197
7198 equirect: {
7199
7200 uniforms: {
7201 tEquirect: { value: null },
7202 },
7203
7204 vertexShader: ShaderChunk.equirect_vert,
7205 fragmentShader: ShaderChunk.equirect_frag
7206
7207 },
7208
7209 distanceRGBA: {
7210
7211 uniforms: UniformsUtils.merge( [
7212 UniformsLib.common,
7213 UniformsLib.displacementmap,
7214 {
7215 referencePosition: { value: new Vector3() },
7216 nearDistance: { value: 1 },
7217 farDistance: { value: 1000 }
7218 }
7219 ] ),
7220
7221 vertexShader: ShaderChunk.distanceRGBA_vert,
7222 fragmentShader: ShaderChunk.distanceRGBA_frag
7223
7224 },
7225
7226 shadow: {
7227
7228 uniforms: UniformsUtils.merge( [
7229 UniformsLib.lights,
7230 UniformsLib.fog,
7231 {
7232 color: { value: new Color( 0x00000 ) },
7233 opacity: { value: 1.0 }
7234 },
7235 ] ),
7236
7237 vertexShader: ShaderChunk.shadow_vert,
7238 fragmentShader: ShaderChunk.shadow_frag
7239
7240 }
7241
7242};
7243
7244ShaderLib.physical = {
7245
7246 uniforms: UniformsUtils.merge( [
7247 ShaderLib.standard.uniforms,
7248 {
7249 clearCoat: { value: 0 },
7250 clearCoatRoughness: { value: 0 }
7251 }
7252 ] ),
7253
7254 vertexShader: ShaderChunk.meshphysical_vert,
7255 fragmentShader: ShaderChunk.meshphysical_frag
7256
7257};
7258
7259/**
7260 * @author mrdoob / http://mrdoob.com/
7261 */
7262
7263function WebGLAttributes( gl ) {
7264
7265 var buffers = new WeakMap();
7266
7267 function createBuffer( attribute, bufferType ) {
7268
7269 var array = attribute.array;
7270 var usage = attribute.dynamic ? gl.DYNAMIC_DRAW : gl.STATIC_DRAW;
7271
7272 var buffer = gl.createBuffer();
7273
7274 gl.bindBuffer( bufferType, buffer );
7275 gl.bufferData( bufferType, array, usage );
7276
7277 attribute.onUploadCallback();
7278
7279 var type = gl.FLOAT;
7280
7281 if ( array instanceof Float32Array ) {
7282
7283 type = gl.FLOAT;
7284
7285 } else if ( array instanceof Float64Array ) {
7286
7287 console.warn( 'THREE.WebGLAttributes: Unsupported data buffer format: Float64Array.' );
7288
7289 } else if ( array instanceof Uint16Array ) {
7290
7291 type = gl.UNSIGNED_SHORT;
7292
7293 } else if ( array instanceof Int16Array ) {
7294
7295 type = gl.SHORT;
7296
7297 } else if ( array instanceof Uint32Array ) {
7298
7299 type = gl.UNSIGNED_INT;
7300
7301 } else if ( array instanceof Int32Array ) {
7302
7303 type = gl.INT;
7304
7305 } else if ( array instanceof Int8Array ) {
7306
7307 type = gl.BYTE;
7308
7309 } else if ( array instanceof Uint8Array ) {
7310
7311 type = gl.UNSIGNED_BYTE;
7312
7313 }
7314
7315 return {
7316 buffer: buffer,
7317 type: type,
7318 bytesPerElement: array.BYTES_PER_ELEMENT,
7319 version: attribute.version
7320 };
7321
7322 }
7323
7324 function updateBuffer( buffer, attribute, bufferType ) {
7325
7326 var array = attribute.array;
7327 var updateRange = attribute.updateRange;
7328
7329 gl.bindBuffer( bufferType, buffer );
7330
7331 if ( attribute.dynamic === false ) {
7332
7333 gl.bufferData( bufferType, array, gl.STATIC_DRAW );
7334
7335 } else if ( updateRange.count === - 1 ) {
7336
7337 // Not using update ranges
7338
7339 gl.bufferSubData( bufferType, 0, array );
7340
7341 } else if ( updateRange.count === 0 ) {
7342
7343 console.error( 'THREE.WebGLObjects.updateBuffer: dynamic THREE.BufferAttribute marked as needsUpdate but updateRange.count is 0, ensure you are using set methods or updating manually.' );
7344
7345 } else {
7346
7347 gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT,
7348 array.subarray( updateRange.offset, updateRange.offset + updateRange.count ) );
7349
7350 updateRange.count = - 1; // reset range
7351
7352 }
7353
7354 }
7355
7356 //
7357
7358 function get( attribute ) {
7359
7360 if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
7361
7362 return buffers.get( attribute );
7363
7364 }
7365
7366 function remove( attribute ) {
7367
7368 if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
7369
7370 var data = buffers.get( attribute );
7371
7372 if ( data ) {
7373
7374 gl.deleteBuffer( data.buffer );
7375
7376 buffers.delete( attribute );
7377
7378 }
7379
7380 }
7381
7382 function update( attribute, bufferType ) {
7383
7384 if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
7385
7386 var data = buffers.get( attribute );
7387
7388 if ( data === undefined ) {
7389
7390 buffers.set( attribute, createBuffer( attribute, bufferType ) );
7391
7392 } else if ( data.version < attribute.version ) {
7393
7394 updateBuffer( data.buffer, attribute, bufferType );
7395
7396 data.version = attribute.version;
7397
7398 }
7399
7400 }
7401
7402 return {
7403
7404 get: get,
7405 remove: remove,
7406 update: update
7407
7408 };
7409
7410}
7411
7412/**
7413 * @author mrdoob / http://mrdoob.com/
7414 * @author WestLangley / http://github.com/WestLangley
7415 * @author bhouston / http://clara.io
7416 */
7417
7418function Euler( x, y, z, order ) {
7419
7420 this._x = x || 0;
7421 this._y = y || 0;
7422 this._z = z || 0;
7423 this._order = order || Euler.DefaultOrder;
7424
7425}
7426
7427Euler.RotationOrders = [ 'XYZ', 'YZX', 'ZXY', 'XZY', 'YXZ', 'ZYX' ];
7428
7429Euler.DefaultOrder = 'XYZ';
7430
7431Object.defineProperties( Euler.prototype, {
7432
7433 x: {
7434
7435 get: function () {
7436
7437 return this._x;
7438
7439 },
7440
7441 set: function ( value ) {
7442
7443 this._x = value;
7444 this.onChangeCallback();
7445
7446 }
7447
7448 },
7449
7450 y: {
7451
7452 get: function () {
7453
7454 return this._y;
7455
7456 },
7457
7458 set: function ( value ) {
7459
7460 this._y = value;
7461 this.onChangeCallback();
7462
7463 }
7464
7465 },
7466
7467 z: {
7468
7469 get: function () {
7470
7471 return this._z;
7472
7473 },
7474
7475 set: function ( value ) {
7476
7477 this._z = value;
7478 this.onChangeCallback();
7479
7480 }
7481
7482 },
7483
7484 order: {
7485
7486 get: function () {
7487
7488 return this._order;
7489
7490 },
7491
7492 set: function ( value ) {
7493
7494 this._order = value;
7495 this.onChangeCallback();
7496
7497 }
7498
7499 }
7500
7501} );
7502
7503Object.assign( Euler.prototype, {
7504
7505 isEuler: true,
7506
7507 set: function ( x, y, z, order ) {
7508
7509 this._x = x;
7510 this._y = y;
7511 this._z = z;
7512 this._order = order || this._order;
7513
7514 this.onChangeCallback();
7515
7516 return this;
7517
7518 },
7519
7520 clone: function () {
7521
7522 return new this.constructor( this._x, this._y, this._z, this._order );
7523
7524 },
7525
7526 copy: function ( euler ) {
7527
7528 this._x = euler._x;
7529 this._y = euler._y;
7530 this._z = euler._z;
7531 this._order = euler._order;
7532
7533 this.onChangeCallback();
7534
7535 return this;
7536
7537 },
7538
7539 setFromRotationMatrix: function ( m, order, update ) {
7540
7541 var clamp = _Math.clamp;
7542
7543 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
7544
7545 var te = m.elements;
7546 var m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ];
7547 var m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ];
7548 var m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
7549
7550 order = order || this._order;
7551
7552 if ( order === 'XYZ' ) {
7553
7554 this._y = Math.asin( clamp( m13, - 1, 1 ) );
7555
7556 if ( Math.abs( m13 ) < 0.99999 ) {
7557
7558 this._x = Math.atan2( - m23, m33 );
7559 this._z = Math.atan2( - m12, m11 );
7560
7561 } else {
7562
7563 this._x = Math.atan2( m32, m22 );
7564 this._z = 0;
7565
7566 }
7567
7568 } else if ( order === 'YXZ' ) {
7569
7570 this._x = Math.asin( - clamp( m23, - 1, 1 ) );
7571
7572 if ( Math.abs( m23 ) < 0.99999 ) {
7573
7574 this._y = Math.atan2( m13, m33 );
7575 this._z = Math.atan2( m21, m22 );
7576
7577 } else {
7578
7579 this._y = Math.atan2( - m31, m11 );
7580 this._z = 0;
7581
7582 }
7583
7584 } else if ( order === 'ZXY' ) {
7585
7586 this._x = Math.asin( clamp( m32, - 1, 1 ) );
7587
7588 if ( Math.abs( m32 ) < 0.99999 ) {
7589
7590 this._y = Math.atan2( - m31, m33 );
7591 this._z = Math.atan2( - m12, m22 );
7592
7593 } else {
7594
7595 this._y = 0;
7596 this._z = Math.atan2( m21, m11 );
7597
7598 }
7599
7600 } else if ( order === 'ZYX' ) {
7601
7602 this._y = Math.asin( - clamp( m31, - 1, 1 ) );
7603
7604 if ( Math.abs( m31 ) < 0.99999 ) {
7605
7606 this._x = Math.atan2( m32, m33 );
7607 this._z = Math.atan2( m21, m11 );
7608
7609 } else {
7610
7611 this._x = 0;
7612 this._z = Math.atan2( - m12, m22 );
7613
7614 }
7615
7616 } else if ( order === 'YZX' ) {
7617
7618 this._z = Math.asin( clamp( m21, - 1, 1 ) );
7619
7620 if ( Math.abs( m21 ) < 0.99999 ) {
7621
7622 this._x = Math.atan2( - m23, m22 );
7623 this._y = Math.atan2( - m31, m11 );
7624
7625 } else {
7626
7627 this._x = 0;
7628 this._y = Math.atan2( m13, m33 );
7629
7630 }
7631
7632 } else if ( order === 'XZY' ) {
7633
7634 this._z = Math.asin( - clamp( m12, - 1, 1 ) );
7635
7636 if ( Math.abs( m12 ) < 0.99999 ) {
7637
7638 this._x = Math.atan2( m32, m22 );
7639 this._y = Math.atan2( m13, m11 );
7640
7641 } else {
7642
7643 this._x = Math.atan2( - m23, m33 );
7644 this._y = 0;
7645
7646 }
7647
7648 } else {
7649
7650 console.warn( 'THREE.Euler: .setFromRotationMatrix() given unsupported order: ' + order );
7651
7652 }
7653
7654 this._order = order;
7655
7656 if ( update !== false ) this.onChangeCallback();
7657
7658 return this;
7659
7660 },
7661
7662 setFromQuaternion: function () {
7663
7664 var matrix = new Matrix4();
7665
7666 return function setFromQuaternion( q, order, update ) {
7667
7668 matrix.makeRotationFromQuaternion( q );
7669
7670 return this.setFromRotationMatrix( matrix, order, update );
7671
7672 };
7673
7674 }(),
7675
7676 setFromVector3: function ( v, order ) {
7677
7678 return this.set( v.x, v.y, v.z, order || this._order );
7679
7680 },
7681
7682 reorder: function () {
7683
7684 // WARNING: this discards revolution information -bhouston
7685
7686 var q = new Quaternion();
7687
7688 return function reorder( newOrder ) {
7689
7690 q.setFromEuler( this );
7691
7692 return this.setFromQuaternion( q, newOrder );
7693
7694 };
7695
7696 }(),
7697
7698 equals: function ( euler ) {
7699
7700 return ( euler._x === this._x ) && ( euler._y === this._y ) && ( euler._z === this._z ) && ( euler._order === this._order );
7701
7702 },
7703
7704 fromArray: function ( array ) {
7705
7706 this._x = array[ 0 ];
7707 this._y = array[ 1 ];
7708 this._z = array[ 2 ];
7709 if ( array[ 3 ] !== undefined ) this._order = array[ 3 ];
7710
7711 this.onChangeCallback();
7712
7713 return this;
7714
7715 },
7716
7717 toArray: function ( array, offset ) {
7718
7719 if ( array === undefined ) array = [];
7720 if ( offset === undefined ) offset = 0;
7721
7722 array[ offset ] = this._x;
7723 array[ offset + 1 ] = this._y;
7724 array[ offset + 2 ] = this._z;
7725 array[ offset + 3 ] = this._order;
7726
7727 return array;
7728
7729 },
7730
7731 toVector3: function ( optionalResult ) {
7732
7733 if ( optionalResult ) {
7734
7735 return optionalResult.set( this._x, this._y, this._z );
7736
7737 } else {
7738
7739 return new Vector3( this._x, this._y, this._z );
7740
7741 }
7742
7743 },
7744
7745 onChange: function ( callback ) {
7746
7747 this.onChangeCallback = callback;
7748
7749 return this;
7750
7751 },
7752
7753 onChangeCallback: function () {}
7754
7755} );
7756
7757/**
7758 * @author mrdoob / http://mrdoob.com/
7759 */
7760
7761function Layers() {
7762
7763 this.mask = 1 | 0;
7764
7765}
7766
7767Object.assign( Layers.prototype, {
7768
7769 set: function ( channel ) {
7770
7771 this.mask = 1 << channel | 0;
7772
7773 },
7774
7775 enable: function ( channel ) {
7776
7777 this.mask |= 1 << channel | 0;
7778
7779 },
7780
7781 toggle: function ( channel ) {
7782
7783 this.mask ^= 1 << channel | 0;
7784
7785 },
7786
7787 disable: function ( channel ) {
7788
7789 this.mask &= ~ ( 1 << channel | 0 );
7790
7791 },
7792
7793 test: function ( layers ) {
7794
7795 return ( this.mask & layers.mask ) !== 0;
7796
7797 }
7798
7799} );
7800
7801/**
7802 * @author mrdoob / http://mrdoob.com/
7803 * @author mikael emtinger / http://gomo.se/
7804 * @author alteredq / http://alteredqualia.com/
7805 * @author WestLangley / http://github.com/WestLangley
7806 * @author elephantatwork / www.elephantatwork.ch
7807 */
7808
7809var object3DId = 0;
7810
7811function Object3D() {
7812
7813 Object.defineProperty( this, 'id', { value: object3DId ++ } );
7814
7815 this.uuid = _Math.generateUUID();
7816
7817 this.name = '';
7818 this.type = 'Object3D';
7819
7820 this.parent = null;
7821 this.children = [];
7822
7823 this.up = Object3D.DefaultUp.clone();
7824
7825 var position = new Vector3();
7826 var rotation = new Euler();
7827 var quaternion = new Quaternion();
7828 var scale = new Vector3( 1, 1, 1 );
7829
7830 function onRotationChange() {
7831
7832 quaternion.setFromEuler( rotation, false );
7833
7834 }
7835
7836 function onQuaternionChange() {
7837
7838 rotation.setFromQuaternion( quaternion, undefined, false );
7839
7840 }
7841
7842 rotation.onChange( onRotationChange );
7843 quaternion.onChange( onQuaternionChange );
7844
7845 Object.defineProperties( this, {
7846 position: {
7847 enumerable: true,
7848 value: position
7849 },
7850 rotation: {
7851 enumerable: true,
7852 value: rotation
7853 },
7854 quaternion: {
7855 enumerable: true,
7856 value: quaternion
7857 },
7858 scale: {
7859 enumerable: true,
7860 value: scale
7861 },
7862 modelViewMatrix: {
7863 value: new Matrix4()
7864 },
7865 normalMatrix: {
7866 value: new Matrix3()
7867 }
7868 } );
7869
7870 this.matrix = new Matrix4();
7871 this.matrixWorld = new Matrix4();
7872
7873 this.matrixAutoUpdate = Object3D.DefaultMatrixAutoUpdate;
7874 this.matrixWorldNeedsUpdate = false;
7875
7876 this.layers = new Layers();
7877 this.visible = true;
7878
7879 this.castShadow = false;
7880 this.receiveShadow = false;
7881
7882 this.frustumCulled = true;
7883 this.renderOrder = 0;
7884
7885 this.userData = {};
7886
7887}
7888
7889Object3D.DefaultUp = new Vector3( 0, 1, 0 );
7890Object3D.DefaultMatrixAutoUpdate = true;
7891
7892Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
7893
7894 constructor: Object3D,
7895
7896 isObject3D: true,
7897
7898 onBeforeRender: function () {},
7899 onAfterRender: function () {},
7900
7901 applyMatrix: function ( matrix ) {
7902
7903 this.matrix.multiplyMatrices( matrix, this.matrix );
7904
7905 this.matrix.decompose( this.position, this.quaternion, this.scale );
7906
7907 },
7908
7909 applyQuaternion: function ( q ) {
7910
7911 this.quaternion.premultiply( q );
7912
7913 return this;
7914
7915 },
7916
7917 setRotationFromAxisAngle: function ( axis, angle ) {
7918
7919 // assumes axis is normalized
7920
7921 this.quaternion.setFromAxisAngle( axis, angle );
7922
7923 },
7924
7925 setRotationFromEuler: function ( euler ) {
7926
7927 this.quaternion.setFromEuler( euler, true );
7928
7929 },
7930
7931 setRotationFromMatrix: function ( m ) {
7932
7933 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
7934
7935 this.quaternion.setFromRotationMatrix( m );
7936
7937 },
7938
7939 setRotationFromQuaternion: function ( q ) {
7940
7941 // assumes q is normalized
7942
7943 this.quaternion.copy( q );
7944
7945 },
7946
7947 rotateOnAxis: function () {
7948
7949 // rotate object on axis in object space
7950 // axis is assumed to be normalized
7951
7952 var q1 = new Quaternion();
7953
7954 return function rotateOnAxis( axis, angle ) {
7955
7956 q1.setFromAxisAngle( axis, angle );
7957
7958 this.quaternion.multiply( q1 );
7959
7960 return this;
7961
7962 };
7963
7964 }(),
7965
7966 rotateOnWorldAxis: function () {
7967
7968 // rotate object on axis in world space
7969 // axis is assumed to be normalized
7970 // method assumes no rotated parent
7971
7972 var q1 = new Quaternion();
7973
7974 return function rotateOnWorldAxis( axis, angle ) {
7975
7976 q1.setFromAxisAngle( axis, angle );
7977
7978 this.quaternion.premultiply( q1 );
7979
7980 return this;
7981
7982 };
7983
7984 }(),
7985
7986 rotateX: function () {
7987
7988 var v1 = new Vector3( 1, 0, 0 );
7989
7990 return function rotateX( angle ) {
7991
7992 return this.rotateOnAxis( v1, angle );
7993
7994 };
7995
7996 }(),
7997
7998 rotateY: function () {
7999
8000 var v1 = new Vector3( 0, 1, 0 );
8001
8002 return function rotateY( angle ) {
8003
8004 return this.rotateOnAxis( v1, angle );
8005
8006 };
8007
8008 }(),
8009
8010 rotateZ: function () {
8011
8012 var v1 = new Vector3( 0, 0, 1 );
8013
8014 return function rotateZ( angle ) {
8015
8016 return this.rotateOnAxis( v1, angle );
8017
8018 };
8019
8020 }(),
8021
8022 translateOnAxis: function () {
8023
8024 // translate object by distance along axis in object space
8025 // axis is assumed to be normalized
8026
8027 var v1 = new Vector3();
8028
8029 return function translateOnAxis( axis, distance ) {
8030
8031 v1.copy( axis ).applyQuaternion( this.quaternion );
8032
8033 this.position.add( v1.multiplyScalar( distance ) );
8034
8035 return this;
8036
8037 };
8038
8039 }(),
8040
8041 translateX: function () {
8042
8043 var v1 = new Vector3( 1, 0, 0 );
8044
8045 return function translateX( distance ) {
8046
8047 return this.translateOnAxis( v1, distance );
8048
8049 };
8050
8051 }(),
8052
8053 translateY: function () {
8054
8055 var v1 = new Vector3( 0, 1, 0 );
8056
8057 return function translateY( distance ) {
8058
8059 return this.translateOnAxis( v1, distance );
8060
8061 };
8062
8063 }(),
8064
8065 translateZ: function () {
8066
8067 var v1 = new Vector3( 0, 0, 1 );
8068
8069 return function translateZ( distance ) {
8070
8071 return this.translateOnAxis( v1, distance );
8072
8073 };
8074
8075 }(),
8076
8077 localToWorld: function ( vector ) {
8078
8079 return vector.applyMatrix4( this.matrixWorld );
8080
8081 },
8082
8083 worldToLocal: function () {
8084
8085 var m1 = new Matrix4();
8086
8087 return function worldToLocal( vector ) {
8088
8089 return vector.applyMatrix4( m1.getInverse( this.matrixWorld ) );
8090
8091 };
8092
8093 }(),
8094
8095 lookAt: function () {
8096
8097 // This method does not support objects with rotated and/or translated parent(s)
8098
8099 var m1 = new Matrix4();
8100 var vector = new Vector3();
8101
8102 return function lookAt( x, y, z ) {
8103
8104 if ( x.isVector3 ) {
8105
8106 vector.copy( x );
8107
8108 } else {
8109
8110 vector.set( x, y, z );
8111
8112 }
8113
8114 if ( this.isCamera ) {
8115
8116 m1.lookAt( this.position, vector, this.up );
8117
8118 } else {
8119
8120 m1.lookAt( vector, this.position, this.up );
8121
8122 }
8123
8124 this.quaternion.setFromRotationMatrix( m1 );
8125
8126 };
8127
8128 }(),
8129
8130 add: function ( object ) {
8131
8132 if ( arguments.length > 1 ) {
8133
8134 for ( var i = 0; i < arguments.length; i ++ ) {
8135
8136 this.add( arguments[ i ] );
8137
8138 }
8139
8140 return this;
8141
8142 }
8143
8144 if ( object === this ) {
8145
8146 console.error( "THREE.Object3D.add: object can't be added as a child of itself.", object );
8147 return this;
8148
8149 }
8150
8151 if ( ( object && object.isObject3D ) ) {
8152
8153 if ( object.parent !== null ) {
8154
8155 object.parent.remove( object );
8156
8157 }
8158
8159 object.parent = this;
8160 object.dispatchEvent( { type: 'added' } );
8161
8162 this.children.push( object );
8163
8164 } else {
8165
8166 console.error( "THREE.Object3D.add: object not an instance of THREE.Object3D.", object );
8167
8168 }
8169
8170 return this;
8171
8172 },
8173
8174 remove: function ( object ) {
8175
8176 if ( arguments.length > 1 ) {
8177
8178 for ( var i = 0; i < arguments.length; i ++ ) {
8179
8180 this.remove( arguments[ i ] );
8181
8182 }
8183
8184 return this;
8185
8186 }
8187
8188 var index = this.children.indexOf( object );
8189
8190 if ( index !== - 1 ) {
8191
8192 object.parent = null;
8193
8194 object.dispatchEvent( { type: 'removed' } );
8195
8196 this.children.splice( index, 1 );
8197
8198 }
8199
8200 return this;
8201
8202 },
8203
8204 getObjectById: function ( id ) {
8205
8206 return this.getObjectByProperty( 'id', id );
8207
8208 },
8209
8210 getObjectByName: function ( name ) {
8211
8212 return this.getObjectByProperty( 'name', name );
8213
8214 },
8215
8216 getObjectByProperty: function ( name, value ) {
8217
8218 if ( this[ name ] === value ) return this;
8219
8220 for ( var i = 0, l = this.children.length; i < l; i ++ ) {
8221
8222 var child = this.children[ i ];
8223 var object = child.getObjectByProperty( name, value );
8224
8225 if ( object !== undefined ) {
8226
8227 return object;
8228
8229 }
8230
8231 }
8232
8233 return undefined;
8234
8235 },
8236
8237 getWorldPosition: function ( target ) {
8238
8239 if ( target === undefined ) {
8240
8241 console.warn( 'THREE.Object3D: .getWorldPosition() target is now required' );
8242 target = new Vector3();
8243
8244 }
8245
8246 this.updateMatrixWorld( true );
8247
8248 return target.setFromMatrixPosition( this.matrixWorld );
8249
8250 },
8251
8252 getWorldQuaternion: function () {
8253
8254 var position = new Vector3();
8255 var scale = new Vector3();
8256
8257 return function getWorldQuaternion( target ) {
8258
8259 if ( target === undefined ) {
8260
8261 console.warn( 'THREE.Object3D: .getWorldQuaternion() target is now required' );
8262 target = new Quaternion();
8263
8264 }
8265
8266 this.updateMatrixWorld( true );
8267
8268 this.matrixWorld.decompose( position, target, scale );
8269
8270 return target;
8271
8272 };
8273
8274 }(),
8275
8276 getWorldScale: function () {
8277
8278 var position = new Vector3();
8279 var quaternion = new Quaternion();
8280
8281 return function getWorldScale( target ) {
8282
8283 if ( target === undefined ) {
8284
8285 console.warn( 'THREE.Object3D: .getWorldScale() target is now required' );
8286 target = new Vector3();
8287
8288 }
8289
8290 this.updateMatrixWorld( true );
8291
8292 this.matrixWorld.decompose( position, quaternion, target );
8293
8294 return target;
8295
8296 };
8297
8298 }(),
8299
8300 getWorldDirection: function () {
8301
8302 var quaternion = new Quaternion();
8303
8304 return function getWorldDirection( target ) {
8305
8306 if ( target === undefined ) {
8307
8308 console.warn( 'THREE.Object3D: .getWorldDirection() target is now required' );
8309 target = new Vector3();
8310
8311 }
8312
8313 this.getWorldQuaternion( quaternion );
8314
8315 return target.set( 0, 0, 1 ).applyQuaternion( quaternion );
8316
8317 };
8318
8319 }(),
8320
8321 raycast: function () {},
8322
8323 traverse: function ( callback ) {
8324
8325 callback( this );
8326
8327 var children = this.children;
8328
8329 for ( var i = 0, l = children.length; i < l; i ++ ) {
8330
8331 children[ i ].traverse( callback );
8332
8333 }
8334
8335 },
8336
8337 traverseVisible: function ( callback ) {
8338
8339 if ( this.visible === false ) return;
8340
8341 callback( this );
8342
8343 var children = this.children;
8344
8345 for ( var i = 0, l = children.length; i < l; i ++ ) {
8346
8347 children[ i ].traverseVisible( callback );
8348
8349 }
8350
8351 },
8352
8353 traverseAncestors: function ( callback ) {
8354
8355 var parent = this.parent;
8356
8357 if ( parent !== null ) {
8358
8359 callback( parent );
8360
8361 parent.traverseAncestors( callback );
8362
8363 }
8364
8365 },
8366
8367 updateMatrix: function () {
8368
8369 this.matrix.compose( this.position, this.quaternion, this.scale );
8370
8371 this.matrixWorldNeedsUpdate = true;
8372
8373 },
8374
8375 updateMatrixWorld: function ( force ) {
8376
8377 if ( this.matrixAutoUpdate ) this.updateMatrix();
8378
8379 if ( this.matrixWorldNeedsUpdate || force ) {
8380
8381 if ( this.parent === null ) {
8382
8383 this.matrixWorld.copy( this.matrix );
8384
8385 } else {
8386
8387 this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
8388
8389 }
8390
8391 this.matrixWorldNeedsUpdate = false;
8392
8393 force = true;
8394
8395 }
8396
8397 // update children
8398
8399 var children = this.children;
8400
8401 for ( var i = 0, l = children.length; i < l; i ++ ) {
8402
8403 children[ i ].updateMatrixWorld( force );
8404
8405 }
8406
8407 },
8408
8409 toJSON: function ( meta ) {
8410
8411 // meta is a string when called from JSON.stringify
8412 var isRootObject = ( meta === undefined || typeof meta === 'string' );
8413
8414 var output = {};
8415
8416 // meta is a hash used to collect geometries, materials.
8417 // not providing it implies that this is the root object
8418 // being serialized.
8419 if ( isRootObject ) {
8420
8421 // initialize meta obj
8422 meta = {
8423 geometries: {},
8424 materials: {},
8425 textures: {},
8426 images: {},
8427 shapes: {}
8428 };
8429
8430 output.metadata = {
8431 version: 4.5,
8432 type: 'Object',
8433 generator: 'Object3D.toJSON'
8434 };
8435
8436 }
8437
8438 // standard Object3D serialization
8439
8440 var object = {};
8441
8442 object.uuid = this.uuid;
8443 object.type = this.type;
8444
8445 if ( this.name !== '' ) object.name = this.name;
8446 if ( this.castShadow === true ) object.castShadow = true;
8447 if ( this.receiveShadow === true ) object.receiveShadow = true;
8448 if ( this.visible === false ) object.visible = false;
8449 if ( this.frustumCulled === false ) object.frustumCulled = false;
8450 if ( this.renderOrder !== 0 ) object.renderOrder = this.renderOrder;
8451 if ( JSON.stringify( this.userData ) !== '{}' ) object.userData = this.userData;
8452
8453 object.matrix = this.matrix.toArray();
8454
8455 if ( this.matrixAutoUpdate === false ) object.matrixAutoUpdate = false;
8456
8457 //
8458
8459 function serialize( library, element ) {
8460
8461 if ( library[ element.uuid ] === undefined ) {
8462
8463 library[ element.uuid ] = element.toJSON( meta );
8464
8465 }
8466
8467 return element.uuid;
8468
8469 }
8470
8471 if ( this.geometry !== undefined ) {
8472
8473 object.geometry = serialize( meta.geometries, this.geometry );
8474
8475 var parameters = this.geometry.parameters;
8476
8477 if ( parameters !== undefined && parameters.shapes !== undefined ) {
8478
8479 var shapes = parameters.shapes;
8480
8481 if ( Array.isArray( shapes ) ) {
8482
8483 for ( var i = 0, l = shapes.length; i < l; i ++ ) {
8484
8485 var shape = shapes[ i ];
8486
8487 serialize( meta.shapes, shape );
8488
8489 }
8490
8491 } else {
8492
8493 serialize( meta.shapes, shapes );
8494
8495 }
8496
8497 }
8498
8499 }
8500
8501 if ( this.material !== undefined ) {
8502
8503 if ( Array.isArray( this.material ) ) {
8504
8505 var uuids = [];
8506
8507 for ( var i = 0, l = this.material.length; i < l; i ++ ) {
8508
8509 uuids.push( serialize( meta.materials, this.material[ i ] ) );
8510
8511 }
8512
8513 object.material = uuids;
8514
8515 } else {
8516
8517 object.material = serialize( meta.materials, this.material );
8518
8519 }
8520
8521 }
8522
8523 //
8524
8525 if ( this.children.length > 0 ) {
8526
8527 object.children = [];
8528
8529 for ( var i = 0; i < this.children.length; i ++ ) {
8530
8531 object.children.push( this.children[ i ].toJSON( meta ).object );
8532
8533 }
8534
8535 }
8536
8537 if ( isRootObject ) {
8538
8539 var geometries = extractFromCache( meta.geometries );
8540 var materials = extractFromCache( meta.materials );
8541 var textures = extractFromCache( meta.textures );
8542 var images = extractFromCache( meta.images );
8543 var shapes = extractFromCache( meta.shapes );
8544
8545 if ( geometries.length > 0 ) output.geometries = geometries;
8546 if ( materials.length > 0 ) output.materials = materials;
8547 if ( textures.length > 0 ) output.textures = textures;
8548 if ( images.length > 0 ) output.images = images;
8549 if ( shapes.length > 0 ) output.shapes = shapes;
8550
8551 }
8552
8553 output.object = object;
8554
8555 return output;
8556
8557 // extract data from the cache hash
8558 // remove metadata on each item
8559 // and return as array
8560 function extractFromCache( cache ) {
8561
8562 var values = [];
8563 for ( var key in cache ) {
8564
8565 var data = cache[ key ];
8566 delete data.metadata;
8567 values.push( data );
8568
8569 }
8570 return values;
8571
8572 }
8573
8574 },
8575
8576 clone: function ( recursive ) {
8577
8578 return new this.constructor().copy( this, recursive );
8579
8580 },
8581
8582 copy: function ( source, recursive ) {
8583
8584 if ( recursive === undefined ) recursive = true;
8585
8586 this.name = source.name;
8587
8588 this.up.copy( source.up );
8589
8590 this.position.copy( source.position );
8591 this.quaternion.copy( source.quaternion );
8592 this.scale.copy( source.scale );
8593
8594 this.matrix.copy( source.matrix );
8595 this.matrixWorld.copy( source.matrixWorld );
8596
8597 this.matrixAutoUpdate = source.matrixAutoUpdate;
8598 this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate;
8599
8600 this.layers.mask = source.layers.mask;
8601 this.visible = source.visible;
8602
8603 this.castShadow = source.castShadow;
8604 this.receiveShadow = source.receiveShadow;
8605
8606 this.frustumCulled = source.frustumCulled;
8607 this.renderOrder = source.renderOrder;
8608
8609 this.userData = JSON.parse( JSON.stringify( source.userData ) );
8610
8611 if ( recursive === true ) {
8612
8613 for ( var i = 0; i < source.children.length; i ++ ) {
8614
8615 var child = source.children[ i ];
8616 this.add( child.clone() );
8617
8618 }
8619
8620 }
8621
8622 return this;
8623
8624 }
8625
8626} );
8627
8628/**
8629 * @author mrdoob / http://mrdoob.com/
8630 * @author mikael emtinger / http://gomo.se/
8631 * @author WestLangley / http://github.com/WestLangley
8632*/
8633
8634function Camera() {
8635
8636 Object3D.call( this );
8637
8638 this.type = 'Camera';
8639
8640 this.matrixWorldInverse = new Matrix4();
8641 this.projectionMatrix = new Matrix4();
8642
8643}
8644
8645Camera.prototype = Object.assign( Object.create( Object3D.prototype ), {
8646
8647 constructor: Camera,
8648
8649 isCamera: true,
8650
8651 copy: function ( source, recursive ) {
8652
8653 Object3D.prototype.copy.call( this, source, recursive );
8654
8655 this.matrixWorldInverse.copy( source.matrixWorldInverse );
8656 this.projectionMatrix.copy( source.projectionMatrix );
8657
8658 return this;
8659
8660 },
8661
8662 getWorldDirection: function () {
8663
8664 var quaternion = new Quaternion();
8665
8666 return function getWorldDirection( target ) {
8667
8668 if ( target === undefined ) {
8669
8670 console.warn( 'THREE.Camera: .getWorldDirection() target is now required' );
8671 target = new Vector3();
8672
8673 }
8674
8675 this.getWorldQuaternion( quaternion );
8676
8677 return target.set( 0, 0, - 1 ).applyQuaternion( quaternion );
8678
8679 };
8680
8681 }(),
8682
8683 updateMatrixWorld: function ( force ) {
8684
8685 Object3D.prototype.updateMatrixWorld.call( this, force );
8686
8687 this.matrixWorldInverse.getInverse( this.matrixWorld );
8688
8689 },
8690
8691 clone: function () {
8692
8693 return new this.constructor().copy( this );
8694
8695 }
8696
8697} );
8698
8699/**
8700 * @author alteredq / http://alteredqualia.com/
8701 * @author arose / http://github.com/arose
8702 */
8703
8704function OrthographicCamera( left, right, top, bottom, near, far ) {
8705
8706 Camera.call( this );
8707
8708 this.type = 'OrthographicCamera';
8709
8710 this.zoom = 1;
8711 this.view = null;
8712
8713 this.left = left;
8714 this.right = right;
8715 this.top = top;
8716 this.bottom = bottom;
8717
8718 this.near = ( near !== undefined ) ? near : 0.1;
8719 this.far = ( far !== undefined ) ? far : 2000;
8720
8721 this.updateProjectionMatrix();
8722
8723}
8724
8725OrthographicCamera.prototype = Object.assign( Object.create( Camera.prototype ), {
8726
8727 constructor: OrthographicCamera,
8728
8729 isOrthographicCamera: true,
8730
8731 copy: function ( source, recursive ) {
8732
8733 Camera.prototype.copy.call( this, source, recursive );
8734
8735 this.left = source.left;
8736 this.right = source.right;
8737 this.top = source.top;
8738 this.bottom = source.bottom;
8739 this.near = source.near;
8740 this.far = source.far;
8741
8742 this.zoom = source.zoom;
8743 this.view = source.view === null ? null : Object.assign( {}, source.view );
8744
8745 return this;
8746
8747 },
8748
8749 setViewOffset: function ( fullWidth, fullHeight, x, y, width, height ) {
8750
8751 if ( this.view === null ) {
8752
8753 this.view = {
8754 enabled: true,
8755 fullWidth: 1,
8756 fullHeight: 1,
8757 offsetX: 0,
8758 offsetY: 0,
8759 width: 1,
8760 height: 1
8761 };
8762
8763 }
8764
8765 this.view.enabled = true;
8766 this.view.fullWidth = fullWidth;
8767 this.view.fullHeight = fullHeight;
8768 this.view.offsetX = x;
8769 this.view.offsetY = y;
8770 this.view.width = width;
8771 this.view.height = height;
8772
8773 this.updateProjectionMatrix();
8774
8775 },
8776
8777 clearViewOffset: function () {
8778
8779 if ( this.view !== null ) {
8780
8781 this.view.enabled = false;
8782
8783 }
8784
8785 this.updateProjectionMatrix();
8786
8787 },
8788
8789 updateProjectionMatrix: function () {
8790
8791 var dx = ( this.right - this.left ) / ( 2 * this.zoom );
8792 var dy = ( this.top - this.bottom ) / ( 2 * this.zoom );
8793 var cx = ( this.right + this.left ) / 2;
8794 var cy = ( this.top + this.bottom ) / 2;
8795
8796 var left = cx - dx;
8797 var right = cx + dx;
8798 var top = cy + dy;
8799 var bottom = cy - dy;
8800
8801 if ( this.view !== null && this.view.enabled ) {
8802
8803 var zoomW = this.zoom / ( this.view.width / this.view.fullWidth );
8804 var zoomH = this.zoom / ( this.view.height / this.view.fullHeight );
8805 var scaleW = ( this.right - this.left ) / this.view.width;
8806 var scaleH = ( this.top - this.bottom ) / this.view.height;
8807
8808 left += scaleW * ( this.view.offsetX / zoomW );
8809 right = left + scaleW * ( this.view.width / zoomW );
8810 top -= scaleH * ( this.view.offsetY / zoomH );
8811 bottom = top - scaleH * ( this.view.height / zoomH );
8812
8813 }
8814
8815 this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far );
8816
8817 },
8818
8819 toJSON: function ( meta ) {
8820
8821 var data = Object3D.prototype.toJSON.call( this, meta );
8822
8823 data.object.zoom = this.zoom;
8824 data.object.left = this.left;
8825 data.object.right = this.right;
8826 data.object.top = this.top;
8827 data.object.bottom = this.bottom;
8828 data.object.near = this.near;
8829 data.object.far = this.far;
8830
8831 if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
8832
8833 return data;
8834
8835 }
8836
8837} );
8838
8839/**
8840 * @author mrdoob / http://mrdoob.com/
8841 * @author alteredq / http://alteredqualia.com/
8842 */
8843
8844function Face3( a, b, c, normal, color, materialIndex ) {
8845
8846 this.a = a;
8847 this.b = b;
8848 this.c = c;
8849
8850 this.normal = ( normal && normal.isVector3 ) ? normal : new Vector3();
8851 this.vertexNormals = Array.isArray( normal ) ? normal : [];
8852
8853 this.color = ( color && color.isColor ) ? color : new Color();
8854 this.vertexColors = Array.isArray( color ) ? color : [];
8855
8856 this.materialIndex = materialIndex !== undefined ? materialIndex : 0;
8857
8858}
8859
8860Object.assign( Face3.prototype, {
8861
8862 clone: function () {
8863
8864 return new this.constructor().copy( this );
8865
8866 },
8867
8868 copy: function ( source ) {
8869
8870 this.a = source.a;
8871 this.b = source.b;
8872 this.c = source.c;
8873
8874 this.normal.copy( source.normal );
8875 this.color.copy( source.color );
8876
8877 this.materialIndex = source.materialIndex;
8878
8879 for ( var i = 0, il = source.vertexNormals.length; i < il; i ++ ) {
8880
8881 this.vertexNormals[ i ] = source.vertexNormals[ i ].clone();
8882
8883 }
8884
8885 for ( var i = 0, il = source.vertexColors.length; i < il; i ++ ) {
8886
8887 this.vertexColors[ i ] = source.vertexColors[ i ].clone();
8888
8889 }
8890
8891 return this;
8892
8893 }
8894
8895} );
8896
8897/**
8898 * @author mrdoob / http://mrdoob.com/
8899 * @author kile / http://kile.stravaganza.org/
8900 * @author alteredq / http://alteredqualia.com/
8901 * @author mikael emtinger / http://gomo.se/
8902 * @author zz85 / http://www.lab4games.net/zz85/blog
8903 * @author bhouston / http://clara.io
8904 */
8905
8906var geometryId = 0; // Geometry uses even numbers as Id
8907
8908function Geometry() {
8909
8910 Object.defineProperty( this, 'id', { value: geometryId += 2 } );
8911
8912 this.uuid = _Math.generateUUID();
8913
8914 this.name = '';
8915 this.type = 'Geometry';
8916
8917 this.vertices = [];
8918 this.colors = [];
8919 this.faces = [];
8920 this.faceVertexUvs = [[]];
8921
8922 this.morphTargets = [];
8923 this.morphNormals = [];
8924
8925 this.skinWeights = [];
8926 this.skinIndices = [];
8927
8928 this.lineDistances = [];
8929
8930 this.boundingBox = null;
8931 this.boundingSphere = null;
8932
8933 // update flags
8934
8935 this.elementsNeedUpdate = false;
8936 this.verticesNeedUpdate = false;
8937 this.uvsNeedUpdate = false;
8938 this.normalsNeedUpdate = false;
8939 this.colorsNeedUpdate = false;
8940 this.lineDistancesNeedUpdate = false;
8941 this.groupsNeedUpdate = false;
8942
8943}
8944
8945Geometry.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
8946
8947 constructor: Geometry,
8948
8949 isGeometry: true,
8950
8951 applyMatrix: function ( matrix ) {
8952
8953 var normalMatrix = new Matrix3().getNormalMatrix( matrix );
8954
8955 for ( var i = 0, il = this.vertices.length; i < il; i ++ ) {
8956
8957 var vertex = this.vertices[ i ];
8958 vertex.applyMatrix4( matrix );
8959
8960 }
8961
8962 for ( var i = 0, il = this.faces.length; i < il; i ++ ) {
8963
8964 var face = this.faces[ i ];
8965 face.normal.applyMatrix3( normalMatrix ).normalize();
8966
8967 for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {
8968
8969 face.vertexNormals[ j ].applyMatrix3( normalMatrix ).normalize();
8970
8971 }
8972
8973 }
8974
8975 if ( this.boundingBox !== null ) {
8976
8977 this.computeBoundingBox();
8978
8979 }
8980
8981 if ( this.boundingSphere !== null ) {
8982
8983 this.computeBoundingSphere();
8984
8985 }
8986
8987 this.verticesNeedUpdate = true;
8988 this.normalsNeedUpdate = true;
8989
8990 return this;
8991
8992 },
8993
8994 rotateX: function () {
8995
8996 // rotate geometry around world x-axis
8997
8998 var m1 = new Matrix4();
8999
9000 return function rotateX( angle ) {
9001
9002 m1.makeRotationX( angle );
9003
9004 this.applyMatrix( m1 );
9005
9006 return this;
9007
9008 };
9009
9010 }(),
9011
9012 rotateY: function () {
9013
9014 // rotate geometry around world y-axis
9015
9016 var m1 = new Matrix4();
9017
9018 return function rotateY( angle ) {
9019
9020 m1.makeRotationY( angle );
9021
9022 this.applyMatrix( m1 );
9023
9024 return this;
9025
9026 };
9027
9028 }(),
9029
9030 rotateZ: function () {
9031
9032 // rotate geometry around world z-axis
9033
9034 var m1 = new Matrix4();
9035
9036 return function rotateZ( angle ) {
9037
9038 m1.makeRotationZ( angle );
9039
9040 this.applyMatrix( m1 );
9041
9042 return this;
9043
9044 };
9045
9046 }(),
9047
9048 translate: function () {
9049
9050 // translate geometry
9051
9052 var m1 = new Matrix4();
9053
9054 return function translate( x, y, z ) {
9055
9056 m1.makeTranslation( x, y, z );
9057
9058 this.applyMatrix( m1 );
9059
9060 return this;
9061
9062 };
9063
9064 }(),
9065
9066 scale: function () {
9067
9068 // scale geometry
9069
9070 var m1 = new Matrix4();
9071
9072 return function scale( x, y, z ) {
9073
9074 m1.makeScale( x, y, z );
9075
9076 this.applyMatrix( m1 );
9077
9078 return this;
9079
9080 };
9081
9082 }(),
9083
9084 lookAt: function () {
9085
9086 var obj = new Object3D();
9087
9088 return function lookAt( vector ) {
9089
9090 obj.lookAt( vector );
9091
9092 obj.updateMatrix();
9093
9094 this.applyMatrix( obj.matrix );
9095
9096 };
9097
9098 }(),
9099
9100 fromBufferGeometry: function ( geometry ) {
9101
9102 var scope = this;
9103
9104 var indices = geometry.index !== null ? geometry.index.array : undefined;
9105 var attributes = geometry.attributes;
9106
9107 var positions = attributes.position.array;
9108 var normals = attributes.normal !== undefined ? attributes.normal.array : undefined;
9109 var colors = attributes.color !== undefined ? attributes.color.array : undefined;
9110 var uvs = attributes.uv !== undefined ? attributes.uv.array : undefined;
9111 var uvs2 = attributes.uv2 !== undefined ? attributes.uv2.array : undefined;
9112
9113 if ( uvs2 !== undefined ) this.faceVertexUvs[ 1 ] = [];
9114
9115 var tempNormals = [];
9116 var tempUVs = [];
9117 var tempUVs2 = [];
9118
9119 for ( var i = 0, j = 0; i < positions.length; i += 3, j += 2 ) {
9120
9121 scope.vertices.push( new Vector3( positions[ i ], positions[ i + 1 ], positions[ i + 2 ] ) );
9122
9123 if ( normals !== undefined ) {
9124
9125 tempNormals.push( new Vector3( normals[ i ], normals[ i + 1 ], normals[ i + 2 ] ) );
9126
9127 }
9128
9129 if ( colors !== undefined ) {
9130
9131 scope.colors.push( new Color( colors[ i ], colors[ i + 1 ], colors[ i + 2 ] ) );
9132
9133 }
9134
9135 if ( uvs !== undefined ) {
9136
9137 tempUVs.push( new Vector2( uvs[ j ], uvs[ j + 1 ] ) );
9138
9139 }
9140
9141 if ( uvs2 !== undefined ) {
9142
9143 tempUVs2.push( new Vector2( uvs2[ j ], uvs2[ j + 1 ] ) );
9144
9145 }
9146
9147 }
9148
9149 function addFace( a, b, c, materialIndex ) {
9150
9151 var vertexNormals = normals !== undefined ? [ tempNormals[ a ].clone(), tempNormals[ b ].clone(), tempNormals[ c ].clone() ] : [];
9152 var vertexColors = colors !== undefined ? [ scope.colors[ a ].clone(), scope.colors[ b ].clone(), scope.colors[ c ].clone() ] : [];
9153
9154 var face = new Face3( a, b, c, vertexNormals, vertexColors, materialIndex );
9155
9156 scope.faces.push( face );
9157
9158 if ( uvs !== undefined ) {
9159
9160 scope.faceVertexUvs[ 0 ].push( [ tempUVs[ a ].clone(), tempUVs[ b ].clone(), tempUVs[ c ].clone() ] );
9161
9162 }
9163
9164 if ( uvs2 !== undefined ) {
9165
9166 scope.faceVertexUvs[ 1 ].push( [ tempUVs2[ a ].clone(), tempUVs2[ b ].clone(), tempUVs2[ c ].clone() ] );
9167
9168 }
9169
9170 }
9171
9172 var groups = geometry.groups;
9173
9174 if ( groups.length > 0 ) {
9175
9176 for ( var i = 0; i < groups.length; i ++ ) {
9177
9178 var group = groups[ i ];
9179
9180 var start = group.start;
9181 var count = group.count;
9182
9183 for ( var j = start, jl = start + count; j < jl; j += 3 ) {
9184
9185 if ( indices !== undefined ) {
9186
9187 addFace( indices[ j ], indices[ j + 1 ], indices[ j + 2 ], group.materialIndex );
9188
9189 } else {
9190
9191 addFace( j, j + 1, j + 2, group.materialIndex );
9192
9193 }
9194
9195 }
9196
9197 }
9198
9199 } else {
9200
9201 if ( indices !== undefined ) {
9202
9203 for ( var i = 0; i < indices.length; i += 3 ) {
9204
9205 addFace( indices[ i ], indices[ i + 1 ], indices[ i + 2 ] );
9206
9207 }
9208
9209 } else {
9210
9211 for ( var i = 0; i < positions.length / 3; i += 3 ) {
9212
9213 addFace( i, i + 1, i + 2 );
9214
9215 }
9216
9217 }
9218
9219 }
9220
9221 this.computeFaceNormals();
9222
9223 if ( geometry.boundingBox !== null ) {
9224
9225 this.boundingBox = geometry.boundingBox.clone();
9226
9227 }
9228
9229 if ( geometry.boundingSphere !== null ) {
9230
9231 this.boundingSphere = geometry.boundingSphere.clone();
9232
9233 }
9234
9235 return this;
9236
9237 },
9238
9239 center: function () {
9240
9241 var offset = new Vector3();
9242
9243 return function center() {
9244
9245 this.computeBoundingBox();
9246
9247 this.boundingBox.getCenter( offset ).negate();
9248
9249 this.translate( offset.x, offset.y, offset.z );
9250
9251 return this;
9252
9253 };
9254
9255 }(),
9256
9257 normalize: function () {
9258
9259 this.computeBoundingSphere();
9260
9261 var center = this.boundingSphere.center;
9262 var radius = this.boundingSphere.radius;
9263
9264 var s = radius === 0 ? 1 : 1.0 / radius;
9265
9266 var matrix = new Matrix4();
9267 matrix.set(
9268 s, 0, 0, - s * center.x,
9269 0, s, 0, - s * center.y,
9270 0, 0, s, - s * center.z,
9271 0, 0, 0, 1
9272 );
9273
9274 this.applyMatrix( matrix );
9275
9276 return this;
9277
9278 },
9279
9280 computeFaceNormals: function () {
9281
9282 var cb = new Vector3(), ab = new Vector3();
9283
9284 for ( var f = 0, fl = this.faces.length; f < fl; f ++ ) {
9285
9286 var face = this.faces[ f ];
9287
9288 var vA = this.vertices[ face.a ];
9289 var vB = this.vertices[ face.b ];
9290 var vC = this.vertices[ face.c ];
9291
9292 cb.subVectors( vC, vB );
9293 ab.subVectors( vA, vB );
9294 cb.cross( ab );
9295
9296 cb.normalize();
9297
9298 face.normal.copy( cb );
9299
9300 }
9301
9302 },
9303
9304 computeVertexNormals: function ( areaWeighted ) {
9305
9306 if ( areaWeighted === undefined ) areaWeighted = true;
9307
9308 var v, vl, f, fl, face, vertices;
9309
9310 vertices = new Array( this.vertices.length );
9311
9312 for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
9313
9314 vertices[ v ] = new Vector3();
9315
9316 }
9317
9318 if ( areaWeighted ) {
9319
9320 // vertex normals weighted by triangle areas
9321 // http://www.iquilezles.org/www/articles/normals/normals.htm
9322
9323 var vA, vB, vC;
9324 var cb = new Vector3(), ab = new Vector3();
9325
9326 for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
9327
9328 face = this.faces[ f ];
9329
9330 vA = this.vertices[ face.a ];
9331 vB = this.vertices[ face.b ];
9332 vC = this.vertices[ face.c ];
9333
9334 cb.subVectors( vC, vB );
9335 ab.subVectors( vA, vB );
9336 cb.cross( ab );
9337
9338 vertices[ face.a ].add( cb );
9339 vertices[ face.b ].add( cb );
9340 vertices[ face.c ].add( cb );
9341
9342 }
9343
9344 } else {
9345
9346 this.computeFaceNormals();
9347
9348 for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
9349
9350 face = this.faces[ f ];
9351
9352 vertices[ face.a ].add( face.normal );
9353 vertices[ face.b ].add( face.normal );
9354 vertices[ face.c ].add( face.normal );
9355
9356 }
9357
9358 }
9359
9360 for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
9361
9362 vertices[ v ].normalize();
9363
9364 }
9365
9366 for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
9367
9368 face = this.faces[ f ];
9369
9370 var vertexNormals = face.vertexNormals;
9371
9372 if ( vertexNormals.length === 3 ) {
9373
9374 vertexNormals[ 0 ].copy( vertices[ face.a ] );
9375 vertexNormals[ 1 ].copy( vertices[ face.b ] );
9376 vertexNormals[ 2 ].copy( vertices[ face.c ] );
9377
9378 } else {
9379
9380 vertexNormals[ 0 ] = vertices[ face.a ].clone();
9381 vertexNormals[ 1 ] = vertices[ face.b ].clone();
9382 vertexNormals[ 2 ] = vertices[ face.c ].clone();
9383
9384 }
9385
9386 }
9387
9388 if ( this.faces.length > 0 ) {
9389
9390 this.normalsNeedUpdate = true;
9391
9392 }
9393
9394 },
9395
9396 computeFlatVertexNormals: function () {
9397
9398 var f, fl, face;
9399
9400 this.computeFaceNormals();
9401
9402 for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
9403
9404 face = this.faces[ f ];
9405
9406 var vertexNormals = face.vertexNormals;
9407
9408 if ( vertexNormals.length === 3 ) {
9409
9410 vertexNormals[ 0 ].copy( face.normal );
9411 vertexNormals[ 1 ].copy( face.normal );
9412 vertexNormals[ 2 ].copy( face.normal );
9413
9414 } else {
9415
9416 vertexNormals[ 0 ] = face.normal.clone();
9417 vertexNormals[ 1 ] = face.normal.clone();
9418 vertexNormals[ 2 ] = face.normal.clone();
9419
9420 }
9421
9422 }
9423
9424 if ( this.faces.length > 0 ) {
9425
9426 this.normalsNeedUpdate = true;
9427
9428 }
9429
9430 },
9431
9432 computeMorphNormals: function () {
9433
9434 var i, il, f, fl, face;
9435
9436 // save original normals
9437 // - create temp variables on first access
9438 // otherwise just copy (for faster repeated calls)
9439
9440 for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
9441
9442 face = this.faces[ f ];
9443
9444 if ( ! face.__originalFaceNormal ) {
9445
9446 face.__originalFaceNormal = face.normal.clone();
9447
9448 } else {
9449
9450 face.__originalFaceNormal.copy( face.normal );
9451
9452 }
9453
9454 if ( ! face.__originalVertexNormals ) face.__originalVertexNormals = [];
9455
9456 for ( i = 0, il = face.vertexNormals.length; i < il; i ++ ) {
9457
9458 if ( ! face.__originalVertexNormals[ i ] ) {
9459
9460 face.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone();
9461
9462 } else {
9463
9464 face.__originalVertexNormals[ i ].copy( face.vertexNormals[ i ] );
9465
9466 }
9467
9468 }
9469
9470 }
9471
9472 // use temp geometry to compute face and vertex normals for each morph
9473
9474 var tmpGeo = new Geometry();
9475 tmpGeo.faces = this.faces;
9476
9477 for ( i = 0, il = this.morphTargets.length; i < il; i ++ ) {
9478
9479 // create on first access
9480
9481 if ( ! this.morphNormals[ i ] ) {
9482
9483 this.morphNormals[ i ] = {};
9484 this.morphNormals[ i ].faceNormals = [];
9485 this.morphNormals[ i ].vertexNormals = [];
9486
9487 var dstNormalsFace = this.morphNormals[ i ].faceNormals;
9488 var dstNormalsVertex = this.morphNormals[ i ].vertexNormals;
9489
9490 var faceNormal, vertexNormals;
9491
9492 for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
9493
9494 faceNormal = new Vector3();
9495 vertexNormals = { a: new Vector3(), b: new Vector3(), c: new Vector3() };
9496
9497 dstNormalsFace.push( faceNormal );
9498 dstNormalsVertex.push( vertexNormals );
9499
9500 }
9501
9502 }
9503
9504 var morphNormals = this.morphNormals[ i ];
9505
9506 // set vertices to morph target
9507
9508 tmpGeo.vertices = this.morphTargets[ i ].vertices;
9509
9510 // compute morph normals
9511
9512 tmpGeo.computeFaceNormals();
9513 tmpGeo.computeVertexNormals();
9514
9515 // store morph normals
9516
9517 var faceNormal, vertexNormals;
9518
9519 for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
9520
9521 face = this.faces[ f ];
9522
9523 faceNormal = morphNormals.faceNormals[ f ];
9524 vertexNormals = morphNormals.vertexNormals[ f ];
9525
9526 faceNormal.copy( face.normal );
9527
9528 vertexNormals.a.copy( face.vertexNormals[ 0 ] );
9529 vertexNormals.b.copy( face.vertexNormals[ 1 ] );
9530 vertexNormals.c.copy( face.vertexNormals[ 2 ] );
9531
9532 }
9533
9534 }
9535
9536 // restore original normals
9537
9538 for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
9539
9540 face = this.faces[ f ];
9541
9542 face.normal = face.__originalFaceNormal;
9543 face.vertexNormals = face.__originalVertexNormals;
9544
9545 }
9546
9547 },
9548
9549 computeBoundingBox: function () {
9550
9551 if ( this.boundingBox === null ) {
9552
9553 this.boundingBox = new Box3();
9554
9555 }
9556
9557 this.boundingBox.setFromPoints( this.vertices );
9558
9559 },
9560
9561 computeBoundingSphere: function () {
9562
9563 if ( this.boundingSphere === null ) {
9564
9565 this.boundingSphere = new Sphere();
9566
9567 }
9568
9569 this.boundingSphere.setFromPoints( this.vertices );
9570
9571 },
9572
9573 merge: function ( geometry, matrix, materialIndexOffset ) {
9574
9575 if ( ! ( geometry && geometry.isGeometry ) ) {
9576
9577 console.error( 'THREE.Geometry.merge(): geometry not an instance of THREE.Geometry.', geometry );
9578 return;
9579
9580 }
9581
9582 var normalMatrix,
9583 vertexOffset = this.vertices.length,
9584 vertices1 = this.vertices,
9585 vertices2 = geometry.vertices,
9586 faces1 = this.faces,
9587 faces2 = geometry.faces,
9588 uvs1 = this.faceVertexUvs[ 0 ],
9589 uvs2 = geometry.faceVertexUvs[ 0 ],
9590 colors1 = this.colors,
9591 colors2 = geometry.colors;
9592
9593 if ( materialIndexOffset === undefined ) materialIndexOffset = 0;
9594
9595 if ( matrix !== undefined ) {
9596
9597 normalMatrix = new Matrix3().getNormalMatrix( matrix );
9598
9599 }
9600
9601 // vertices
9602
9603 for ( var i = 0, il = vertices2.length; i < il; i ++ ) {
9604
9605 var vertex = vertices2[ i ];
9606
9607 var vertexCopy = vertex.clone();
9608
9609 if ( matrix !== undefined ) vertexCopy.applyMatrix4( matrix );
9610
9611 vertices1.push( vertexCopy );
9612
9613 }
9614
9615 // colors
9616
9617 for ( var i = 0, il = colors2.length; i < il; i ++ ) {
9618
9619 colors1.push( colors2[ i ].clone() );
9620
9621 }
9622
9623 // faces
9624
9625 for ( i = 0, il = faces2.length; i < il; i ++ ) {
9626
9627 var face = faces2[ i ], faceCopy, normal, color,
9628 faceVertexNormals = face.vertexNormals,
9629 faceVertexColors = face.vertexColors;
9630
9631 faceCopy = new Face3( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset );
9632 faceCopy.normal.copy( face.normal );
9633
9634 if ( normalMatrix !== undefined ) {
9635
9636 faceCopy.normal.applyMatrix3( normalMatrix ).normalize();
9637
9638 }
9639
9640 for ( var j = 0, jl = faceVertexNormals.length; j < jl; j ++ ) {
9641
9642 normal = faceVertexNormals[ j ].clone();
9643
9644 if ( normalMatrix !== undefined ) {
9645
9646 normal.applyMatrix3( normalMatrix ).normalize();
9647
9648 }
9649
9650 faceCopy.vertexNormals.push( normal );
9651
9652 }
9653
9654 faceCopy.color.copy( face.color );
9655
9656 for ( var j = 0, jl = faceVertexColors.length; j < jl; j ++ ) {
9657
9658 color = faceVertexColors[ j ];
9659 faceCopy.vertexColors.push( color.clone() );
9660
9661 }
9662
9663 faceCopy.materialIndex = face.materialIndex + materialIndexOffset;
9664
9665 faces1.push( faceCopy );
9666
9667 }
9668
9669 // uvs
9670
9671 for ( i = 0, il = uvs2.length; i < il; i ++ ) {
9672
9673 var uv = uvs2[ i ], uvCopy = [];
9674
9675 if ( uv === undefined ) {
9676
9677 continue;
9678
9679 }
9680
9681 for ( var j = 0, jl = uv.length; j < jl; j ++ ) {
9682
9683 uvCopy.push( uv[ j ].clone() );
9684
9685 }
9686
9687 uvs1.push( uvCopy );
9688
9689 }
9690
9691 },
9692
9693 mergeMesh: function ( mesh ) {
9694
9695 if ( ! ( mesh && mesh.isMesh ) ) {
9696
9697 console.error( 'THREE.Geometry.mergeMesh(): mesh not an instance of THREE.Mesh.', mesh );
9698 return;
9699
9700 }
9701
9702 if ( mesh.matrixAutoUpdate ) mesh.updateMatrix();
9703
9704 this.merge( mesh.geometry, mesh.matrix );
9705
9706 },
9707
9708 /*
9709 * Checks for duplicate vertices with hashmap.
9710 * Duplicated vertices are removed
9711 * and faces' vertices are updated.
9712 */
9713
9714 mergeVertices: function () {
9715
9716 var verticesMap = {}; // Hashmap for looking up vertices by position coordinates (and making sure they are unique)
9717 var unique = [], changes = [];
9718
9719 var v, key;
9720 var precisionPoints = 4; // number of decimal points, e.g. 4 for epsilon of 0.0001
9721 var precision = Math.pow( 10, precisionPoints );
9722 var i, il, face;
9723 var indices, j, jl;
9724
9725 for ( i = 0, il = this.vertices.length; i < il; i ++ ) {
9726
9727 v = this.vertices[ i ];
9728 key = Math.round( v.x * precision ) + '_' + Math.round( v.y * precision ) + '_' + Math.round( v.z * precision );
9729
9730 if ( verticesMap[ key ] === undefined ) {
9731
9732 verticesMap[ key ] = i;
9733 unique.push( this.vertices[ i ] );
9734 changes[ i ] = unique.length - 1;
9735
9736 } else {
9737
9738 //console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]);
9739 changes[ i ] = changes[ verticesMap[ key ] ];
9740
9741 }
9742
9743 }
9744
9745
9746 // if faces are completely degenerate after merging vertices, we
9747 // have to remove them from the geometry.
9748 var faceIndicesToRemove = [];
9749
9750 for ( i = 0, il = this.faces.length; i < il; i ++ ) {
9751
9752 face = this.faces[ i ];
9753
9754 face.a = changes[ face.a ];
9755 face.b = changes[ face.b ];
9756 face.c = changes[ face.c ];
9757
9758 indices = [ face.a, face.b, face.c ];
9759
9760 // if any duplicate vertices are found in a Face3
9761 // we have to remove the face as nothing can be saved
9762 for ( var n = 0; n < 3; n ++ ) {
9763
9764 if ( indices[ n ] === indices[ ( n + 1 ) % 3 ] ) {
9765
9766 faceIndicesToRemove.push( i );
9767 break;
9768
9769 }
9770
9771 }
9772
9773 }
9774
9775 for ( i = faceIndicesToRemove.length - 1; i >= 0; i -- ) {
9776
9777 var idx = faceIndicesToRemove[ i ];
9778
9779 this.faces.splice( idx, 1 );
9780
9781 for ( j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) {
9782
9783 this.faceVertexUvs[ j ].splice( idx, 1 );
9784
9785 }
9786
9787 }
9788
9789 // Use unique set of vertices
9790
9791 var diff = this.vertices.length - unique.length;
9792 this.vertices = unique;
9793 return diff;
9794
9795 },
9796
9797 setFromPoints: function ( points ) {
9798
9799 this.vertices = [];
9800
9801 for ( var i = 0, l = points.length; i < l; i ++ ) {
9802
9803 var point = points[ i ];
9804 this.vertices.push( new Vector3( point.x, point.y, point.z || 0 ) );
9805
9806 }
9807
9808 return this;
9809
9810 },
9811
9812 sortFacesByMaterialIndex: function () {
9813
9814 var faces = this.faces;
9815 var length = faces.length;
9816
9817 // tag faces
9818
9819 for ( var i = 0; i < length; i ++ ) {
9820
9821 faces[ i ]._id = i;
9822
9823 }
9824
9825 // sort faces
9826
9827 function materialIndexSort( a, b ) {
9828
9829 return a.materialIndex - b.materialIndex;
9830
9831 }
9832
9833 faces.sort( materialIndexSort );
9834
9835 // sort uvs
9836
9837 var uvs1 = this.faceVertexUvs[ 0 ];
9838 var uvs2 = this.faceVertexUvs[ 1 ];
9839
9840 var newUvs1, newUvs2;
9841
9842 if ( uvs1 && uvs1.length === length ) newUvs1 = [];
9843 if ( uvs2 && uvs2.length === length ) newUvs2 = [];
9844
9845 for ( var i = 0; i < length; i ++ ) {
9846
9847 var id = faces[ i ]._id;
9848
9849 if ( newUvs1 ) newUvs1.push( uvs1[ id ] );
9850 if ( newUvs2 ) newUvs2.push( uvs2[ id ] );
9851
9852 }
9853
9854 if ( newUvs1 ) this.faceVertexUvs[ 0 ] = newUvs1;
9855 if ( newUvs2 ) this.faceVertexUvs[ 1 ] = newUvs2;
9856
9857 },
9858
9859 toJSON: function () {
9860
9861 var data = {
9862 metadata: {
9863 version: 4.5,
9864 type: 'Geometry',
9865 generator: 'Geometry.toJSON'
9866 }
9867 };
9868
9869 // standard Geometry serialization
9870
9871 data.uuid = this.uuid;
9872 data.type = this.type;
9873 if ( this.name !== '' ) data.name = this.name;
9874
9875 if ( this.parameters !== undefined ) {
9876
9877 var parameters = this.parameters;
9878
9879 for ( var key in parameters ) {
9880
9881 if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ];
9882
9883 }
9884
9885 return data;
9886
9887 }
9888
9889 var vertices = [];
9890
9891 for ( var i = 0; i < this.vertices.length; i ++ ) {
9892
9893 var vertex = this.vertices[ i ];
9894 vertices.push( vertex.x, vertex.y, vertex.z );
9895
9896 }
9897
9898 var faces = [];
9899 var normals = [];
9900 var normalsHash = {};
9901 var colors = [];
9902 var colorsHash = {};
9903 var uvs = [];
9904 var uvsHash = {};
9905
9906 for ( var i = 0; i < this.faces.length; i ++ ) {
9907
9908 var face = this.faces[ i ];
9909
9910 var hasMaterial = true;
9911 var hasFaceUv = false; // deprecated
9912 var hasFaceVertexUv = this.faceVertexUvs[ 0 ][ i ] !== undefined;
9913 var hasFaceNormal = face.normal.length() > 0;
9914 var hasFaceVertexNormal = face.vertexNormals.length > 0;
9915 var hasFaceColor = face.color.r !== 1 || face.color.g !== 1 || face.color.b !== 1;
9916 var hasFaceVertexColor = face.vertexColors.length > 0;
9917
9918 var faceType = 0;
9919
9920 faceType = setBit( faceType, 0, 0 ); // isQuad
9921 faceType = setBit( faceType, 1, hasMaterial );
9922 faceType = setBit( faceType, 2, hasFaceUv );
9923 faceType = setBit( faceType, 3, hasFaceVertexUv );
9924 faceType = setBit( faceType, 4, hasFaceNormal );
9925 faceType = setBit( faceType, 5, hasFaceVertexNormal );
9926 faceType = setBit( faceType, 6, hasFaceColor );
9927 faceType = setBit( faceType, 7, hasFaceVertexColor );
9928
9929 faces.push( faceType );
9930 faces.push( face.a, face.b, face.c );
9931 faces.push( face.materialIndex );
9932
9933 if ( hasFaceVertexUv ) {
9934
9935 var faceVertexUvs = this.faceVertexUvs[ 0 ][ i ];
9936
9937 faces.push(
9938 getUvIndex( faceVertexUvs[ 0 ] ),
9939 getUvIndex( faceVertexUvs[ 1 ] ),
9940 getUvIndex( faceVertexUvs[ 2 ] )
9941 );
9942
9943 }
9944
9945 if ( hasFaceNormal ) {
9946
9947 faces.push( getNormalIndex( face.normal ) );
9948
9949 }
9950
9951 if ( hasFaceVertexNormal ) {
9952
9953 var vertexNormals = face.vertexNormals;
9954
9955 faces.push(
9956 getNormalIndex( vertexNormals[ 0 ] ),
9957 getNormalIndex( vertexNormals[ 1 ] ),
9958 getNormalIndex( vertexNormals[ 2 ] )
9959 );
9960
9961 }
9962
9963 if ( hasFaceColor ) {
9964
9965 faces.push( getColorIndex( face.color ) );
9966
9967 }
9968
9969 if ( hasFaceVertexColor ) {
9970
9971 var vertexColors = face.vertexColors;
9972
9973 faces.push(
9974 getColorIndex( vertexColors[ 0 ] ),
9975 getColorIndex( vertexColors[ 1 ] ),
9976 getColorIndex( vertexColors[ 2 ] )
9977 );
9978
9979 }
9980
9981 }
9982
9983 function setBit( value, position, enabled ) {
9984
9985 return enabled ? value | ( 1 << position ) : value & ( ~ ( 1 << position ) );
9986
9987 }
9988
9989 function getNormalIndex( normal ) {
9990
9991 var hash = normal.x.toString() + normal.y.toString() + normal.z.toString();
9992
9993 if ( normalsHash[ hash ] !== undefined ) {
9994
9995 return normalsHash[ hash ];
9996
9997 }
9998
9999 normalsHash[ hash ] = normals.length / 3;
10000 normals.push( normal.x, normal.y, normal.z );
10001
10002 return normalsHash[ hash ];
10003
10004 }
10005
10006 function getColorIndex( color ) {
10007
10008 var hash = color.r.toString() + color.g.toString() + color.b.toString();
10009
10010 if ( colorsHash[ hash ] !== undefined ) {
10011
10012 return colorsHash[ hash ];
10013
10014 }
10015
10016 colorsHash[ hash ] = colors.length;
10017 colors.push( color.getHex() );
10018
10019 return colorsHash[ hash ];
10020
10021 }
10022
10023 function getUvIndex( uv ) {
10024
10025 var hash = uv.x.toString() + uv.y.toString();
10026
10027 if ( uvsHash[ hash ] !== undefined ) {
10028
10029 return uvsHash[ hash ];
10030
10031 }
10032
10033 uvsHash[ hash ] = uvs.length / 2;
10034 uvs.push( uv.x, uv.y );
10035
10036 return uvsHash[ hash ];
10037
10038 }
10039
10040 data.data = {};
10041
10042 data.data.vertices = vertices;
10043 data.data.normals = normals;
10044 if ( colors.length > 0 ) data.data.colors = colors;
10045 if ( uvs.length > 0 ) data.data.uvs = [ uvs ]; // temporal backward compatibility
10046 data.data.faces = faces;
10047
10048 return data;
10049
10050 },
10051
10052 clone: function () {
10053
10054 /*
10055 // Handle primitives
10056
10057 var parameters = this.parameters;
10058
10059 if ( parameters !== undefined ) {
10060
10061 var values = [];
10062
10063 for ( var key in parameters ) {
10064
10065 values.push( parameters[ key ] );
10066
10067 }
10068
10069 var geometry = Object.create( this.constructor.prototype );
10070 this.constructor.apply( geometry, values );
10071 return geometry;
10072
10073 }
10074
10075 return new this.constructor().copy( this );
10076 */
10077
10078 return new Geometry().copy( this );
10079
10080 },
10081
10082 copy: function ( source ) {
10083
10084 var i, il, j, jl, k, kl;
10085
10086 // reset
10087
10088 this.vertices = [];
10089 this.colors = [];
10090 this.faces = [];
10091 this.faceVertexUvs = [[]];
10092 this.morphTargets = [];
10093 this.morphNormals = [];
10094 this.skinWeights = [];
10095 this.skinIndices = [];
10096 this.lineDistances = [];
10097 this.boundingBox = null;
10098 this.boundingSphere = null;
10099
10100 // name
10101
10102 this.name = source.name;
10103
10104 // vertices
10105
10106 var vertices = source.vertices;
10107
10108 for ( i = 0, il = vertices.length; i < il; i ++ ) {
10109
10110 this.vertices.push( vertices[ i ].clone() );
10111
10112 }
10113
10114 // colors
10115
10116 var colors = source.colors;
10117
10118 for ( i = 0, il = colors.length; i < il; i ++ ) {
10119
10120 this.colors.push( colors[ i ].clone() );
10121
10122 }
10123
10124 // faces
10125
10126 var faces = source.faces;
10127
10128 for ( i = 0, il = faces.length; i < il; i ++ ) {
10129
10130 this.faces.push( faces[ i ].clone() );
10131
10132 }
10133
10134 // face vertex uvs
10135
10136 for ( i = 0, il = source.faceVertexUvs.length; i < il; i ++ ) {
10137
10138 var faceVertexUvs = source.faceVertexUvs[ i ];
10139
10140 if ( this.faceVertexUvs[ i ] === undefined ) {
10141
10142 this.faceVertexUvs[ i ] = [];
10143
10144 }
10145
10146 for ( j = 0, jl = faceVertexUvs.length; j < jl; j ++ ) {
10147
10148 var uvs = faceVertexUvs[ j ], uvsCopy = [];
10149
10150 for ( k = 0, kl = uvs.length; k < kl; k ++ ) {
10151
10152 var uv = uvs[ k ];
10153
10154 uvsCopy.push( uv.clone() );
10155
10156 }
10157
10158 this.faceVertexUvs[ i ].push( uvsCopy );
10159
10160 }
10161
10162 }
10163
10164 // morph targets
10165
10166 var morphTargets = source.morphTargets;
10167
10168 for ( i = 0, il = morphTargets.length; i < il; i ++ ) {
10169
10170 var morphTarget = {};
10171 morphTarget.name = morphTargets[ i ].name;
10172
10173 // vertices
10174
10175 if ( morphTargets[ i ].vertices !== undefined ) {
10176
10177 morphTarget.vertices = [];
10178
10179 for ( j = 0, jl = morphTargets[ i ].vertices.length; j < jl; j ++ ) {
10180
10181 morphTarget.vertices.push( morphTargets[ i ].vertices[ j ].clone() );
10182
10183 }
10184
10185 }
10186
10187 // normals
10188
10189 if ( morphTargets[ i ].normals !== undefined ) {
10190
10191 morphTarget.normals = [];
10192
10193 for ( j = 0, jl = morphTargets[ i ].normals.length; j < jl; j ++ ) {
10194
10195 morphTarget.normals.push( morphTargets[ i ].normals[ j ].clone() );
10196
10197 }
10198
10199 }
10200
10201 this.morphTargets.push( morphTarget );
10202
10203 }
10204
10205 // morph normals
10206
10207 var morphNormals = source.morphNormals;
10208
10209 for ( i = 0, il = morphNormals.length; i < il; i ++ ) {
10210
10211 var morphNormal = {};
10212
10213 // vertex normals
10214
10215 if ( morphNormals[ i ].vertexNormals !== undefined ) {
10216
10217 morphNormal.vertexNormals = [];
10218
10219 for ( j = 0, jl = morphNormals[ i ].vertexNormals.length; j < jl; j ++ ) {
10220
10221 var srcVertexNormal = morphNormals[ i ].vertexNormals[ j ];
10222 var destVertexNormal = {};
10223
10224 destVertexNormal.a = srcVertexNormal.a.clone();
10225 destVertexNormal.b = srcVertexNormal.b.clone();
10226 destVertexNormal.c = srcVertexNormal.c.clone();
10227
10228 morphNormal.vertexNormals.push( destVertexNormal );
10229
10230 }
10231
10232 }
10233
10234 // face normals
10235
10236 if ( morphNormals[ i ].faceNormals !== undefined ) {
10237
10238 morphNormal.faceNormals = [];
10239
10240 for ( j = 0, jl = morphNormals[ i ].faceNormals.length; j < jl; j ++ ) {
10241
10242 morphNormal.faceNormals.push( morphNormals[ i ].faceNormals[ j ].clone() );
10243
10244 }
10245
10246 }
10247
10248 this.morphNormals.push( morphNormal );
10249
10250 }
10251
10252 // skin weights
10253
10254 var skinWeights = source.skinWeights;
10255
10256 for ( i = 0, il = skinWeights.length; i < il; i ++ ) {
10257
10258 this.skinWeights.push( skinWeights[ i ].clone() );
10259
10260 }
10261
10262 // skin indices
10263
10264 var skinIndices = source.skinIndices;
10265
10266 for ( i = 0, il = skinIndices.length; i < il; i ++ ) {
10267
10268 this.skinIndices.push( skinIndices[ i ].clone() );
10269
10270 }
10271
10272 // line distances
10273
10274 var lineDistances = source.lineDistances;
10275
10276 for ( i = 0, il = lineDistances.length; i < il; i ++ ) {
10277
10278 this.lineDistances.push( lineDistances[ i ] );
10279
10280 }
10281
10282 // bounding box
10283
10284 var boundingBox = source.boundingBox;
10285
10286 if ( boundingBox !== null ) {
10287
10288 this.boundingBox = boundingBox.clone();
10289
10290 }
10291
10292 // bounding sphere
10293
10294 var boundingSphere = source.boundingSphere;
10295
10296 if ( boundingSphere !== null ) {
10297
10298 this.boundingSphere = boundingSphere.clone();
10299
10300 }
10301
10302 // update flags
10303
10304 this.elementsNeedUpdate = source.elementsNeedUpdate;
10305 this.verticesNeedUpdate = source.verticesNeedUpdate;
10306 this.uvsNeedUpdate = source.uvsNeedUpdate;
10307 this.normalsNeedUpdate = source.normalsNeedUpdate;
10308 this.colorsNeedUpdate = source.colorsNeedUpdate;
10309 this.lineDistancesNeedUpdate = source.lineDistancesNeedUpdate;
10310 this.groupsNeedUpdate = source.groupsNeedUpdate;
10311
10312 return this;
10313
10314 },
10315
10316 dispose: function () {
10317
10318 this.dispatchEvent( { type: 'dispose' } );
10319
10320 }
10321
10322} );
10323
10324/**
10325 * @author mrdoob / http://mrdoob.com/
10326 */
10327
10328function BufferAttribute( array, itemSize, normalized ) {
10329
10330 if ( Array.isArray( array ) ) {
10331
10332 throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' );
10333
10334 }
10335
10336 this.name = '';
10337
10338 this.array = array;
10339 this.itemSize = itemSize;
10340 this.count = array !== undefined ? array.length / itemSize : 0;
10341 this.normalized = normalized === true;
10342
10343 this.dynamic = false;
10344 this.updateRange = { offset: 0, count: - 1 };
10345
10346 this.version = 0;
10347
10348}
10349
10350Object.defineProperty( BufferAttribute.prototype, 'needsUpdate', {
10351
10352 set: function ( value ) {
10353
10354 if ( value === true ) this.version ++;
10355
10356 }
10357
10358} );
10359
10360Object.assign( BufferAttribute.prototype, {
10361
10362 isBufferAttribute: true,
10363
10364 onUploadCallback: function () {},
10365
10366 setArray: function ( array ) {
10367
10368 if ( Array.isArray( array ) ) {
10369
10370 throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' );
10371
10372 }
10373
10374 this.count = array !== undefined ? array.length / this.itemSize : 0;
10375 this.array = array;
10376
10377 return this;
10378
10379 },
10380
10381 setDynamic: function ( value ) {
10382
10383 this.dynamic = value;
10384
10385 return this;
10386
10387 },
10388
10389 copy: function ( source ) {
10390
10391 this.name = source.name;
10392 this.array = new source.array.constructor( source.array );
10393 this.itemSize = source.itemSize;
10394 this.count = source.count;
10395 this.normalized = source.normalized;
10396
10397 this.dynamic = source.dynamic;
10398
10399 return this;
10400
10401 },
10402
10403 copyAt: function ( index1, attribute, index2 ) {
10404
10405 index1 *= this.itemSize;
10406 index2 *= attribute.itemSize;
10407
10408 for ( var i = 0, l = this.itemSize; i < l; i ++ ) {
10409
10410 this.array[ index1 + i ] = attribute.array[ index2 + i ];
10411
10412 }
10413
10414 return this;
10415
10416 },
10417
10418 copyArray: function ( array ) {
10419
10420 this.array.set( array );
10421
10422 return this;
10423
10424 },
10425
10426 copyColorsArray: function ( colors ) {
10427
10428 var array = this.array, offset = 0;
10429
10430 for ( var i = 0, l = colors.length; i < l; i ++ ) {
10431
10432 var color = colors[ i ];
10433
10434 if ( color === undefined ) {
10435
10436 console.warn( 'THREE.BufferAttribute.copyColorsArray(): color is undefined', i );
10437 color = new Color();
10438
10439 }
10440
10441 array[ offset ++ ] = color.r;
10442 array[ offset ++ ] = color.g;
10443 array[ offset ++ ] = color.b;
10444
10445 }
10446
10447 return this;
10448
10449 },
10450
10451 copyVector2sArray: function ( vectors ) {
10452
10453 var array = this.array, offset = 0;
10454
10455 for ( var i = 0, l = vectors.length; i < l; i ++ ) {
10456
10457 var vector = vectors[ i ];
10458
10459 if ( vector === undefined ) {
10460
10461 console.warn( 'THREE.BufferAttribute.copyVector2sArray(): vector is undefined', i );
10462 vector = new Vector2();
10463
10464 }
10465
10466 array[ offset ++ ] = vector.x;
10467 array[ offset ++ ] = vector.y;
10468
10469 }
10470
10471 return this;
10472
10473 },
10474
10475 copyVector3sArray: function ( vectors ) {
10476
10477 var array = this.array, offset = 0;
10478
10479 for ( var i = 0, l = vectors.length; i < l; i ++ ) {
10480
10481 var vector = vectors[ i ];
10482
10483 if ( vector === undefined ) {
10484
10485 console.warn( 'THREE.BufferAttribute.copyVector3sArray(): vector is undefined', i );
10486 vector = new Vector3();
10487
10488 }
10489
10490 array[ offset ++ ] = vector.x;
10491 array[ offset ++ ] = vector.y;
10492 array[ offset ++ ] = vector.z;
10493
10494 }
10495
10496 return this;
10497
10498 },
10499
10500 copyVector4sArray: function ( vectors ) {
10501
10502 var array = this.array, offset = 0;
10503
10504 for ( var i = 0, l = vectors.length; i < l; i ++ ) {
10505
10506 var vector = vectors[ i ];
10507
10508 if ( vector === undefined ) {
10509
10510 console.warn( 'THREE.BufferAttribute.copyVector4sArray(): vector is undefined', i );
10511 vector = new Vector4();
10512
10513 }
10514
10515 array[ offset ++ ] = vector.x;
10516 array[ offset ++ ] = vector.y;
10517 array[ offset ++ ] = vector.z;
10518 array[ offset ++ ] = vector.w;
10519
10520 }
10521
10522 return this;
10523
10524 },
10525
10526 set: function ( value, offset ) {
10527
10528 if ( offset === undefined ) offset = 0;
10529
10530 this.array.set( value, offset );
10531
10532 return this;
10533
10534 },
10535
10536 getX: function ( index ) {
10537
10538 return this.array[ index * this.itemSize ];
10539
10540 },
10541
10542 setX: function ( index, x ) {
10543
10544 this.array[ index * this.itemSize ] = x;
10545
10546 return this;
10547
10548 },
10549
10550 getY: function ( index ) {
10551
10552 return this.array[ index * this.itemSize + 1 ];
10553
10554 },
10555
10556 setY: function ( index, y ) {
10557
10558 this.array[ index * this.itemSize + 1 ] = y;
10559
10560 return this;
10561
10562 },
10563
10564 getZ: function ( index ) {
10565
10566 return this.array[ index * this.itemSize + 2 ];
10567
10568 },
10569
10570 setZ: function ( index, z ) {
10571
10572 this.array[ index * this.itemSize + 2 ] = z;
10573
10574 return this;
10575
10576 },
10577
10578 getW: function ( index ) {
10579
10580 return this.array[ index * this.itemSize + 3 ];
10581
10582 },
10583
10584 setW: function ( index, w ) {
10585
10586 this.array[ index * this.itemSize + 3 ] = w;
10587
10588 return this;
10589
10590 },
10591
10592 setXY: function ( index, x, y ) {
10593
10594 index *= this.itemSize;
10595
10596 this.array[ index + 0 ] = x;
10597 this.array[ index + 1 ] = y;
10598
10599 return this;
10600
10601 },
10602
10603 setXYZ: function ( index, x, y, z ) {
10604
10605 index *= this.itemSize;
10606
10607 this.array[ index + 0 ] = x;
10608 this.array[ index + 1 ] = y;
10609 this.array[ index + 2 ] = z;
10610
10611 return this;
10612
10613 },
10614
10615 setXYZW: function ( index, x, y, z, w ) {
10616
10617 index *= this.itemSize;
10618
10619 this.array[ index + 0 ] = x;
10620 this.array[ index + 1 ] = y;
10621 this.array[ index + 2 ] = z;
10622 this.array[ index + 3 ] = w;
10623
10624 return this;
10625
10626 },
10627
10628 onUpload: function ( callback ) {
10629
10630 this.onUploadCallback = callback;
10631
10632 return this;
10633
10634 },
10635
10636 clone: function () {
10637
10638 return new this.constructor( this.array, this.itemSize ).copy( this );
10639
10640 }
10641
10642} );
10643
10644//
10645
10646function Int8BufferAttribute( array, itemSize, normalized ) {
10647
10648 BufferAttribute.call( this, new Int8Array( array ), itemSize, normalized );
10649
10650}
10651
10652Int8BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
10653Int8BufferAttribute.prototype.constructor = Int8BufferAttribute;
10654
10655
10656function Uint8BufferAttribute( array, itemSize, normalized ) {
10657
10658 BufferAttribute.call( this, new Uint8Array( array ), itemSize, normalized );
10659
10660}
10661
10662Uint8BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
10663Uint8BufferAttribute.prototype.constructor = Uint8BufferAttribute;
10664
10665
10666function Uint8ClampedBufferAttribute( array, itemSize, normalized ) {
10667
10668 BufferAttribute.call( this, new Uint8ClampedArray( array ), itemSize, normalized );
10669
10670}
10671
10672Uint8ClampedBufferAttribute.prototype = Object.create( BufferAttribute.prototype );
10673Uint8ClampedBufferAttribute.prototype.constructor = Uint8ClampedBufferAttribute;
10674
10675
10676function Int16BufferAttribute( array, itemSize, normalized ) {
10677
10678 BufferAttribute.call( this, new Int16Array( array ), itemSize, normalized );
10679
10680}
10681
10682Int16BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
10683Int16BufferAttribute.prototype.constructor = Int16BufferAttribute;
10684
10685
10686function Uint16BufferAttribute( array, itemSize, normalized ) {
10687
10688 BufferAttribute.call( this, new Uint16Array( array ), itemSize, normalized );
10689
10690}
10691
10692Uint16BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
10693Uint16BufferAttribute.prototype.constructor = Uint16BufferAttribute;
10694
10695
10696function Int32BufferAttribute( array, itemSize, normalized ) {
10697
10698 BufferAttribute.call( this, new Int32Array( array ), itemSize, normalized );
10699
10700}
10701
10702Int32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
10703Int32BufferAttribute.prototype.constructor = Int32BufferAttribute;
10704
10705
10706function Uint32BufferAttribute( array, itemSize, normalized ) {
10707
10708 BufferAttribute.call( this, new Uint32Array( array ), itemSize, normalized );
10709
10710}
10711
10712Uint32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
10713Uint32BufferAttribute.prototype.constructor = Uint32BufferAttribute;
10714
10715
10716function Float32BufferAttribute( array, itemSize, normalized ) {
10717
10718 BufferAttribute.call( this, new Float32Array( array ), itemSize, normalized );
10719
10720}
10721
10722Float32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
10723Float32BufferAttribute.prototype.constructor = Float32BufferAttribute;
10724
10725
10726function Float64BufferAttribute( array, itemSize, normalized ) {
10727
10728 BufferAttribute.call( this, new Float64Array( array ), itemSize, normalized );
10729
10730}
10731
10732Float64BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
10733Float64BufferAttribute.prototype.constructor = Float64BufferAttribute;
10734
10735/**
10736 * @author mrdoob / http://mrdoob.com/
10737 */
10738
10739function DirectGeometry() {
10740
10741 this.vertices = [];
10742 this.normals = [];
10743 this.colors = [];
10744 this.uvs = [];
10745 this.uvs2 = [];
10746
10747 this.groups = [];
10748
10749 this.morphTargets = {};
10750
10751 this.skinWeights = [];
10752 this.skinIndices = [];
10753
10754 // this.lineDistances = [];
10755
10756 this.boundingBox = null;
10757 this.boundingSphere = null;
10758
10759 // update flags
10760
10761 this.verticesNeedUpdate = false;
10762 this.normalsNeedUpdate = false;
10763 this.colorsNeedUpdate = false;
10764 this.uvsNeedUpdate = false;
10765 this.groupsNeedUpdate = false;
10766
10767}
10768
10769Object.assign( DirectGeometry.prototype, {
10770
10771 computeGroups: function ( geometry ) {
10772
10773 var group;
10774 var groups = [];
10775 var materialIndex = undefined;
10776
10777 var faces = geometry.faces;
10778
10779 for ( var i = 0; i < faces.length; i ++ ) {
10780
10781 var face = faces[ i ];
10782
10783 // materials
10784
10785 if ( face.materialIndex !== materialIndex ) {
10786
10787 materialIndex = face.materialIndex;
10788
10789 if ( group !== undefined ) {
10790
10791 group.count = ( i * 3 ) - group.start;
10792 groups.push( group );
10793
10794 }
10795
10796 group = {
10797 start: i * 3,
10798 materialIndex: materialIndex
10799 };
10800
10801 }
10802
10803 }
10804
10805 if ( group !== undefined ) {
10806
10807 group.count = ( i * 3 ) - group.start;
10808 groups.push( group );
10809
10810 }
10811
10812 this.groups = groups;
10813
10814 },
10815
10816 fromGeometry: function ( geometry ) {
10817
10818 var faces = geometry.faces;
10819 var vertices = geometry.vertices;
10820 var faceVertexUvs = geometry.faceVertexUvs;
10821
10822 var hasFaceVertexUv = faceVertexUvs[ 0 ] && faceVertexUvs[ 0 ].length > 0;
10823 var hasFaceVertexUv2 = faceVertexUvs[ 1 ] && faceVertexUvs[ 1 ].length > 0;
10824
10825 // morphs
10826
10827 var morphTargets = geometry.morphTargets;
10828 var morphTargetsLength = morphTargets.length;
10829
10830 var morphTargetsPosition;
10831
10832 if ( morphTargetsLength > 0 ) {
10833
10834 morphTargetsPosition = [];
10835
10836 for ( var i = 0; i < morphTargetsLength; i ++ ) {
10837
10838 morphTargetsPosition[ i ] = [];
10839
10840 }
10841
10842 this.morphTargets.position = morphTargetsPosition;
10843
10844 }
10845
10846 var morphNormals = geometry.morphNormals;
10847 var morphNormalsLength = morphNormals.length;
10848
10849 var morphTargetsNormal;
10850
10851 if ( morphNormalsLength > 0 ) {
10852
10853 morphTargetsNormal = [];
10854
10855 for ( var i = 0; i < morphNormalsLength; i ++ ) {
10856
10857 morphTargetsNormal[ i ] = [];
10858
10859 }
10860
10861 this.morphTargets.normal = morphTargetsNormal;
10862
10863 }
10864
10865 // skins
10866
10867 var skinIndices = geometry.skinIndices;
10868 var skinWeights = geometry.skinWeights;
10869
10870 var hasSkinIndices = skinIndices.length === vertices.length;
10871 var hasSkinWeights = skinWeights.length === vertices.length;
10872
10873 //
10874
10875 for ( var i = 0; i < faces.length; i ++ ) {
10876
10877 var face = faces[ i ];
10878
10879 this.vertices.push( vertices[ face.a ], vertices[ face.b ], vertices[ face.c ] );
10880
10881 var vertexNormals = face.vertexNormals;
10882
10883 if ( vertexNormals.length === 3 ) {
10884
10885 this.normals.push( vertexNormals[ 0 ], vertexNormals[ 1 ], vertexNormals[ 2 ] );
10886
10887 } else {
10888
10889 var normal = face.normal;
10890
10891 this.normals.push( normal, normal, normal );
10892
10893 }
10894
10895 var vertexColors = face.vertexColors;
10896
10897 if ( vertexColors.length === 3 ) {
10898
10899 this.colors.push( vertexColors[ 0 ], vertexColors[ 1 ], vertexColors[ 2 ] );
10900
10901 } else {
10902
10903 var color = face.color;
10904
10905 this.colors.push( color, color, color );
10906
10907 }
10908
10909 if ( hasFaceVertexUv === true ) {
10910
10911 var vertexUvs = faceVertexUvs[ 0 ][ i ];
10912
10913 if ( vertexUvs !== undefined ) {
10914
10915 this.uvs.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] );
10916
10917 } else {
10918
10919 console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv ', i );
10920
10921 this.uvs.push( new Vector2(), new Vector2(), new Vector2() );
10922
10923 }
10924
10925 }
10926
10927 if ( hasFaceVertexUv2 === true ) {
10928
10929 var vertexUvs = faceVertexUvs[ 1 ][ i ];
10930
10931 if ( vertexUvs !== undefined ) {
10932
10933 this.uvs2.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] );
10934
10935 } else {
10936
10937 console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv2 ', i );
10938
10939 this.uvs2.push( new Vector2(), new Vector2(), new Vector2() );
10940
10941 }
10942
10943 }
10944
10945 // morphs
10946
10947 for ( var j = 0; j < morphTargetsLength; j ++ ) {
10948
10949 var morphTarget = morphTargets[ j ].vertices;
10950
10951 morphTargetsPosition[ j ].push( morphTarget[ face.a ], morphTarget[ face.b ], morphTarget[ face.c ] );
10952
10953 }
10954
10955 for ( var j = 0; j < morphNormalsLength; j ++ ) {
10956
10957 var morphNormal = morphNormals[ j ].vertexNormals[ i ];
10958
10959 morphTargetsNormal[ j ].push( morphNormal.a, morphNormal.b, morphNormal.c );
10960
10961 }
10962
10963 // skins
10964
10965 if ( hasSkinIndices ) {
10966
10967 this.skinIndices.push( skinIndices[ face.a ], skinIndices[ face.b ], skinIndices[ face.c ] );
10968
10969 }
10970
10971 if ( hasSkinWeights ) {
10972
10973 this.skinWeights.push( skinWeights[ face.a ], skinWeights[ face.b ], skinWeights[ face.c ] );
10974
10975 }
10976
10977 }
10978
10979 this.computeGroups( geometry );
10980
10981 this.verticesNeedUpdate = geometry.verticesNeedUpdate;
10982 this.normalsNeedUpdate = geometry.normalsNeedUpdate;
10983 this.colorsNeedUpdate = geometry.colorsNeedUpdate;
10984 this.uvsNeedUpdate = geometry.uvsNeedUpdate;
10985 this.groupsNeedUpdate = geometry.groupsNeedUpdate;
10986
10987 return this;
10988
10989 }
10990
10991} );
10992
10993/**
10994 * @author mrdoob / http://mrdoob.com/
10995 */
10996
10997function arrayMax( array ) {
10998
10999 if ( array.length === 0 ) return - Infinity;
11000
11001 var max = array[ 0 ];
11002
11003 for ( var i = 1, l = array.length; i < l; ++ i ) {
11004
11005 if ( array[ i ] > max ) max = array[ i ];
11006
11007 }
11008
11009 return max;
11010
11011}
11012
11013/**
11014 * @author alteredq / http://alteredqualia.com/
11015 * @author mrdoob / http://mrdoob.com/
11016 */
11017
11018var bufferGeometryId = 1; // BufferGeometry uses odd numbers as Id
11019
11020function BufferGeometry() {
11021
11022 Object.defineProperty( this, 'id', { value: bufferGeometryId += 2 } );
11023
11024 this.uuid = _Math.generateUUID();
11025
11026 this.name = '';
11027 this.type = 'BufferGeometry';
11028
11029 this.index = null;
11030 this.attributes = {};
11031
11032 this.morphAttributes = {};
11033
11034 this.groups = [];
11035
11036 this.boundingBox = null;
11037 this.boundingSphere = null;
11038
11039 this.drawRange = { start: 0, count: Infinity };
11040
11041}
11042
11043BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
11044
11045 constructor: BufferGeometry,
11046
11047 isBufferGeometry: true,
11048
11049 getIndex: function () {
11050
11051 return this.index;
11052
11053 },
11054
11055 setIndex: function ( index ) {
11056
11057 if ( Array.isArray( index ) ) {
11058
11059 this.index = new ( arrayMax( index ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 );
11060
11061 } else {
11062
11063 this.index = index;
11064
11065 }
11066
11067 },
11068
11069 addAttribute: function ( name, attribute ) {
11070
11071 if ( ! ( attribute && attribute.isBufferAttribute ) && ! ( attribute && attribute.isInterleavedBufferAttribute ) ) {
11072
11073 console.warn( 'THREE.BufferGeometry: .addAttribute() now expects ( name, attribute ).' );
11074
11075 this.addAttribute( name, new BufferAttribute( arguments[ 1 ], arguments[ 2 ] ) );
11076
11077 return;
11078
11079 }
11080
11081 if ( name === 'index' ) {
11082
11083 console.warn( 'THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute.' );
11084 this.setIndex( attribute );
11085
11086 return;
11087
11088 }
11089
11090 this.attributes[ name ] = attribute;
11091
11092 return this;
11093
11094 },
11095
11096 getAttribute: function ( name ) {
11097
11098 return this.attributes[ name ];
11099
11100 },
11101
11102 removeAttribute: function ( name ) {
11103
11104 delete this.attributes[ name ];
11105
11106 return this;
11107
11108 },
11109
11110 addGroup: function ( start, count, materialIndex ) {
11111
11112 this.groups.push( {
11113
11114 start: start,
11115 count: count,
11116 materialIndex: materialIndex !== undefined ? materialIndex : 0
11117
11118 } );
11119
11120 },
11121
11122 clearGroups: function () {
11123
11124 this.groups = [];
11125
11126 },
11127
11128 setDrawRange: function ( start, count ) {
11129
11130 this.drawRange.start = start;
11131 this.drawRange.count = count;
11132
11133 },
11134
11135 applyMatrix: function ( matrix ) {
11136
11137 var position = this.attributes.position;
11138
11139 if ( position !== undefined ) {
11140
11141 matrix.applyToBufferAttribute( position );
11142 position.needsUpdate = true;
11143
11144 }
11145
11146 var normal = this.attributes.normal;
11147
11148 if ( normal !== undefined ) {
11149
11150 var normalMatrix = new Matrix3().getNormalMatrix( matrix );
11151
11152 normalMatrix.applyToBufferAttribute( normal );
11153 normal.needsUpdate = true;
11154
11155 }
11156
11157 if ( this.boundingBox !== null ) {
11158
11159 this.computeBoundingBox();
11160
11161 }
11162
11163 if ( this.boundingSphere !== null ) {
11164
11165 this.computeBoundingSphere();
11166
11167 }
11168
11169 return this;
11170
11171 },
11172
11173 rotateX: function () {
11174
11175 // rotate geometry around world x-axis
11176
11177 var m1 = new Matrix4();
11178
11179 return function rotateX( angle ) {
11180
11181 m1.makeRotationX( angle );
11182
11183 this.applyMatrix( m1 );
11184
11185 return this;
11186
11187 };
11188
11189 }(),
11190
11191 rotateY: function () {
11192
11193 // rotate geometry around world y-axis
11194
11195 var m1 = new Matrix4();
11196
11197 return function rotateY( angle ) {
11198
11199 m1.makeRotationY( angle );
11200
11201 this.applyMatrix( m1 );
11202
11203 return this;
11204
11205 };
11206
11207 }(),
11208
11209 rotateZ: function () {
11210
11211 // rotate geometry around world z-axis
11212
11213 var m1 = new Matrix4();
11214
11215 return function rotateZ( angle ) {
11216
11217 m1.makeRotationZ( angle );
11218
11219 this.applyMatrix( m1 );
11220
11221 return this;
11222
11223 };
11224
11225 }(),
11226
11227 translate: function () {
11228
11229 // translate geometry
11230
11231 var m1 = new Matrix4();
11232
11233 return function translate( x, y, z ) {
11234
11235 m1.makeTranslation( x, y, z );
11236
11237 this.applyMatrix( m1 );
11238
11239 return this;
11240
11241 };
11242
11243 }(),
11244
11245 scale: function () {
11246
11247 // scale geometry
11248
11249 var m1 = new Matrix4();
11250
11251 return function scale( x, y, z ) {
11252
11253 m1.makeScale( x, y, z );
11254
11255 this.applyMatrix( m1 );
11256
11257 return this;
11258
11259 };
11260
11261 }(),
11262
11263 lookAt: function () {
11264
11265 var obj = new Object3D();
11266
11267 return function lookAt( vector ) {
11268
11269 obj.lookAt( vector );
11270
11271 obj.updateMatrix();
11272
11273 this.applyMatrix( obj.matrix );
11274
11275 };
11276
11277 }(),
11278
11279 center: function () {
11280
11281 var offset = new Vector3();
11282
11283 return function center() {
11284
11285 this.computeBoundingBox();
11286
11287 this.boundingBox.getCenter( offset ).negate();
11288
11289 this.translate( offset.x, offset.y, offset.z );
11290
11291 return this;
11292
11293 };
11294
11295 }(),
11296
11297 setFromObject: function ( object ) {
11298
11299 // console.log( 'THREE.BufferGeometry.setFromObject(). Converting', object, this );
11300
11301 var geometry = object.geometry;
11302
11303 if ( object.isPoints || object.isLine ) {
11304
11305 var positions = new Float32BufferAttribute( geometry.vertices.length * 3, 3 );
11306 var colors = new Float32BufferAttribute( geometry.colors.length * 3, 3 );
11307
11308 this.addAttribute( 'position', positions.copyVector3sArray( geometry.vertices ) );
11309 this.addAttribute( 'color', colors.copyColorsArray( geometry.colors ) );
11310
11311 if ( geometry.lineDistances && geometry.lineDistances.length === geometry.vertices.length ) {
11312
11313 var lineDistances = new Float32BufferAttribute( geometry.lineDistances.length, 1 );
11314
11315 this.addAttribute( 'lineDistance', lineDistances.copyArray( geometry.lineDistances ) );
11316
11317 }
11318
11319 if ( geometry.boundingSphere !== null ) {
11320
11321 this.boundingSphere = geometry.boundingSphere.clone();
11322
11323 }
11324
11325 if ( geometry.boundingBox !== null ) {
11326
11327 this.boundingBox = geometry.boundingBox.clone();
11328
11329 }
11330
11331 } else if ( object.isMesh ) {
11332
11333 if ( geometry && geometry.isGeometry ) {
11334
11335 this.fromGeometry( geometry );
11336
11337 }
11338
11339 }
11340
11341 return this;
11342
11343 },
11344
11345 setFromPoints: function ( points ) {
11346
11347 var position = [];
11348
11349 for ( var i = 0, l = points.length; i < l; i ++ ) {
11350
11351 var point = points[ i ];
11352 position.push( point.x, point.y, point.z || 0 );
11353
11354 }
11355
11356 this.addAttribute( 'position', new Float32BufferAttribute( position, 3 ) );
11357
11358 return this;
11359
11360 },
11361
11362 updateFromObject: function ( object ) {
11363
11364 var geometry = object.geometry;
11365
11366 if ( object.isMesh ) {
11367
11368 var direct = geometry.__directGeometry;
11369
11370 if ( geometry.elementsNeedUpdate === true ) {
11371
11372 direct = undefined;
11373 geometry.elementsNeedUpdate = false;
11374
11375 }
11376
11377 if ( direct === undefined ) {
11378
11379 return this.fromGeometry( geometry );
11380
11381 }
11382
11383 direct.verticesNeedUpdate = geometry.verticesNeedUpdate;
11384 direct.normalsNeedUpdate = geometry.normalsNeedUpdate;
11385 direct.colorsNeedUpdate = geometry.colorsNeedUpdate;
11386 direct.uvsNeedUpdate = geometry.uvsNeedUpdate;
11387 direct.groupsNeedUpdate = geometry.groupsNeedUpdate;
11388
11389 geometry.verticesNeedUpdate = false;
11390 geometry.normalsNeedUpdate = false;
11391 geometry.colorsNeedUpdate = false;
11392 geometry.uvsNeedUpdate = false;
11393 geometry.groupsNeedUpdate = false;
11394
11395 geometry = direct;
11396
11397 }
11398
11399 var attribute;
11400
11401 if ( geometry.verticesNeedUpdate === true ) {
11402
11403 attribute = this.attributes.position;
11404
11405 if ( attribute !== undefined ) {
11406
11407 attribute.copyVector3sArray( geometry.vertices );
11408 attribute.needsUpdate = true;
11409
11410 }
11411
11412 geometry.verticesNeedUpdate = false;
11413
11414 }
11415
11416 if ( geometry.normalsNeedUpdate === true ) {
11417
11418 attribute = this.attributes.normal;
11419
11420 if ( attribute !== undefined ) {
11421
11422 attribute.copyVector3sArray( geometry.normals );
11423 attribute.needsUpdate = true;
11424
11425 }
11426
11427 geometry.normalsNeedUpdate = false;
11428
11429 }
11430
11431 if ( geometry.colorsNeedUpdate === true ) {
11432
11433 attribute = this.attributes.color;
11434
11435 if ( attribute !== undefined ) {
11436
11437 attribute.copyColorsArray( geometry.colors );
11438 attribute.needsUpdate = true;
11439
11440 }
11441
11442 geometry.colorsNeedUpdate = false;
11443
11444 }
11445
11446 if ( geometry.uvsNeedUpdate ) {
11447
11448 attribute = this.attributes.uv;
11449
11450 if ( attribute !== undefined ) {
11451
11452 attribute.copyVector2sArray( geometry.uvs );
11453 attribute.needsUpdate = true;
11454
11455 }
11456
11457 geometry.uvsNeedUpdate = false;
11458
11459 }
11460
11461 if ( geometry.lineDistancesNeedUpdate ) {
11462
11463 attribute = this.attributes.lineDistance;
11464
11465 if ( attribute !== undefined ) {
11466
11467 attribute.copyArray( geometry.lineDistances );
11468 attribute.needsUpdate = true;
11469
11470 }
11471
11472 geometry.lineDistancesNeedUpdate = false;
11473
11474 }
11475
11476 if ( geometry.groupsNeedUpdate ) {
11477
11478 geometry.computeGroups( object.geometry );
11479 this.groups = geometry.groups;
11480
11481 geometry.groupsNeedUpdate = false;
11482
11483 }
11484
11485 return this;
11486
11487 },
11488
11489 fromGeometry: function ( geometry ) {
11490
11491 geometry.__directGeometry = new DirectGeometry().fromGeometry( geometry );
11492
11493 return this.fromDirectGeometry( geometry.__directGeometry );
11494
11495 },
11496
11497 fromDirectGeometry: function ( geometry ) {
11498
11499 var positions = new Float32Array( geometry.vertices.length * 3 );
11500 this.addAttribute( 'position', new BufferAttribute( positions, 3 ).copyVector3sArray( geometry.vertices ) );
11501
11502 if ( geometry.normals.length > 0 ) {
11503
11504 var normals = new Float32Array( geometry.normals.length * 3 );
11505 this.addAttribute( 'normal', new BufferAttribute( normals, 3 ).copyVector3sArray( geometry.normals ) );
11506
11507 }
11508
11509 if ( geometry.colors.length > 0 ) {
11510
11511 var colors = new Float32Array( geometry.colors.length * 3 );
11512 this.addAttribute( 'color', new BufferAttribute( colors, 3 ).copyColorsArray( geometry.colors ) );
11513
11514 }
11515
11516 if ( geometry.uvs.length > 0 ) {
11517
11518 var uvs = new Float32Array( geometry.uvs.length * 2 );
11519 this.addAttribute( 'uv', new BufferAttribute( uvs, 2 ).copyVector2sArray( geometry.uvs ) );
11520
11521 }
11522
11523 if ( geometry.uvs2.length > 0 ) {
11524
11525 var uvs2 = new Float32Array( geometry.uvs2.length * 2 );
11526 this.addAttribute( 'uv2', new BufferAttribute( uvs2, 2 ).copyVector2sArray( geometry.uvs2 ) );
11527
11528 }
11529
11530 // groups
11531
11532 this.groups = geometry.groups;
11533
11534 // morphs
11535
11536 for ( var name in geometry.morphTargets ) {
11537
11538 var array = [];
11539 var morphTargets = geometry.morphTargets[ name ];
11540
11541 for ( var i = 0, l = morphTargets.length; i < l; i ++ ) {
11542
11543 var morphTarget = morphTargets[ i ];
11544
11545 var attribute = new Float32BufferAttribute( morphTarget.length * 3, 3 );
11546
11547 array.push( attribute.copyVector3sArray( morphTarget ) );
11548
11549 }
11550
11551 this.morphAttributes[ name ] = array;
11552
11553 }
11554
11555 // skinning
11556
11557 if ( geometry.skinIndices.length > 0 ) {
11558
11559 var skinIndices = new Float32BufferAttribute( geometry.skinIndices.length * 4, 4 );
11560 this.addAttribute( 'skinIndex', skinIndices.copyVector4sArray( geometry.skinIndices ) );
11561
11562 }
11563
11564 if ( geometry.skinWeights.length > 0 ) {
11565
11566 var skinWeights = new Float32BufferAttribute( geometry.skinWeights.length * 4, 4 );
11567 this.addAttribute( 'skinWeight', skinWeights.copyVector4sArray( geometry.skinWeights ) );
11568
11569 }
11570
11571 //
11572
11573 if ( geometry.boundingSphere !== null ) {
11574
11575 this.boundingSphere = geometry.boundingSphere.clone();
11576
11577 }
11578
11579 if ( geometry.boundingBox !== null ) {
11580
11581 this.boundingBox = geometry.boundingBox.clone();
11582
11583 }
11584
11585 return this;
11586
11587 },
11588
11589 computeBoundingBox: function () {
11590
11591 if ( this.boundingBox === null ) {
11592
11593 this.boundingBox = new Box3();
11594
11595 }
11596
11597 var position = this.attributes.position;
11598
11599 if ( position !== undefined ) {
11600
11601 this.boundingBox.setFromBufferAttribute( position );
11602
11603 } else {
11604
11605 this.boundingBox.makeEmpty();
11606
11607 }
11608
11609 if ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) {
11610
11611 console.error( 'THREE.BufferGeometry.computeBoundingBox: Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this );
11612
11613 }
11614
11615 },
11616
11617 computeBoundingSphere: function () {
11618
11619 var box = new Box3();
11620 var vector = new Vector3();
11621
11622 return function computeBoundingSphere() {
11623
11624 if ( this.boundingSphere === null ) {
11625
11626 this.boundingSphere = new Sphere();
11627
11628 }
11629
11630 var position = this.attributes.position;
11631
11632 if ( position ) {
11633
11634 var center = this.boundingSphere.center;
11635
11636 box.setFromBufferAttribute( position );
11637 box.getCenter( center );
11638
11639 // hoping to find a boundingSphere with a radius smaller than the
11640 // boundingSphere of the boundingBox: sqrt(3) smaller in the best case
11641
11642 var maxRadiusSq = 0;
11643
11644 for ( var i = 0, il = position.count; i < il; i ++ ) {
11645
11646 vector.x = position.getX( i );
11647 vector.y = position.getY( i );
11648 vector.z = position.getZ( i );
11649 maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( vector ) );
11650
11651 }
11652
11653 this.boundingSphere.radius = Math.sqrt( maxRadiusSq );
11654
11655 if ( isNaN( this.boundingSphere.radius ) ) {
11656
11657 console.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this );
11658
11659 }
11660
11661 }
11662
11663 };
11664
11665 }(),
11666
11667 computeFaceNormals: function () {
11668
11669 // backwards compatibility
11670
11671 },
11672
11673 computeVertexNormals: function () {
11674
11675 var index = this.index;
11676 var attributes = this.attributes;
11677 var groups = this.groups;
11678
11679 if ( attributes.position ) {
11680
11681 var positions = attributes.position.array;
11682
11683 if ( attributes.normal === undefined ) {
11684
11685 this.addAttribute( 'normal', new BufferAttribute( new Float32Array( positions.length ), 3 ) );
11686
11687 } else {
11688
11689 // reset existing normals to zero
11690
11691 var array = attributes.normal.array;
11692
11693 for ( var i = 0, il = array.length; i < il; i ++ ) {
11694
11695 array[ i ] = 0;
11696
11697 }
11698
11699 }
11700
11701 var normals = attributes.normal.array;
11702
11703 var vA, vB, vC;
11704 var pA = new Vector3(), pB = new Vector3(), pC = new Vector3();
11705 var cb = new Vector3(), ab = new Vector3();
11706
11707 // indexed elements
11708
11709 if ( index ) {
11710
11711 var indices = index.array;
11712
11713 if ( groups.length === 0 ) {
11714
11715 this.addGroup( 0, indices.length );
11716
11717 }
11718
11719 for ( var j = 0, jl = groups.length; j < jl; ++ j ) {
11720
11721 var group = groups[ j ];
11722
11723 var start = group.start;
11724 var count = group.count;
11725
11726 for ( var i = start, il = start + count; i < il; i += 3 ) {
11727
11728 vA = indices[ i + 0 ] * 3;
11729 vB = indices[ i + 1 ] * 3;
11730 vC = indices[ i + 2 ] * 3;
11731
11732 pA.fromArray( positions, vA );
11733 pB.fromArray( positions, vB );
11734 pC.fromArray( positions, vC );
11735
11736 cb.subVectors( pC, pB );
11737 ab.subVectors( pA, pB );
11738 cb.cross( ab );
11739
11740 normals[ vA ] += cb.x;
11741 normals[ vA + 1 ] += cb.y;
11742 normals[ vA + 2 ] += cb.z;
11743
11744 normals[ vB ] += cb.x;
11745 normals[ vB + 1 ] += cb.y;
11746 normals[ vB + 2 ] += cb.z;
11747
11748 normals[ vC ] += cb.x;
11749 normals[ vC + 1 ] += cb.y;
11750 normals[ vC + 2 ] += cb.z;
11751
11752 }
11753
11754 }
11755
11756 } else {
11757
11758 // non-indexed elements (unconnected triangle soup)
11759
11760 for ( var i = 0, il = positions.length; i < il; i += 9 ) {
11761
11762 pA.fromArray( positions, i );
11763 pB.fromArray( positions, i + 3 );
11764 pC.fromArray( positions, i + 6 );
11765
11766 cb.subVectors( pC, pB );
11767 ab.subVectors( pA, pB );
11768 cb.cross( ab );
11769
11770 normals[ i ] = cb.x;
11771 normals[ i + 1 ] = cb.y;
11772 normals[ i + 2 ] = cb.z;
11773
11774 normals[ i + 3 ] = cb.x;
11775 normals[ i + 4 ] = cb.y;
11776 normals[ i + 5 ] = cb.z;
11777
11778 normals[ i + 6 ] = cb.x;
11779 normals[ i + 7 ] = cb.y;
11780 normals[ i + 8 ] = cb.z;
11781
11782 }
11783
11784 }
11785
11786 this.normalizeNormals();
11787
11788 attributes.normal.needsUpdate = true;
11789
11790 }
11791
11792 },
11793
11794 merge: function ( geometry, offset ) {
11795
11796 if ( ! ( geometry && geometry.isBufferGeometry ) ) {
11797
11798 console.error( 'THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.', geometry );
11799 return;
11800
11801 }
11802
11803 if ( offset === undefined ) {
11804
11805 offset = 0;
11806
11807 console.warn(
11808 'THREE.BufferGeometry.merge(): Overwriting original geometry, starting at offset=0. '
11809 + 'Use BufferGeometryUtils.mergeBufferGeometries() for lossless merge.'
11810 );
11811
11812 }
11813
11814 var attributes = this.attributes;
11815
11816 for ( var key in attributes ) {
11817
11818 if ( geometry.attributes[ key ] === undefined ) continue;
11819
11820 var attribute1 = attributes[ key ];
11821 var attributeArray1 = attribute1.array;
11822
11823 var attribute2 = geometry.attributes[ key ];
11824 var attributeArray2 = attribute2.array;
11825
11826 var attributeSize = attribute2.itemSize;
11827
11828 for ( var i = 0, j = attributeSize * offset; i < attributeArray2.length; i ++, j ++ ) {
11829
11830 attributeArray1[ j ] = attributeArray2[ i ];
11831
11832 }
11833
11834 }
11835
11836 return this;
11837
11838 },
11839
11840 normalizeNormals: function () {
11841
11842 var vector = new Vector3();
11843
11844 return function normalizeNormals() {
11845
11846 var normals = this.attributes.normal;
11847
11848 for ( var i = 0, il = normals.count; i < il; i ++ ) {
11849
11850 vector.x = normals.getX( i );
11851 vector.y = normals.getY( i );
11852 vector.z = normals.getZ( i );
11853
11854 vector.normalize();
11855
11856 normals.setXYZ( i, vector.x, vector.y, vector.z );
11857
11858 }
11859
11860 };
11861
11862 }(),
11863
11864 toNonIndexed: function () {
11865
11866 if ( this.index === null ) {
11867
11868 console.warn( 'THREE.BufferGeometry.toNonIndexed(): Geometry is already non-indexed.' );
11869 return this;
11870
11871 }
11872
11873 var geometry2 = new BufferGeometry();
11874
11875 var indices = this.index.array;
11876 var attributes = this.attributes;
11877
11878 for ( var name in attributes ) {
11879
11880 var attribute = attributes[ name ];
11881
11882 var array = attribute.array;
11883 var itemSize = attribute.itemSize;
11884
11885 var array2 = new array.constructor( indices.length * itemSize );
11886
11887 var index = 0, index2 = 0;
11888
11889 for ( var i = 0, l = indices.length; i < l; i ++ ) {
11890
11891 index = indices[ i ] * itemSize;
11892
11893 for ( var j = 0; j < itemSize; j ++ ) {
11894
11895 array2[ index2 ++ ] = array[ index ++ ];
11896
11897 }
11898
11899 }
11900
11901 geometry2.addAttribute( name, new BufferAttribute( array2, itemSize ) );
11902
11903 }
11904
11905 var groups = this.groups;
11906
11907 for ( var i = 0, l = groups.length; i < l; i ++ ) {
11908
11909 var group = groups[ i ];
11910 geometry2.addGroup( group.start, group.count, group.materialIndex );
11911
11912 }
11913
11914 return geometry2;
11915
11916 },
11917
11918 toJSON: function () {
11919
11920 var data = {
11921 metadata: {
11922 version: 4.5,
11923 type: 'BufferGeometry',
11924 generator: 'BufferGeometry.toJSON'
11925 }
11926 };
11927
11928 // standard BufferGeometry serialization
11929
11930 data.uuid = this.uuid;
11931 data.type = this.type;
11932 if ( this.name !== '' ) data.name = this.name;
11933
11934 if ( this.parameters !== undefined ) {
11935
11936 var parameters = this.parameters;
11937
11938 for ( var key in parameters ) {
11939
11940 if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ];
11941
11942 }
11943
11944 return data;
11945
11946 }
11947
11948 data.data = { attributes: {} };
11949
11950 var index = this.index;
11951
11952 if ( index !== null ) {
11953
11954 var array = Array.prototype.slice.call( index.array );
11955
11956 data.data.index = {
11957 type: index.array.constructor.name,
11958 array: array
11959 };
11960
11961 }
11962
11963 var attributes = this.attributes;
11964
11965 for ( var key in attributes ) {
11966
11967 var attribute = attributes[ key ];
11968
11969 var array = Array.prototype.slice.call( attribute.array );
11970
11971 data.data.attributes[ key ] = {
11972 itemSize: attribute.itemSize,
11973 type: attribute.array.constructor.name,
11974 array: array,
11975 normalized: attribute.normalized
11976 };
11977
11978 }
11979
11980 var groups = this.groups;
11981
11982 if ( groups.length > 0 ) {
11983
11984 data.data.groups = JSON.parse( JSON.stringify( groups ) );
11985
11986 }
11987
11988 var boundingSphere = this.boundingSphere;
11989
11990 if ( boundingSphere !== null ) {
11991
11992 data.data.boundingSphere = {
11993 center: boundingSphere.center.toArray(),
11994 radius: boundingSphere.radius
11995 };
11996
11997 }
11998
11999 return data;
12000
12001 },
12002
12003 clone: function () {
12004
12005 /*
12006 // Handle primitives
12007
12008 var parameters = this.parameters;
12009
12010 if ( parameters !== undefined ) {
12011
12012 var values = [];
12013
12014 for ( var key in parameters ) {
12015
12016 values.push( parameters[ key ] );
12017
12018 }
12019
12020 var geometry = Object.create( this.constructor.prototype );
12021 this.constructor.apply( geometry, values );
12022 return geometry;
12023
12024 }
12025
12026 return new this.constructor().copy( this );
12027 */
12028
12029 return new BufferGeometry().copy( this );
12030
12031 },
12032
12033 copy: function ( source ) {
12034
12035 var name, i, l;
12036
12037 // reset
12038
12039 this.index = null;
12040 this.attributes = {};
12041 this.morphAttributes = {};
12042 this.groups = [];
12043 this.boundingBox = null;
12044 this.boundingSphere = null;
12045
12046 // name
12047
12048 this.name = source.name;
12049
12050 // index
12051
12052 var index = source.index;
12053
12054 if ( index !== null ) {
12055
12056 this.setIndex( index.clone() );
12057
12058 }
12059
12060 // attributes
12061
12062 var attributes = source.attributes;
12063
12064 for ( name in attributes ) {
12065
12066 var attribute = attributes[ name ];
12067 this.addAttribute( name, attribute.clone() );
12068
12069 }
12070
12071 // morph attributes
12072
12073 var morphAttributes = source.morphAttributes;
12074
12075 for ( name in morphAttributes ) {
12076
12077 var array = [];
12078 var morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes
12079
12080 for ( i = 0, l = morphAttribute.length; i < l; i ++ ) {
12081
12082 array.push( morphAttribute[ i ].clone() );
12083
12084 }
12085
12086 this.morphAttributes[ name ] = array;
12087
12088 }
12089
12090 // groups
12091
12092 var groups = source.groups;
12093
12094 for ( i = 0, l = groups.length; i < l; i ++ ) {
12095
12096 var group = groups[ i ];
12097 this.addGroup( group.start, group.count, group.materialIndex );
12098
12099 }
12100
12101 // bounding box
12102
12103 var boundingBox = source.boundingBox;
12104
12105 if ( boundingBox !== null ) {
12106
12107 this.boundingBox = boundingBox.clone();
12108
12109 }
12110
12111 // bounding sphere
12112
12113 var boundingSphere = source.boundingSphere;
12114
12115 if ( boundingSphere !== null ) {
12116
12117 this.boundingSphere = boundingSphere.clone();
12118
12119 }
12120
12121 // draw range
12122
12123 this.drawRange.start = source.drawRange.start;
12124 this.drawRange.count = source.drawRange.count;
12125
12126 return this;
12127
12128 },
12129
12130 dispose: function () {
12131
12132 this.dispatchEvent( { type: 'dispose' } );
12133
12134 }
12135
12136} );
12137
12138/**
12139 * @author mrdoob / http://mrdoob.com/
12140 * @author Mugen87 / https://github.com/Mugen87
12141 */
12142
12143// BoxGeometry
12144
12145function BoxGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) {
12146
12147 Geometry.call( this );
12148
12149 this.type = 'BoxGeometry';
12150
12151 this.parameters = {
12152 width: width,
12153 height: height,
12154 depth: depth,
12155 widthSegments: widthSegments,
12156 heightSegments: heightSegments,
12157 depthSegments: depthSegments
12158 };
12159
12160 this.fromBufferGeometry( new BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) );
12161 this.mergeVertices();
12162
12163}
12164
12165BoxGeometry.prototype = Object.create( Geometry.prototype );
12166BoxGeometry.prototype.constructor = BoxGeometry;
12167
12168// BoxBufferGeometry
12169
12170function BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) {
12171
12172 BufferGeometry.call( this );
12173
12174 this.type = 'BoxBufferGeometry';
12175
12176 this.parameters = {
12177 width: width,
12178 height: height,
12179 depth: depth,
12180 widthSegments: widthSegments,
12181 heightSegments: heightSegments,
12182 depthSegments: depthSegments
12183 };
12184
12185 var scope = this;
12186
12187 width = width || 1;
12188 height = height || 1;
12189 depth = depth || 1;
12190
12191 // segments
12192
12193 widthSegments = Math.floor( widthSegments ) || 1;
12194 heightSegments = Math.floor( heightSegments ) || 1;
12195 depthSegments = Math.floor( depthSegments ) || 1;
12196
12197 // buffers
12198
12199 var indices = [];
12200 var vertices = [];
12201 var normals = [];
12202 var uvs = [];
12203
12204 // helper variables
12205
12206 var numberOfVertices = 0;
12207 var groupStart = 0;
12208
12209 // build each side of the box geometry
12210
12211 buildPlane( 'z', 'y', 'x', - 1, - 1, depth, height, width, depthSegments, heightSegments, 0 ); // px
12212 buildPlane( 'z', 'y', 'x', 1, - 1, depth, height, - width, depthSegments, heightSegments, 1 ); // nx
12213 buildPlane( 'x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2 ); // py
12214 buildPlane( 'x', 'z', 'y', 1, - 1, width, depth, - height, widthSegments, depthSegments, 3 ); // ny
12215 buildPlane( 'x', 'y', 'z', 1, - 1, width, height, depth, widthSegments, heightSegments, 4 ); // pz
12216 buildPlane( 'x', 'y', 'z', - 1, - 1, width, height, - depth, widthSegments, heightSegments, 5 ); // nz
12217
12218 // build geometry
12219
12220 this.setIndex( indices );
12221 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
12222 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
12223 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
12224
12225 function buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) {
12226
12227 var segmentWidth = width / gridX;
12228 var segmentHeight = height / gridY;
12229
12230 var widthHalf = width / 2;
12231 var heightHalf = height / 2;
12232 var depthHalf = depth / 2;
12233
12234 var gridX1 = gridX + 1;
12235 var gridY1 = gridY + 1;
12236
12237 var vertexCounter = 0;
12238 var groupCount = 0;
12239
12240 var ix, iy;
12241
12242 var vector = new Vector3();
12243
12244 // generate vertices, normals and uvs
12245
12246 for ( iy = 0; iy < gridY1; iy ++ ) {
12247
12248 var y = iy * segmentHeight - heightHalf;
12249
12250 for ( ix = 0; ix < gridX1; ix ++ ) {
12251
12252 var x = ix * segmentWidth - widthHalf;
12253
12254 // set values to correct vector component
12255
12256 vector[ u ] = x * udir;
12257 vector[ v ] = y * vdir;
12258 vector[ w ] = depthHalf;
12259
12260 // now apply vector to vertex buffer
12261
12262 vertices.push( vector.x, vector.y, vector.z );
12263
12264 // set values to correct vector component
12265
12266 vector[ u ] = 0;
12267 vector[ v ] = 0;
12268 vector[ w ] = depth > 0 ? 1 : - 1;
12269
12270 // now apply vector to normal buffer
12271
12272 normals.push( vector.x, vector.y, vector.z );
12273
12274 // uvs
12275
12276 uvs.push( ix / gridX );
12277 uvs.push( 1 - ( iy / gridY ) );
12278
12279 // counters
12280
12281 vertexCounter += 1;
12282
12283 }
12284
12285 }
12286
12287 // indices
12288
12289 // 1. you need three indices to draw a single face
12290 // 2. a single segment consists of two faces
12291 // 3. so we need to generate six (2*3) indices per segment
12292
12293 for ( iy = 0; iy < gridY; iy ++ ) {
12294
12295 for ( ix = 0; ix < gridX; ix ++ ) {
12296
12297 var a = numberOfVertices + ix + gridX1 * iy;
12298 var b = numberOfVertices + ix + gridX1 * ( iy + 1 );
12299 var c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 );
12300 var d = numberOfVertices + ( ix + 1 ) + gridX1 * iy;
12301
12302 // faces
12303
12304 indices.push( a, b, d );
12305 indices.push( b, c, d );
12306
12307 // increase counter
12308
12309 groupCount += 6;
12310
12311 }
12312
12313 }
12314
12315 // add a group to the geometry. this will ensure multi material support
12316
12317 scope.addGroup( groupStart, groupCount, materialIndex );
12318
12319 // calculate new start value for groups
12320
12321 groupStart += groupCount;
12322
12323 // update total number of vertices
12324
12325 numberOfVertices += vertexCounter;
12326
12327 }
12328
12329}
12330
12331BoxBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
12332BoxBufferGeometry.prototype.constructor = BoxBufferGeometry;
12333
12334/**
12335 * @author mrdoob / http://mrdoob.com/
12336 * @author Mugen87 / https://github.com/Mugen87
12337 */
12338
12339// PlaneGeometry
12340
12341function PlaneGeometry( width, height, widthSegments, heightSegments ) {
12342
12343 Geometry.call( this );
12344
12345 this.type = 'PlaneGeometry';
12346
12347 this.parameters = {
12348 width: width,
12349 height: height,
12350 widthSegments: widthSegments,
12351 heightSegments: heightSegments
12352 };
12353
12354 this.fromBufferGeometry( new PlaneBufferGeometry( width, height, widthSegments, heightSegments ) );
12355 this.mergeVertices();
12356
12357}
12358
12359PlaneGeometry.prototype = Object.create( Geometry.prototype );
12360PlaneGeometry.prototype.constructor = PlaneGeometry;
12361
12362// PlaneBufferGeometry
12363
12364function PlaneBufferGeometry( width, height, widthSegments, heightSegments ) {
12365
12366 BufferGeometry.call( this );
12367
12368 this.type = 'PlaneBufferGeometry';
12369
12370 this.parameters = {
12371 width: width,
12372 height: height,
12373 widthSegments: widthSegments,
12374 heightSegments: heightSegments
12375 };
12376
12377 width = width || 1;
12378 height = height || 1;
12379
12380 var width_half = width / 2;
12381 var height_half = height / 2;
12382
12383 var gridX = Math.floor( widthSegments ) || 1;
12384 var gridY = Math.floor( heightSegments ) || 1;
12385
12386 var gridX1 = gridX + 1;
12387 var gridY1 = gridY + 1;
12388
12389 var segment_width = width / gridX;
12390 var segment_height = height / gridY;
12391
12392 var ix, iy;
12393
12394 // buffers
12395
12396 var indices = [];
12397 var vertices = [];
12398 var normals = [];
12399 var uvs = [];
12400
12401 // generate vertices, normals and uvs
12402
12403 for ( iy = 0; iy < gridY1; iy ++ ) {
12404
12405 var y = iy * segment_height - height_half;
12406
12407 for ( ix = 0; ix < gridX1; ix ++ ) {
12408
12409 var x = ix * segment_width - width_half;
12410
12411 vertices.push( x, - y, 0 );
12412
12413 normals.push( 0, 0, 1 );
12414
12415 uvs.push( ix / gridX );
12416 uvs.push( 1 - ( iy / gridY ) );
12417
12418 }
12419
12420 }
12421
12422 // indices
12423
12424 for ( iy = 0; iy < gridY; iy ++ ) {
12425
12426 for ( ix = 0; ix < gridX; ix ++ ) {
12427
12428 var a = ix + gridX1 * iy;
12429 var b = ix + gridX1 * ( iy + 1 );
12430 var c = ( ix + 1 ) + gridX1 * ( iy + 1 );
12431 var d = ( ix + 1 ) + gridX1 * iy;
12432
12433 // faces
12434
12435 indices.push( a, b, d );
12436 indices.push( b, c, d );
12437
12438 }
12439
12440 }
12441
12442 // build geometry
12443
12444 this.setIndex( indices );
12445 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
12446 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
12447 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
12448
12449}
12450
12451PlaneBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
12452PlaneBufferGeometry.prototype.constructor = PlaneBufferGeometry;
12453
12454/**
12455 * @author mrdoob / http://mrdoob.com/
12456 * @author alteredq / http://alteredqualia.com/
12457 */
12458
12459var materialId = 0;
12460
12461function Material() {
12462
12463 Object.defineProperty( this, 'id', { value: materialId ++ } );
12464
12465 this.uuid = _Math.generateUUID();
12466
12467 this.name = '';
12468 this.type = 'Material';
12469
12470 this.fog = true;
12471 this.lights = true;
12472
12473 this.blending = NormalBlending;
12474 this.side = FrontSide;
12475 this.flatShading = false;
12476 this.vertexColors = NoColors; // THREE.NoColors, THREE.VertexColors, THREE.FaceColors
12477
12478 this.opacity = 1;
12479 this.transparent = false;
12480
12481 this.blendSrc = SrcAlphaFactor;
12482 this.blendDst = OneMinusSrcAlphaFactor;
12483 this.blendEquation = AddEquation;
12484 this.blendSrcAlpha = null;
12485 this.blendDstAlpha = null;
12486 this.blendEquationAlpha = null;
12487
12488 this.depthFunc = LessEqualDepth;
12489 this.depthTest = true;
12490 this.depthWrite = true;
12491
12492 this.clippingPlanes = null;
12493 this.clipIntersection = false;
12494 this.clipShadows = false;
12495
12496 this.shadowSide = null;
12497
12498 this.colorWrite = true;
12499
12500 this.precision = null; // override the renderer's default precision for this material
12501
12502 this.polygonOffset = false;
12503 this.polygonOffsetFactor = 0;
12504 this.polygonOffsetUnits = 0;
12505
12506 this.dithering = false;
12507
12508 this.alphaTest = 0;
12509 this.premultipliedAlpha = false;
12510
12511 this.overdraw = 0; // Overdrawn pixels (typically between 0 and 1) for fixing antialiasing gaps in CanvasRenderer
12512
12513 this.visible = true;
12514
12515 this.userData = {};
12516
12517 this.needsUpdate = true;
12518
12519}
12520
12521Material.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
12522
12523 constructor: Material,
12524
12525 isMaterial: true,
12526
12527 onBeforeCompile: function () {},
12528
12529 setValues: function ( values ) {
12530
12531 if ( values === undefined ) return;
12532
12533 for ( var key in values ) {
12534
12535 var newValue = values[ key ];
12536
12537 if ( newValue === undefined ) {
12538
12539 console.warn( "THREE.Material: '" + key + "' parameter is undefined." );
12540 continue;
12541
12542 }
12543
12544 // for backward compatability if shading is set in the constructor
12545 if ( key === 'shading' ) {
12546
12547 console.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );
12548 this.flatShading = ( newValue === FlatShading ) ? true : false;
12549 continue;
12550
12551 }
12552
12553 var currentValue = this[ key ];
12554
12555 if ( currentValue === undefined ) {
12556
12557 console.warn( "THREE." + this.type + ": '" + key + "' is not a property of this material." );
12558 continue;
12559
12560 }
12561
12562 if ( currentValue && currentValue.isColor ) {
12563
12564 currentValue.set( newValue );
12565
12566 } else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) {
12567
12568 currentValue.copy( newValue );
12569
12570 } else if ( key === 'overdraw' ) {
12571
12572 // ensure overdraw is backwards-compatible with legacy boolean type
12573 this[ key ] = Number( newValue );
12574
12575 } else {
12576
12577 this[ key ] = newValue;
12578
12579 }
12580
12581 }
12582
12583 },
12584
12585 toJSON: function ( meta ) {
12586
12587 var isRoot = ( meta === undefined || typeof meta === 'string' );
12588
12589 if ( isRoot ) {
12590
12591 meta = {
12592 textures: {},
12593 images: {}
12594 };
12595
12596 }
12597
12598 var data = {
12599 metadata: {
12600 version: 4.5,
12601 type: 'Material',
12602 generator: 'Material.toJSON'
12603 }
12604 };
12605
12606 // standard Material serialization
12607 data.uuid = this.uuid;
12608 data.type = this.type;
12609
12610 if ( this.name !== '' ) data.name = this.name;
12611
12612 if ( this.color && this.color.isColor ) data.color = this.color.getHex();
12613
12614 if ( this.roughness !== undefined ) data.roughness = this.roughness;
12615 if ( this.metalness !== undefined ) data.metalness = this.metalness;
12616
12617 if ( this.emissive && this.emissive.isColor ) data.emissive = this.emissive.getHex();
12618 if ( this.emissiveIntensity !== 1 ) data.emissiveIntensity = this.emissiveIntensity;
12619
12620 if ( this.specular && this.specular.isColor ) data.specular = this.specular.getHex();
12621 if ( this.shininess !== undefined ) data.shininess = this.shininess;
12622 if ( this.clearCoat !== undefined ) data.clearCoat = this.clearCoat;
12623 if ( this.clearCoatRoughness !== undefined ) data.clearCoatRoughness = this.clearCoatRoughness;
12624
12625 if ( this.map && this.map.isTexture ) data.map = this.map.toJSON( meta ).uuid;
12626 if ( this.alphaMap && this.alphaMap.isTexture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid;
12627 if ( this.lightMap && this.lightMap.isTexture ) data.lightMap = this.lightMap.toJSON( meta ).uuid;
12628 if ( this.bumpMap && this.bumpMap.isTexture ) {
12629
12630 data.bumpMap = this.bumpMap.toJSON( meta ).uuid;
12631 data.bumpScale = this.bumpScale;
12632
12633 }
12634 if ( this.normalMap && this.normalMap.isTexture ) {
12635
12636 data.normalMap = this.normalMap.toJSON( meta ).uuid;
12637 data.normalScale = this.normalScale.toArray();
12638
12639 }
12640 if ( this.displacementMap && this.displacementMap.isTexture ) {
12641
12642 data.displacementMap = this.displacementMap.toJSON( meta ).uuid;
12643 data.displacementScale = this.displacementScale;
12644 data.displacementBias = this.displacementBias;
12645
12646 }
12647 if ( this.roughnessMap && this.roughnessMap.isTexture ) data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid;
12648 if ( this.metalnessMap && this.metalnessMap.isTexture ) data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid;
12649
12650 if ( this.emissiveMap && this.emissiveMap.isTexture ) data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid;
12651 if ( this.specularMap && this.specularMap.isTexture ) data.specularMap = this.specularMap.toJSON( meta ).uuid;
12652
12653 if ( this.envMap && this.envMap.isTexture ) {
12654
12655 data.envMap = this.envMap.toJSON( meta ).uuid;
12656 data.reflectivity = this.reflectivity; // Scale behind envMap
12657
12658 }
12659
12660 if ( this.gradientMap && this.gradientMap.isTexture ) {
12661
12662 data.gradientMap = this.gradientMap.toJSON( meta ).uuid;
12663
12664 }
12665
12666 if ( this.size !== undefined ) data.size = this.size;
12667 if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation;
12668
12669 if ( this.blending !== NormalBlending ) data.blending = this.blending;
12670 if ( this.flatShading === true ) data.flatShading = this.flatShading;
12671 if ( this.side !== FrontSide ) data.side = this.side;
12672 if ( this.vertexColors !== NoColors ) data.vertexColors = this.vertexColors;
12673
12674 if ( this.opacity < 1 ) data.opacity = this.opacity;
12675 if ( this.transparent === true ) data.transparent = this.transparent;
12676
12677 data.depthFunc = this.depthFunc;
12678 data.depthTest = this.depthTest;
12679 data.depthWrite = this.depthWrite;
12680
12681 // rotation (SpriteMaterial)
12682 if ( this.rotation !== 0 ) data.rotation = this.rotation;
12683
12684 if ( this.linewidth !== 1 ) data.linewidth = this.linewidth;
12685 if ( this.dashSize !== undefined ) data.dashSize = this.dashSize;
12686 if ( this.gapSize !== undefined ) data.gapSize = this.gapSize;
12687 if ( this.scale !== undefined ) data.scale = this.scale;
12688
12689 if ( this.dithering === true ) data.dithering = true;
12690
12691 if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest;
12692 if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = this.premultipliedAlpha;
12693
12694 if ( this.wireframe === true ) data.wireframe = this.wireframe;
12695 if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth;
12696 if ( this.wireframeLinecap !== 'round' ) data.wireframeLinecap = this.wireframeLinecap;
12697 if ( this.wireframeLinejoin !== 'round' ) data.wireframeLinejoin = this.wireframeLinejoin;
12698
12699 if ( this.morphTargets === true ) data.morphTargets = true;
12700 if ( this.skinning === true ) data.skinning = true;
12701
12702 if ( this.visible === false ) data.visible = false;
12703 if ( JSON.stringify( this.userData ) !== '{}' ) data.userData = this.userData;
12704
12705 // TODO: Copied from Object3D.toJSON
12706
12707 function extractFromCache( cache ) {
12708
12709 var values = [];
12710
12711 for ( var key in cache ) {
12712
12713 var data = cache[ key ];
12714 delete data.metadata;
12715 values.push( data );
12716
12717 }
12718
12719 return values;
12720
12721 }
12722
12723 if ( isRoot ) {
12724
12725 var textures = extractFromCache( meta.textures );
12726 var images = extractFromCache( meta.images );
12727
12728 if ( textures.length > 0 ) data.textures = textures;
12729 if ( images.length > 0 ) data.images = images;
12730
12731 }
12732
12733 return data;
12734
12735 },
12736
12737 clone: function () {
12738
12739 return new this.constructor().copy( this );
12740
12741 },
12742
12743 copy: function ( source ) {
12744
12745 this.name = source.name;
12746
12747 this.fog = source.fog;
12748 this.lights = source.lights;
12749
12750 this.blending = source.blending;
12751 this.side = source.side;
12752 this.flatShading = source.flatShading;
12753 this.vertexColors = source.vertexColors;
12754
12755 this.opacity = source.opacity;
12756 this.transparent = source.transparent;
12757
12758 this.blendSrc = source.blendSrc;
12759 this.blendDst = source.blendDst;
12760 this.blendEquation = source.blendEquation;
12761 this.blendSrcAlpha = source.blendSrcAlpha;
12762 this.blendDstAlpha = source.blendDstAlpha;
12763 this.blendEquationAlpha = source.blendEquationAlpha;
12764
12765 this.depthFunc = source.depthFunc;
12766 this.depthTest = source.depthTest;
12767 this.depthWrite = source.depthWrite;
12768
12769 this.colorWrite = source.colorWrite;
12770
12771 this.precision = source.precision;
12772
12773 this.polygonOffset = source.polygonOffset;
12774 this.polygonOffsetFactor = source.polygonOffsetFactor;
12775 this.polygonOffsetUnits = source.polygonOffsetUnits;
12776
12777 this.dithering = source.dithering;
12778
12779 this.alphaTest = source.alphaTest;
12780 this.premultipliedAlpha = source.premultipliedAlpha;
12781
12782 this.overdraw = source.overdraw;
12783
12784 this.visible = source.visible;
12785 this.userData = JSON.parse( JSON.stringify( source.userData ) );
12786
12787 this.clipShadows = source.clipShadows;
12788 this.clipIntersection = source.clipIntersection;
12789
12790 var srcPlanes = source.clippingPlanes,
12791 dstPlanes = null;
12792
12793 if ( srcPlanes !== null ) {
12794
12795 var n = srcPlanes.length;
12796 dstPlanes = new Array( n );
12797
12798 for ( var i = 0; i !== n; ++ i )
12799 dstPlanes[ i ] = srcPlanes[ i ].clone();
12800
12801 }
12802
12803 this.clippingPlanes = dstPlanes;
12804
12805 this.shadowSide = source.shadowSide;
12806
12807 return this;
12808
12809 },
12810
12811 dispose: function () {
12812
12813 this.dispatchEvent( { type: 'dispose' } );
12814
12815 }
12816
12817} );
12818
12819/**
12820 * @author mrdoob / http://mrdoob.com/
12821 * @author alteredq / http://alteredqualia.com/
12822 *
12823 * parameters = {
12824 * color: <hex>,
12825 * opacity: <float>,
12826 * map: new THREE.Texture( <Image> ),
12827 *
12828 * lightMap: new THREE.Texture( <Image> ),
12829 * lightMapIntensity: <float>
12830 *
12831 * aoMap: new THREE.Texture( <Image> ),
12832 * aoMapIntensity: <float>
12833 *
12834 * specularMap: new THREE.Texture( <Image> ),
12835 *
12836 * alphaMap: new THREE.Texture( <Image> ),
12837 *
12838 * envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
12839 * combine: THREE.Multiply,
12840 * reflectivity: <float>,
12841 * refractionRatio: <float>,
12842 *
12843 * depthTest: <bool>,
12844 * depthWrite: <bool>,
12845 *
12846 * wireframe: <boolean>,
12847 * wireframeLinewidth: <float>,
12848 *
12849 * skinning: <bool>,
12850 * morphTargets: <bool>
12851 * }
12852 */
12853
12854function MeshBasicMaterial( parameters ) {
12855
12856 Material.call( this );
12857
12858 this.type = 'MeshBasicMaterial';
12859
12860 this.color = new Color( 0xffffff ); // emissive
12861
12862 this.map = null;
12863
12864 this.lightMap = null;
12865 this.lightMapIntensity = 1.0;
12866
12867 this.aoMap = null;
12868 this.aoMapIntensity = 1.0;
12869
12870 this.specularMap = null;
12871
12872 this.alphaMap = null;
12873
12874 this.envMap = null;
12875 this.combine = MultiplyOperation;
12876 this.reflectivity = 1;
12877 this.refractionRatio = 0.98;
12878
12879 this.wireframe = false;
12880 this.wireframeLinewidth = 1;
12881 this.wireframeLinecap = 'round';
12882 this.wireframeLinejoin = 'round';
12883
12884 this.skinning = false;
12885 this.morphTargets = false;
12886
12887 this.lights = false;
12888
12889 this.setValues( parameters );
12890
12891}
12892
12893MeshBasicMaterial.prototype = Object.create( Material.prototype );
12894MeshBasicMaterial.prototype.constructor = MeshBasicMaterial;
12895
12896MeshBasicMaterial.prototype.isMeshBasicMaterial = true;
12897
12898MeshBasicMaterial.prototype.copy = function ( source ) {
12899
12900 Material.prototype.copy.call( this, source );
12901
12902 this.color.copy( source.color );
12903
12904 this.map = source.map;
12905
12906 this.lightMap = source.lightMap;
12907 this.lightMapIntensity = source.lightMapIntensity;
12908
12909 this.aoMap = source.aoMap;
12910 this.aoMapIntensity = source.aoMapIntensity;
12911
12912 this.specularMap = source.specularMap;
12913
12914 this.alphaMap = source.alphaMap;
12915
12916 this.envMap = source.envMap;
12917 this.combine = source.combine;
12918 this.reflectivity = source.reflectivity;
12919 this.refractionRatio = source.refractionRatio;
12920
12921 this.wireframe = source.wireframe;
12922 this.wireframeLinewidth = source.wireframeLinewidth;
12923 this.wireframeLinecap = source.wireframeLinecap;
12924 this.wireframeLinejoin = source.wireframeLinejoin;
12925
12926 this.skinning = source.skinning;
12927 this.morphTargets = source.morphTargets;
12928
12929 return this;
12930
12931};
12932
12933/**
12934 * @author alteredq / http://alteredqualia.com/
12935 *
12936 * parameters = {
12937 * defines: { "label" : "value" },
12938 * uniforms: { "parameter1": { value: 1.0 }, "parameter2": { value2: 2 } },
12939 *
12940 * fragmentShader: <string>,
12941 * vertexShader: <string>,
12942 *
12943 * wireframe: <boolean>,
12944 * wireframeLinewidth: <float>,
12945 *
12946 * lights: <bool>,
12947 *
12948 * skinning: <bool>,
12949 * morphTargets: <bool>,
12950 * morphNormals: <bool>
12951 * }
12952 */
12953
12954function ShaderMaterial( parameters ) {
12955
12956 Material.call( this );
12957
12958 this.type = 'ShaderMaterial';
12959
12960 this.defines = {};
12961 this.uniforms = {};
12962
12963 this.vertexShader = 'void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}';
12964 this.fragmentShader = 'void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}';
12965
12966 this.linewidth = 1;
12967
12968 this.wireframe = false;
12969 this.wireframeLinewidth = 1;
12970
12971 this.fog = false; // set to use scene fog
12972 this.lights = false; // set to use scene lights
12973 this.clipping = false; // set to use user-defined clipping planes
12974
12975 this.skinning = false; // set to use skinning attribute streams
12976 this.morphTargets = false; // set to use morph targets
12977 this.morphNormals = false; // set to use morph normals
12978
12979 this.extensions = {
12980 derivatives: false, // set to use derivatives
12981 fragDepth: false, // set to use fragment depth values
12982 drawBuffers: false, // set to use draw buffers
12983 shaderTextureLOD: false // set to use shader texture LOD
12984 };
12985
12986 // When rendered geometry doesn't include these attributes but the material does,
12987 // use these default values in WebGL. This avoids errors when buffer data is missing.
12988 this.defaultAttributeValues = {
12989 'color': [ 1, 1, 1 ],
12990 'uv': [ 0, 0 ],
12991 'uv2': [ 0, 0 ]
12992 };
12993
12994 this.index0AttributeName = undefined;
12995 this.uniformsNeedUpdate = false;
12996
12997 if ( parameters !== undefined ) {
12998
12999 if ( parameters.attributes !== undefined ) {
13000
13001 console.error( 'THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead.' );
13002
13003 }
13004
13005 this.setValues( parameters );
13006
13007 }
13008
13009}
13010
13011ShaderMaterial.prototype = Object.create( Material.prototype );
13012ShaderMaterial.prototype.constructor = ShaderMaterial;
13013
13014ShaderMaterial.prototype.isShaderMaterial = true;
13015
13016ShaderMaterial.prototype.copy = function ( source ) {
13017
13018 Material.prototype.copy.call( this, source );
13019
13020 this.fragmentShader = source.fragmentShader;
13021 this.vertexShader = source.vertexShader;
13022
13023 this.uniforms = UniformsUtils.clone( source.uniforms );
13024
13025 this.defines = Object.assign( {}, source.defines );
13026
13027 this.wireframe = source.wireframe;
13028 this.wireframeLinewidth = source.wireframeLinewidth;
13029
13030 this.lights = source.lights;
13031 this.clipping = source.clipping;
13032
13033 this.skinning = source.skinning;
13034
13035 this.morphTargets = source.morphTargets;
13036 this.morphNormals = source.morphNormals;
13037
13038 this.extensions = source.extensions;
13039
13040 return this;
13041
13042};
13043
13044ShaderMaterial.prototype.toJSON = function ( meta ) {
13045
13046 var data = Material.prototype.toJSON.call( this, meta );
13047
13048 data.uniforms = this.uniforms;
13049 data.vertexShader = this.vertexShader;
13050 data.fragmentShader = this.fragmentShader;
13051
13052 return data;
13053
13054};
13055
13056/**
13057 * @author bhouston / http://clara.io
13058 */
13059
13060function Ray( origin, direction ) {
13061
13062 this.origin = ( origin !== undefined ) ? origin : new Vector3();
13063 this.direction = ( direction !== undefined ) ? direction : new Vector3();
13064
13065}
13066
13067Object.assign( Ray.prototype, {
13068
13069 set: function ( origin, direction ) {
13070
13071 this.origin.copy( origin );
13072 this.direction.copy( direction );
13073
13074 return this;
13075
13076 },
13077
13078 clone: function () {
13079
13080 return new this.constructor().copy( this );
13081
13082 },
13083
13084 copy: function ( ray ) {
13085
13086 this.origin.copy( ray.origin );
13087 this.direction.copy( ray.direction );
13088
13089 return this;
13090
13091 },
13092
13093 at: function ( t, target ) {
13094
13095 if ( target === undefined ) {
13096
13097 console.warn( 'THREE.Ray: .at() target is now required' );
13098 target = new Vector3();
13099
13100 }
13101
13102 return target.copy( this.direction ).multiplyScalar( t ).add( this.origin );
13103
13104 },
13105
13106 lookAt: function ( v ) {
13107
13108 this.direction.copy( v ).sub( this.origin ).normalize();
13109
13110 return this;
13111
13112 },
13113
13114 recast: function () {
13115
13116 var v1 = new Vector3();
13117
13118 return function recast( t ) {
13119
13120 this.origin.copy( this.at( t, v1 ) );
13121
13122 return this;
13123
13124 };
13125
13126 }(),
13127
13128 closestPointToPoint: function ( point, target ) {
13129
13130 if ( target === undefined ) {
13131
13132 console.warn( 'THREE.Ray: .closestPointToPoint() target is now required' );
13133 target = new Vector3();
13134
13135 }
13136
13137 target.subVectors( point, this.origin );
13138
13139 var directionDistance = target.dot( this.direction );
13140
13141 if ( directionDistance < 0 ) {
13142
13143 return target.copy( this.origin );
13144
13145 }
13146
13147 return target.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );
13148
13149 },
13150
13151 distanceToPoint: function ( point ) {
13152
13153 return Math.sqrt( this.distanceSqToPoint( point ) );
13154
13155 },
13156
13157 distanceSqToPoint: function () {
13158
13159 var v1 = new Vector3();
13160
13161 return function distanceSqToPoint( point ) {
13162
13163 var directionDistance = v1.subVectors( point, this.origin ).dot( this.direction );
13164
13165 // point behind the ray
13166
13167 if ( directionDistance < 0 ) {
13168
13169 return this.origin.distanceToSquared( point );
13170
13171 }
13172
13173 v1.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );
13174
13175 return v1.distanceToSquared( point );
13176
13177 };
13178
13179 }(),
13180
13181 distanceSqToSegment: function () {
13182
13183 var segCenter = new Vector3();
13184 var segDir = new Vector3();
13185 var diff = new Vector3();
13186
13187 return function distanceSqToSegment( v0, v1, optionalPointOnRay, optionalPointOnSegment ) {
13188
13189 // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteDistRaySegment.h
13190 // It returns the min distance between the ray and the segment
13191 // defined by v0 and v1
13192 // It can also set two optional targets :
13193 // - The closest point on the ray
13194 // - The closest point on the segment
13195
13196 segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 );
13197 segDir.copy( v1 ).sub( v0 ).normalize();
13198 diff.copy( this.origin ).sub( segCenter );
13199
13200 var segExtent = v0.distanceTo( v1 ) * 0.5;
13201 var a01 = - this.direction.dot( segDir );
13202 var b0 = diff.dot( this.direction );
13203 var b1 = - diff.dot( segDir );
13204 var c = diff.lengthSq();
13205 var det = Math.abs( 1 - a01 * a01 );
13206 var s0, s1, sqrDist, extDet;
13207
13208 if ( det > 0 ) {
13209
13210 // The ray and segment are not parallel.
13211
13212 s0 = a01 * b1 - b0;
13213 s1 = a01 * b0 - b1;
13214 extDet = segExtent * det;
13215
13216 if ( s0 >= 0 ) {
13217
13218 if ( s1 >= - extDet ) {
13219
13220 if ( s1 <= extDet ) {
13221
13222 // region 0
13223 // Minimum at interior points of ray and segment.
13224
13225 var invDet = 1 / det;
13226 s0 *= invDet;
13227 s1 *= invDet;
13228 sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c;
13229
13230 } else {
13231
13232 // region 1
13233
13234 s1 = segExtent;
13235 s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
13236 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
13237
13238 }
13239
13240 } else {
13241
13242 // region 5
13243
13244 s1 = - segExtent;
13245 s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
13246 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
13247
13248 }
13249
13250 } else {
13251
13252 if ( s1 <= - extDet ) {
13253
13254 // region 4
13255
13256 s0 = Math.max( 0, - ( - a01 * segExtent + b0 ) );
13257 s1 = ( s0 > 0 ) ? - segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
13258 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
13259
13260 } else if ( s1 <= extDet ) {
13261
13262 // region 3
13263
13264 s0 = 0;
13265 s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent );
13266 sqrDist = s1 * ( s1 + 2 * b1 ) + c;
13267
13268 } else {
13269
13270 // region 2
13271
13272 s0 = Math.max( 0, - ( a01 * segExtent + b0 ) );
13273 s1 = ( s0 > 0 ) ? segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
13274 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
13275
13276 }
13277
13278 }
13279
13280 } else {
13281
13282 // Ray and segment are parallel.
13283
13284 s1 = ( a01 > 0 ) ? - segExtent : segExtent;
13285 s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
13286 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
13287
13288 }
13289
13290 if ( optionalPointOnRay ) {
13291
13292 optionalPointOnRay.copy( this.direction ).multiplyScalar( s0 ).add( this.origin );
13293
13294 }
13295
13296 if ( optionalPointOnSegment ) {
13297
13298 optionalPointOnSegment.copy( segDir ).multiplyScalar( s1 ).add( segCenter );
13299
13300 }
13301
13302 return sqrDist;
13303
13304 };
13305
13306 }(),
13307
13308 intersectSphere: function () {
13309
13310 var v1 = new Vector3();
13311
13312 return function intersectSphere( sphere, target ) {
13313
13314 v1.subVectors( sphere.center, this.origin );
13315 var tca = v1.dot( this.direction );
13316 var d2 = v1.dot( v1 ) - tca * tca;
13317 var radius2 = sphere.radius * sphere.radius;
13318
13319 if ( d2 > radius2 ) return null;
13320
13321 var thc = Math.sqrt( radius2 - d2 );
13322
13323 // t0 = first intersect point - entrance on front of sphere
13324 var t0 = tca - thc;
13325
13326 // t1 = second intersect point - exit point on back of sphere
13327 var t1 = tca + thc;
13328
13329 // test to see if both t0 and t1 are behind the ray - if so, return null
13330 if ( t0 < 0 && t1 < 0 ) return null;
13331
13332 // test to see if t0 is behind the ray:
13333 // if it is, the ray is inside the sphere, so return the second exit point scaled by t1,
13334 // in order to always return an intersect point that is in front of the ray.
13335 if ( t0 < 0 ) return this.at( t1, target );
13336
13337 // else t0 is in front of the ray, so return the first collision point scaled by t0
13338 return this.at( t0, target );
13339
13340 };
13341
13342 }(),
13343
13344 intersectsSphere: function ( sphere ) {
13345
13346 return this.distanceToPoint( sphere.center ) <= sphere.radius;
13347
13348 },
13349
13350 distanceToPlane: function ( plane ) {
13351
13352 var denominator = plane.normal.dot( this.direction );
13353
13354 if ( denominator === 0 ) {
13355
13356 // line is coplanar, return origin
13357 if ( plane.distanceToPoint( this.origin ) === 0 ) {
13358
13359 return 0;
13360
13361 }
13362
13363 // Null is preferable to undefined since undefined means.... it is undefined
13364
13365 return null;
13366
13367 }
13368
13369 var t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator;
13370
13371 // Return if the ray never intersects the plane
13372
13373 return t >= 0 ? t : null;
13374
13375 },
13376
13377 intersectPlane: function ( plane, target ) {
13378
13379 var t = this.distanceToPlane( plane );
13380
13381 if ( t === null ) {
13382
13383 return null;
13384
13385 }
13386
13387 return this.at( t, target );
13388
13389 },
13390
13391 intersectsPlane: function ( plane ) {
13392
13393 // check if the ray lies on the plane first
13394
13395 var distToPoint = plane.distanceToPoint( this.origin );
13396
13397 if ( distToPoint === 0 ) {
13398
13399 return true;
13400
13401 }
13402
13403 var denominator = plane.normal.dot( this.direction );
13404
13405 if ( denominator * distToPoint < 0 ) {
13406
13407 return true;
13408
13409 }
13410
13411 // ray origin is behind the plane (and is pointing behind it)
13412
13413 return false;
13414
13415 },
13416
13417 intersectBox: function ( box, target ) {
13418
13419 var tmin, tmax, tymin, tymax, tzmin, tzmax;
13420
13421 var invdirx = 1 / this.direction.x,
13422 invdiry = 1 / this.direction.y,
13423 invdirz = 1 / this.direction.z;
13424
13425 var origin = this.origin;
13426
13427 if ( invdirx >= 0 ) {
13428
13429 tmin = ( box.min.x - origin.x ) * invdirx;
13430 tmax = ( box.max.x - origin.x ) * invdirx;
13431
13432 } else {
13433
13434 tmin = ( box.max.x - origin.x ) * invdirx;
13435 tmax = ( box.min.x - origin.x ) * invdirx;
13436
13437 }
13438
13439 if ( invdiry >= 0 ) {
13440
13441 tymin = ( box.min.y - origin.y ) * invdiry;
13442 tymax = ( box.max.y - origin.y ) * invdiry;
13443
13444 } else {
13445
13446 tymin = ( box.max.y - origin.y ) * invdiry;
13447 tymax = ( box.min.y - origin.y ) * invdiry;
13448
13449 }
13450
13451 if ( ( tmin > tymax ) || ( tymin > tmax ) ) return null;
13452
13453 // These lines also handle the case where tmin or tmax is NaN
13454 // (result of 0 * Infinity). x !== x returns true if x is NaN
13455
13456 if ( tymin > tmin || tmin !== tmin ) tmin = tymin;
13457
13458 if ( tymax < tmax || tmax !== tmax ) tmax = tymax;
13459
13460 if ( invdirz >= 0 ) {
13461
13462 tzmin = ( box.min.z - origin.z ) * invdirz;
13463 tzmax = ( box.max.z - origin.z ) * invdirz;
13464
13465 } else {
13466
13467 tzmin = ( box.max.z - origin.z ) * invdirz;
13468 tzmax = ( box.min.z - origin.z ) * invdirz;
13469
13470 }
13471
13472 if ( ( tmin > tzmax ) || ( tzmin > tmax ) ) return null;
13473
13474 if ( tzmin > tmin || tmin !== tmin ) tmin = tzmin;
13475
13476 if ( tzmax < tmax || tmax !== tmax ) tmax = tzmax;
13477
13478 //return point closest to the ray (positive side)
13479
13480 if ( tmax < 0 ) return null;
13481
13482 return this.at( tmin >= 0 ? tmin : tmax, target );
13483
13484 },
13485
13486 intersectsBox: ( function () {
13487
13488 var v = new Vector3();
13489
13490 return function intersectsBox( box ) {
13491
13492 return this.intersectBox( box, v ) !== null;
13493
13494 };
13495
13496 } )(),
13497
13498 intersectTriangle: function () {
13499
13500 // Compute the offset origin, edges, and normal.
13501 var diff = new Vector3();
13502 var edge1 = new Vector3();
13503 var edge2 = new Vector3();
13504 var normal = new Vector3();
13505
13506 return function intersectTriangle( a, b, c, backfaceCulling, target ) {
13507
13508 // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h
13509
13510 edge1.subVectors( b, a );
13511 edge2.subVectors( c, a );
13512 normal.crossVectors( edge1, edge2 );
13513
13514 // Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction,
13515 // E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by
13516 // |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2))
13517 // |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q))
13518 // |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N)
13519 var DdN = this.direction.dot( normal );
13520 var sign;
13521
13522 if ( DdN > 0 ) {
13523
13524 if ( backfaceCulling ) return null;
13525 sign = 1;
13526
13527 } else if ( DdN < 0 ) {
13528
13529 sign = - 1;
13530 DdN = - DdN;
13531
13532 } else {
13533
13534 return null;
13535
13536 }
13537
13538 diff.subVectors( this.origin, a );
13539 var DdQxE2 = sign * this.direction.dot( edge2.crossVectors( diff, edge2 ) );
13540
13541 // b1 < 0, no intersection
13542 if ( DdQxE2 < 0 ) {
13543
13544 return null;
13545
13546 }
13547
13548 var DdE1xQ = sign * this.direction.dot( edge1.cross( diff ) );
13549
13550 // b2 < 0, no intersection
13551 if ( DdE1xQ < 0 ) {
13552
13553 return null;
13554
13555 }
13556
13557 // b1+b2 > 1, no intersection
13558 if ( DdQxE2 + DdE1xQ > DdN ) {
13559
13560 return null;
13561
13562 }
13563
13564 // Line intersects triangle, check if ray does.
13565 var QdN = - sign * diff.dot( normal );
13566
13567 // t < 0, no intersection
13568 if ( QdN < 0 ) {
13569
13570 return null;
13571
13572 }
13573
13574 // Ray intersects triangle.
13575 return this.at( QdN / DdN, target );
13576
13577 };
13578
13579 }(),
13580
13581 applyMatrix4: function ( matrix4 ) {
13582
13583 this.origin.applyMatrix4( matrix4 );
13584 this.direction.transformDirection( matrix4 );
13585
13586 return this;
13587
13588 },
13589
13590 equals: function ( ray ) {
13591
13592 return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction );
13593
13594 }
13595
13596} );
13597
13598/**
13599 * @author bhouston / http://clara.io
13600 */
13601
13602function Line3( start, end ) {
13603
13604 this.start = ( start !== undefined ) ? start : new Vector3();
13605 this.end = ( end !== undefined ) ? end : new Vector3();
13606
13607}
13608
13609Object.assign( Line3.prototype, {
13610
13611 set: function ( start, end ) {
13612
13613 this.start.copy( start );
13614 this.end.copy( end );
13615
13616 return this;
13617
13618 },
13619
13620 clone: function () {
13621
13622 return new this.constructor().copy( this );
13623
13624 },
13625
13626 copy: function ( line ) {
13627
13628 this.start.copy( line.start );
13629 this.end.copy( line.end );
13630
13631 return this;
13632
13633 },
13634
13635 getCenter: function ( target ) {
13636
13637 if ( target === undefined ) {
13638
13639 console.warn( 'THREE.Line3: .getCenter() target is now required' );
13640 target = new Vector3();
13641
13642 }
13643
13644 return target.addVectors( this.start, this.end ).multiplyScalar( 0.5 );
13645
13646 },
13647
13648 delta: function ( target ) {
13649
13650 if ( target === undefined ) {
13651
13652 console.warn( 'THREE.Line3: .delta() target is now required' );
13653 target = new Vector3();
13654
13655 }
13656
13657 return target.subVectors( this.end, this.start );
13658
13659 },
13660
13661 distanceSq: function () {
13662
13663 return this.start.distanceToSquared( this.end );
13664
13665 },
13666
13667 distance: function () {
13668
13669 return this.start.distanceTo( this.end );
13670
13671 },
13672
13673 at: function ( t, target ) {
13674
13675 if ( target === undefined ) {
13676
13677 console.warn( 'THREE.Line3: .at() target is now required' );
13678 target = new Vector3();
13679
13680 }
13681
13682 return this.delta( target ).multiplyScalar( t ).add( this.start );
13683
13684 },
13685
13686 closestPointToPointParameter: function () {
13687
13688 var startP = new Vector3();
13689 var startEnd = new Vector3();
13690
13691 return function closestPointToPointParameter( point, clampToLine ) {
13692
13693 startP.subVectors( point, this.start );
13694 startEnd.subVectors( this.end, this.start );
13695
13696 var startEnd2 = startEnd.dot( startEnd );
13697 var startEnd_startP = startEnd.dot( startP );
13698
13699 var t = startEnd_startP / startEnd2;
13700
13701 if ( clampToLine ) {
13702
13703 t = _Math.clamp( t, 0, 1 );
13704
13705 }
13706
13707 return t;
13708
13709 };
13710
13711 }(),
13712
13713 closestPointToPoint: function ( point, clampToLine, target ) {
13714
13715 var t = this.closestPointToPointParameter( point, clampToLine );
13716
13717 if ( target === undefined ) {
13718
13719 console.warn( 'THREE.Line3: .closestPointToPoint() target is now required' );
13720 target = new Vector3();
13721
13722 }
13723
13724 return this.delta( target ).multiplyScalar( t ).add( this.start );
13725
13726 },
13727
13728 applyMatrix4: function ( matrix ) {
13729
13730 this.start.applyMatrix4( matrix );
13731 this.end.applyMatrix4( matrix );
13732
13733 return this;
13734
13735 },
13736
13737 equals: function ( line ) {
13738
13739 return line.start.equals( this.start ) && line.end.equals( this.end );
13740
13741 }
13742
13743} );
13744
13745/**
13746 * @author bhouston / http://clara.io
13747 * @author mrdoob / http://mrdoob.com/
13748 */
13749
13750function Triangle( a, b, c ) {
13751
13752 this.a = ( a !== undefined ) ? a : new Vector3();
13753 this.b = ( b !== undefined ) ? b : new Vector3();
13754 this.c = ( c !== undefined ) ? c : new Vector3();
13755
13756}
13757
13758Object.assign( Triangle, {
13759
13760 getNormal: function () {
13761
13762 var v0 = new Vector3();
13763
13764 return function getNormal( a, b, c, target ) {
13765
13766 if ( target === undefined ) {
13767
13768 console.warn( 'THREE.Triangle: .getNormal() target is now required' );
13769 target = new Vector3();
13770
13771 }
13772
13773 target.subVectors( c, b );
13774 v0.subVectors( a, b );
13775 target.cross( v0 );
13776
13777 var targetLengthSq = target.lengthSq();
13778 if ( targetLengthSq > 0 ) {
13779
13780 return target.multiplyScalar( 1 / Math.sqrt( targetLengthSq ) );
13781
13782 }
13783
13784 return target.set( 0, 0, 0 );
13785
13786 };
13787
13788 }(),
13789
13790 // static/instance method to calculate barycentric coordinates
13791 // based on: http://www.blackpawn.com/texts/pointinpoly/default.html
13792 getBarycoord: function () {
13793
13794 var v0 = new Vector3();
13795 var v1 = new Vector3();
13796 var v2 = new Vector3();
13797
13798 return function getBarycoord( point, a, b, c, target ) {
13799
13800 v0.subVectors( c, a );
13801 v1.subVectors( b, a );
13802 v2.subVectors( point, a );
13803
13804 var dot00 = v0.dot( v0 );
13805 var dot01 = v0.dot( v1 );
13806 var dot02 = v0.dot( v2 );
13807 var dot11 = v1.dot( v1 );
13808 var dot12 = v1.dot( v2 );
13809
13810 var denom = ( dot00 * dot11 - dot01 * dot01 );
13811
13812 if ( target === undefined ) {
13813
13814 console.warn( 'THREE.Triangle: .getBarycoord() target is now required' );
13815 target = new Vector3();
13816
13817 }
13818
13819 // collinear or singular triangle
13820 if ( denom === 0 ) {
13821
13822 // arbitrary location outside of triangle?
13823 // not sure if this is the best idea, maybe should be returning undefined
13824 return target.set( - 2, - 1, - 1 );
13825
13826 }
13827
13828 var invDenom = 1 / denom;
13829 var u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;
13830 var v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;
13831
13832 // barycentric coordinates must always sum to 1
13833 return target.set( 1 - u - v, v, u );
13834
13835 };
13836
13837 }(),
13838
13839 containsPoint: function () {
13840
13841 var v1 = new Vector3();
13842
13843 return function containsPoint( point, a, b, c ) {
13844
13845 Triangle.getBarycoord( point, a, b, c, v1 );
13846
13847 return ( v1.x >= 0 ) && ( v1.y >= 0 ) && ( ( v1.x + v1.y ) <= 1 );
13848
13849 };
13850
13851 }()
13852
13853} );
13854
13855Object.assign( Triangle.prototype, {
13856
13857 set: function ( a, b, c ) {
13858
13859 this.a.copy( a );
13860 this.b.copy( b );
13861 this.c.copy( c );
13862
13863 return this;
13864
13865 },
13866
13867 setFromPointsAndIndices: function ( points, i0, i1, i2 ) {
13868
13869 this.a.copy( points[ i0 ] );
13870 this.b.copy( points[ i1 ] );
13871 this.c.copy( points[ i2 ] );
13872
13873 return this;
13874
13875 },
13876
13877 clone: function () {
13878
13879 return new this.constructor().copy( this );
13880
13881 },
13882
13883 copy: function ( triangle ) {
13884
13885 this.a.copy( triangle.a );
13886 this.b.copy( triangle.b );
13887 this.c.copy( triangle.c );
13888
13889 return this;
13890
13891 },
13892
13893 getArea: function () {
13894
13895 var v0 = new Vector3();
13896 var v1 = new Vector3();
13897
13898 return function getArea() {
13899
13900 v0.subVectors( this.c, this.b );
13901 v1.subVectors( this.a, this.b );
13902
13903 return v0.cross( v1 ).length() * 0.5;
13904
13905 };
13906
13907 }(),
13908
13909 getMidpoint: function ( target ) {
13910
13911 if ( target === undefined ) {
13912
13913 console.warn( 'THREE.Triangle: .getMidpoint() target is now required' );
13914 target = new Vector3();
13915
13916 }
13917
13918 return target.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 );
13919
13920 },
13921
13922 getNormal: function ( target ) {
13923
13924 return Triangle.getNormal( this.a, this.b, this.c, target );
13925
13926 },
13927
13928 getPlane: function ( target ) {
13929
13930 if ( target === undefined ) {
13931
13932 console.warn( 'THREE.Triangle: .getPlane() target is now required' );
13933 target = new Vector3();
13934
13935 }
13936
13937 return target.setFromCoplanarPoints( this.a, this.b, this.c );
13938
13939 },
13940
13941 getBarycoord: function ( point, target ) {
13942
13943 return Triangle.getBarycoord( point, this.a, this.b, this.c, target );
13944
13945 },
13946
13947 containsPoint: function ( point ) {
13948
13949 return Triangle.containsPoint( point, this.a, this.b, this.c );
13950
13951 },
13952
13953 intersectsBox: function ( box ) {
13954
13955 return box.intersectsTriangle( this );
13956
13957 },
13958
13959 closestPointToPoint: function () {
13960
13961 var plane = new Plane();
13962 var edgeList = [ new Line3(), new Line3(), new Line3() ];
13963 var projectedPoint = new Vector3();
13964 var closestPoint = new Vector3();
13965
13966 return function closestPointToPoint( point, target ) {
13967
13968 if ( target === undefined ) {
13969
13970 console.warn( 'THREE.Triangle: .closestPointToPoint() target is now required' );
13971 target = new Vector3();
13972
13973 }
13974
13975 var minDistance = Infinity;
13976
13977 // project the point onto the plane of the triangle
13978
13979 plane.setFromCoplanarPoints( this.a, this.b, this.c );
13980 plane.projectPoint( point, projectedPoint );
13981
13982 // check if the projection lies within the triangle
13983
13984 if ( this.containsPoint( projectedPoint ) === true ) {
13985
13986 // if so, this is the closest point
13987
13988 target.copy( projectedPoint );
13989
13990 } else {
13991
13992 // if not, the point falls outside the triangle. the target is the closest point to the triangle's edges or vertices
13993
13994 edgeList[ 0 ].set( this.a, this.b );
13995 edgeList[ 1 ].set( this.b, this.c );
13996 edgeList[ 2 ].set( this.c, this.a );
13997
13998 for ( var i = 0; i < edgeList.length; i ++ ) {
13999
14000 edgeList[ i ].closestPointToPoint( projectedPoint, true, closestPoint );
14001
14002 var distance = projectedPoint.distanceToSquared( closestPoint );
14003
14004 if ( distance < minDistance ) {
14005
14006 minDistance = distance;
14007
14008 target.copy( closestPoint );
14009
14010 }
14011
14012 }
14013
14014 }
14015
14016 return target;
14017
14018 };
14019
14020 }(),
14021
14022 equals: function ( triangle ) {
14023
14024 return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c );
14025
14026 }
14027
14028} );
14029
14030/**
14031 * @author mrdoob / http://mrdoob.com/
14032 * @author alteredq / http://alteredqualia.com/
14033 * @author mikael emtinger / http://gomo.se/
14034 * @author jonobr1 / http://jonobr1.com/
14035 */
14036
14037function Mesh( geometry, material ) {
14038
14039 Object3D.call( this );
14040
14041 this.type = 'Mesh';
14042
14043 this.geometry = geometry !== undefined ? geometry : new BufferGeometry();
14044 this.material = material !== undefined ? material : new MeshBasicMaterial( { color: Math.random() * 0xffffff } );
14045
14046 this.drawMode = TrianglesDrawMode;
14047
14048 this.updateMorphTargets();
14049
14050}
14051
14052Mesh.prototype = Object.assign( Object.create( Object3D.prototype ), {
14053
14054 constructor: Mesh,
14055
14056 isMesh: true,
14057
14058 setDrawMode: function ( value ) {
14059
14060 this.drawMode = value;
14061
14062 },
14063
14064 copy: function ( source ) {
14065
14066 Object3D.prototype.copy.call( this, source );
14067
14068 this.drawMode = source.drawMode;
14069
14070 if ( source.morphTargetInfluences !== undefined ) {
14071
14072 this.morphTargetInfluences = source.morphTargetInfluences.slice();
14073
14074 }
14075
14076 if ( source.morphTargetDictionary !== undefined ) {
14077
14078 this.morphTargetDictionary = Object.assign( {}, source.morphTargetDictionary );
14079
14080 }
14081
14082 return this;
14083
14084 },
14085
14086 updateMorphTargets: function () {
14087
14088 var geometry = this.geometry;
14089 var m, ml, name;
14090
14091 if ( geometry.isBufferGeometry ) {
14092
14093 var morphAttributes = geometry.morphAttributes;
14094 var keys = Object.keys( morphAttributes );
14095
14096 if ( keys.length > 0 ) {
14097
14098 var morphAttribute = morphAttributes[ keys[ 0 ] ];
14099
14100 if ( morphAttribute !== undefined ) {
14101
14102 this.morphTargetInfluences = [];
14103 this.morphTargetDictionary = {};
14104
14105 for ( m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
14106
14107 name = morphAttribute[ m ].name || String( m );
14108
14109 this.morphTargetInfluences.push( 0 );
14110 this.morphTargetDictionary[ name ] = m;
14111
14112 }
14113
14114 }
14115
14116 }
14117
14118 } else {
14119
14120 var morphTargets = geometry.morphTargets;
14121
14122 if ( morphTargets !== undefined && morphTargets.length > 0 ) {
14123
14124 this.morphTargetInfluences = [];
14125 this.morphTargetDictionary = {};
14126
14127 for ( m = 0, ml = morphTargets.length; m < ml; m ++ ) {
14128
14129 name = morphTargets[ m ].name || String( m );
14130
14131 this.morphTargetInfluences.push( 0 );
14132 this.morphTargetDictionary[ name ] = m;
14133
14134 }
14135
14136 }
14137
14138 }
14139
14140 },
14141
14142 raycast: ( function () {
14143
14144 var inverseMatrix = new Matrix4();
14145 var ray = new Ray();
14146 var sphere = new Sphere();
14147
14148 var vA = new Vector3();
14149 var vB = new Vector3();
14150 var vC = new Vector3();
14151
14152 var tempA = new Vector3();
14153 var tempB = new Vector3();
14154 var tempC = new Vector3();
14155
14156 var uvA = new Vector2();
14157 var uvB = new Vector2();
14158 var uvC = new Vector2();
14159
14160 var barycoord = new Vector3();
14161
14162 var intersectionPoint = new Vector3();
14163 var intersectionPointWorld = new Vector3();
14164
14165 function uvIntersection( point, p1, p2, p3, uv1, uv2, uv3 ) {
14166
14167 Triangle.getBarycoord( point, p1, p2, p3, barycoord );
14168
14169 uv1.multiplyScalar( barycoord.x );
14170 uv2.multiplyScalar( barycoord.y );
14171 uv3.multiplyScalar( barycoord.z );
14172
14173 uv1.add( uv2 ).add( uv3 );
14174
14175 return uv1.clone();
14176
14177 }
14178
14179 function checkIntersection( object, material, raycaster, ray, pA, pB, pC, point ) {
14180
14181 var intersect;
14182
14183 if ( material.side === BackSide ) {
14184
14185 intersect = ray.intersectTriangle( pC, pB, pA, true, point );
14186
14187 } else {
14188
14189 intersect = ray.intersectTriangle( pA, pB, pC, material.side !== DoubleSide, point );
14190
14191 }
14192
14193 if ( intersect === null ) return null;
14194
14195 intersectionPointWorld.copy( point );
14196 intersectionPointWorld.applyMatrix4( object.matrixWorld );
14197
14198 var distance = raycaster.ray.origin.distanceTo( intersectionPointWorld );
14199
14200 if ( distance < raycaster.near || distance > raycaster.far ) return null;
14201
14202 return {
14203 distance: distance,
14204 point: intersectionPointWorld.clone(),
14205 object: object
14206 };
14207
14208 }
14209
14210 function checkBufferGeometryIntersection( object, raycaster, ray, position, uv, a, b, c ) {
14211
14212 vA.fromBufferAttribute( position, a );
14213 vB.fromBufferAttribute( position, b );
14214 vC.fromBufferAttribute( position, c );
14215
14216 var intersection = checkIntersection( object, object.material, raycaster, ray, vA, vB, vC, intersectionPoint );
14217
14218 if ( intersection ) {
14219
14220 if ( uv ) {
14221
14222 uvA.fromBufferAttribute( uv, a );
14223 uvB.fromBufferAttribute( uv, b );
14224 uvC.fromBufferAttribute( uv, c );
14225
14226 intersection.uv = uvIntersection( intersectionPoint, vA, vB, vC, uvA, uvB, uvC );
14227
14228 }
14229
14230 var face = new Face3( a, b, c );
14231 Triangle.getNormal( vA, vB, vC, face.normal );
14232
14233 intersection.face = face;
14234 intersection.faceIndex = a;
14235
14236 }
14237
14238 return intersection;
14239
14240 }
14241
14242 return function raycast( raycaster, intersects ) {
14243
14244 var geometry = this.geometry;
14245 var material = this.material;
14246 var matrixWorld = this.matrixWorld;
14247
14248 if ( material === undefined ) return;
14249
14250 // Checking boundingSphere distance to ray
14251
14252 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
14253
14254 sphere.copy( geometry.boundingSphere );
14255 sphere.applyMatrix4( matrixWorld );
14256
14257 if ( raycaster.ray.intersectsSphere( sphere ) === false ) return;
14258
14259 //
14260
14261 inverseMatrix.getInverse( matrixWorld );
14262 ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix );
14263
14264 // Check boundingBox before continuing
14265
14266 if ( geometry.boundingBox !== null ) {
14267
14268 if ( ray.intersectsBox( geometry.boundingBox ) === false ) return;
14269
14270 }
14271
14272 var intersection;
14273
14274 if ( geometry.isBufferGeometry ) {
14275
14276 var a, b, c;
14277 var index = geometry.index;
14278 var position = geometry.attributes.position;
14279 var uv = geometry.attributes.uv;
14280 var i, l;
14281
14282 if ( index !== null ) {
14283
14284 // indexed buffer geometry
14285
14286 for ( i = 0, l = index.count; i < l; i += 3 ) {
14287
14288 a = index.getX( i );
14289 b = index.getX( i + 1 );
14290 c = index.getX( i + 2 );
14291
14292 intersection = checkBufferGeometryIntersection( this, raycaster, ray, position, uv, a, b, c );
14293
14294 if ( intersection ) {
14295
14296 intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indices buffer semantics
14297 intersects.push( intersection );
14298
14299 }
14300
14301 }
14302
14303 } else if ( position !== undefined ) {
14304
14305 // non-indexed buffer geometry
14306
14307 for ( i = 0, l = position.count; i < l; i += 3 ) {
14308
14309 a = i;
14310 b = i + 1;
14311 c = i + 2;
14312
14313 intersection = checkBufferGeometryIntersection( this, raycaster, ray, position, uv, a, b, c );
14314
14315 if ( intersection ) intersects.push( intersection );
14316
14317 }
14318
14319 }
14320
14321 } else if ( geometry.isGeometry ) {
14322
14323 var fvA, fvB, fvC;
14324 var isMultiMaterial = Array.isArray( material );
14325
14326 var vertices = geometry.vertices;
14327 var faces = geometry.faces;
14328 var uvs;
14329
14330 var faceVertexUvs = geometry.faceVertexUvs[ 0 ];
14331 if ( faceVertexUvs.length > 0 ) uvs = faceVertexUvs;
14332
14333 for ( var f = 0, fl = faces.length; f < fl; f ++ ) {
14334
14335 var face = faces[ f ];
14336 var faceMaterial = isMultiMaterial ? material[ face.materialIndex ] : material;
14337
14338 if ( faceMaterial === undefined ) continue;
14339
14340 fvA = vertices[ face.a ];
14341 fvB = vertices[ face.b ];
14342 fvC = vertices[ face.c ];
14343
14344 if ( faceMaterial.morphTargets === true ) {
14345
14346 var morphTargets = geometry.morphTargets;
14347 var morphInfluences = this.morphTargetInfluences;
14348
14349 vA.set( 0, 0, 0 );
14350 vB.set( 0, 0, 0 );
14351 vC.set( 0, 0, 0 );
14352
14353 for ( var t = 0, tl = morphTargets.length; t < tl; t ++ ) {
14354
14355 var influence = morphInfluences[ t ];
14356
14357 if ( influence === 0 ) continue;
14358
14359 var targets = morphTargets[ t ].vertices;
14360
14361 vA.addScaledVector( tempA.subVectors( targets[ face.a ], fvA ), influence );
14362 vB.addScaledVector( tempB.subVectors( targets[ face.b ], fvB ), influence );
14363 vC.addScaledVector( tempC.subVectors( targets[ face.c ], fvC ), influence );
14364
14365 }
14366
14367 vA.add( fvA );
14368 vB.add( fvB );
14369 vC.add( fvC );
14370
14371 fvA = vA;
14372 fvB = vB;
14373 fvC = vC;
14374
14375 }
14376
14377 intersection = checkIntersection( this, faceMaterial, raycaster, ray, fvA, fvB, fvC, intersectionPoint );
14378
14379 if ( intersection ) {
14380
14381 if ( uvs && uvs[ f ] ) {
14382
14383 var uvs_f = uvs[ f ];
14384 uvA.copy( uvs_f[ 0 ] );
14385 uvB.copy( uvs_f[ 1 ] );
14386 uvC.copy( uvs_f[ 2 ] );
14387
14388 intersection.uv = uvIntersection( intersectionPoint, fvA, fvB, fvC, uvA, uvB, uvC );
14389
14390 }
14391
14392 intersection.face = face;
14393 intersection.faceIndex = f;
14394 intersects.push( intersection );
14395
14396 }
14397
14398 }
14399
14400 }
14401
14402 };
14403
14404 }() ),
14405
14406 clone: function () {
14407
14408 return new this.constructor( this.geometry, this.material ).copy( this );
14409
14410 }
14411
14412} );
14413
14414/**
14415 * @author mrdoob / http://mrdoob.com/
14416 */
14417
14418function WebGLBackground( renderer, state, geometries, premultipliedAlpha ) {
14419
14420 var clearColor = new Color( 0x000000 );
14421 var clearAlpha = 0;
14422
14423 var planeCamera, planeMesh;
14424 var boxMesh;
14425
14426 function render( renderList, scene, camera, forceClear ) {
14427
14428 var background = scene.background;
14429
14430 if ( background === null ) {
14431
14432 setClear( clearColor, clearAlpha );
14433
14434 } else if ( background && background.isColor ) {
14435
14436 setClear( background, 1 );
14437 forceClear = true;
14438
14439 }
14440
14441 if ( renderer.autoClear || forceClear ) {
14442
14443 renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil );
14444
14445 }
14446
14447 if ( background && background.isCubeTexture ) {
14448
14449 if ( boxMesh === undefined ) {
14450
14451 boxMesh = new Mesh(
14452 new BoxBufferGeometry( 1, 1, 1 ),
14453 new ShaderMaterial( {
14454 uniforms: ShaderLib.cube.uniforms,
14455 vertexShader: ShaderLib.cube.vertexShader,
14456 fragmentShader: ShaderLib.cube.fragmentShader,
14457 side: BackSide,
14458 depthTest: true,
14459 depthWrite: false,
14460 fog: false
14461 } )
14462 );
14463
14464 boxMesh.geometry.removeAttribute( 'normal' );
14465 boxMesh.geometry.removeAttribute( 'uv' );
14466
14467 boxMesh.onBeforeRender = function ( renderer, scene, camera ) {
14468
14469 this.matrixWorld.copyPosition( camera.matrixWorld );
14470
14471 };
14472
14473 geometries.update( boxMesh.geometry );
14474
14475 }
14476
14477 boxMesh.material.uniforms.tCube.value = background;
14478
14479 renderList.push( boxMesh, boxMesh.geometry, boxMesh.material, 0, null );
14480
14481 } else if ( background && background.isTexture ) {
14482
14483 if ( planeCamera === undefined ) {
14484
14485 planeCamera = new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );
14486
14487 planeMesh = new Mesh(
14488 new PlaneBufferGeometry( 2, 2 ),
14489 new MeshBasicMaterial( { depthTest: false, depthWrite: false, fog: false } )
14490 );
14491
14492 geometries.update( planeMesh.geometry );
14493
14494 }
14495
14496 planeMesh.material.map = background;
14497
14498 // TODO Push this to renderList
14499
14500 renderer.renderBufferDirect( planeCamera, null, planeMesh.geometry, planeMesh.material, planeMesh, null );
14501
14502 }
14503
14504 }
14505
14506 function setClear( color, alpha ) {
14507
14508 state.buffers.color.setClear( color.r, color.g, color.b, alpha, premultipliedAlpha );
14509
14510 }
14511
14512 return {
14513
14514 getClearColor: function () {
14515
14516 return clearColor;
14517
14518 },
14519 setClearColor: function ( color, alpha ) {
14520
14521 clearColor.set( color );
14522 clearAlpha = alpha !== undefined ? alpha : 1;
14523 setClear( clearColor, clearAlpha );
14524
14525 },
14526 getClearAlpha: function () {
14527
14528 return clearAlpha;
14529
14530 },
14531 setClearAlpha: function ( alpha ) {
14532
14533 clearAlpha = alpha;
14534 setClear( clearColor, clearAlpha );
14535
14536 },
14537 render: render
14538
14539 };
14540
14541}
14542
14543/**
14544 * @author mrdoob / http://mrdoob.com/
14545 */
14546
14547function WebGLBufferRenderer( gl, extensions, info ) {
14548
14549 var mode;
14550
14551 function setMode( value ) {
14552
14553 mode = value;
14554
14555 }
14556
14557 function render( start, count ) {
14558
14559 gl.drawArrays( mode, start, count );
14560
14561 info.update( count, mode );
14562
14563 }
14564
14565 function renderInstances( geometry, start, count ) {
14566
14567 var extension = extensions.get( 'ANGLE_instanced_arrays' );
14568
14569 if ( extension === null ) {
14570
14571 console.error( 'THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
14572 return;
14573
14574 }
14575
14576 var position = geometry.attributes.position;
14577
14578 if ( position.isInterleavedBufferAttribute ) {
14579
14580 count = position.data.count;
14581
14582 extension.drawArraysInstancedANGLE( mode, 0, count, geometry.maxInstancedCount );
14583
14584 } else {
14585
14586 extension.drawArraysInstancedANGLE( mode, start, count, geometry.maxInstancedCount );
14587
14588 }
14589
14590 info.update( count, mode, geometry.maxInstancedCount );
14591
14592 }
14593
14594 //
14595
14596 this.setMode = setMode;
14597 this.render = render;
14598 this.renderInstances = renderInstances;
14599
14600}
14601
14602/**
14603 * @author mrdoob / http://mrdoob.com/
14604 */
14605
14606function WebGLCapabilities( gl, extensions, parameters ) {
14607
14608 var maxAnisotropy;
14609
14610 function getMaxAnisotropy() {
14611
14612 if ( maxAnisotropy !== undefined ) return maxAnisotropy;
14613
14614 var extension = extensions.get( 'EXT_texture_filter_anisotropic' );
14615
14616 if ( extension !== null ) {
14617
14618 maxAnisotropy = gl.getParameter( extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT );
14619
14620 } else {
14621
14622 maxAnisotropy = 0;
14623
14624 }
14625
14626 return maxAnisotropy;
14627
14628 }
14629
14630 function getMaxPrecision( precision ) {
14631
14632 if ( precision === 'highp' ) {
14633
14634 if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.HIGH_FLOAT ).precision > 0 &&
14635 gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.HIGH_FLOAT ).precision > 0 ) {
14636
14637 return 'highp';
14638
14639 }
14640
14641 precision = 'mediump';
14642
14643 }
14644
14645 if ( precision === 'mediump' ) {
14646
14647 if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.MEDIUM_FLOAT ).precision > 0 &&
14648 gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT ).precision > 0 ) {
14649
14650 return 'mediump';
14651
14652 }
14653
14654 }
14655
14656 return 'lowp';
14657
14658 }
14659
14660 var precision = parameters.precision !== undefined ? parameters.precision : 'highp';
14661 var maxPrecision = getMaxPrecision( precision );
14662
14663 if ( maxPrecision !== precision ) {
14664
14665 console.warn( 'THREE.WebGLRenderer:', precision, 'not supported, using', maxPrecision, 'instead.' );
14666 precision = maxPrecision;
14667
14668 }
14669
14670 var logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true;
14671
14672 var maxTextures = gl.getParameter( gl.MAX_TEXTURE_IMAGE_UNITS );
14673 var maxVertexTextures = gl.getParameter( gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS );
14674 var maxTextureSize = gl.getParameter( gl.MAX_TEXTURE_SIZE );
14675 var maxCubemapSize = gl.getParameter( gl.MAX_CUBE_MAP_TEXTURE_SIZE );
14676
14677 var maxAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS );
14678 var maxVertexUniforms = gl.getParameter( gl.MAX_VERTEX_UNIFORM_VECTORS );
14679 var maxVaryings = gl.getParameter( gl.MAX_VARYING_VECTORS );
14680 var maxFragmentUniforms = gl.getParameter( gl.MAX_FRAGMENT_UNIFORM_VECTORS );
14681
14682 var vertexTextures = maxVertexTextures > 0;
14683 var floatFragmentTextures = !! extensions.get( 'OES_texture_float' );
14684 var floatVertexTextures = vertexTextures && floatFragmentTextures;
14685
14686 return {
14687
14688 getMaxAnisotropy: getMaxAnisotropy,
14689 getMaxPrecision: getMaxPrecision,
14690
14691 precision: precision,
14692 logarithmicDepthBuffer: logarithmicDepthBuffer,
14693
14694 maxTextures: maxTextures,
14695 maxVertexTextures: maxVertexTextures,
14696 maxTextureSize: maxTextureSize,
14697 maxCubemapSize: maxCubemapSize,
14698
14699 maxAttributes: maxAttributes,
14700 maxVertexUniforms: maxVertexUniforms,
14701 maxVaryings: maxVaryings,
14702 maxFragmentUniforms: maxFragmentUniforms,
14703
14704 vertexTextures: vertexTextures,
14705 floatFragmentTextures: floatFragmentTextures,
14706 floatVertexTextures: floatVertexTextures
14707
14708 };
14709
14710}
14711
14712/**
14713 * @author tschw
14714 */
14715
14716function WebGLClipping() {
14717
14718 var scope = this,
14719
14720 globalState = null,
14721 numGlobalPlanes = 0,
14722 localClippingEnabled = false,
14723 renderingShadows = false,
14724
14725 plane = new Plane(),
14726 viewNormalMatrix = new Matrix3(),
14727
14728 uniform = { value: null, needsUpdate: false };
14729
14730 this.uniform = uniform;
14731 this.numPlanes = 0;
14732 this.numIntersection = 0;
14733
14734 this.init = function ( planes, enableLocalClipping, camera ) {
14735
14736 var enabled =
14737 planes.length !== 0 ||
14738 enableLocalClipping ||
14739 // enable state of previous frame - the clipping code has to
14740 // run another frame in order to reset the state:
14741 numGlobalPlanes !== 0 ||
14742 localClippingEnabled;
14743
14744 localClippingEnabled = enableLocalClipping;
14745
14746 globalState = projectPlanes( planes, camera, 0 );
14747 numGlobalPlanes = planes.length;
14748
14749 return enabled;
14750
14751 };
14752
14753 this.beginShadows = function () {
14754
14755 renderingShadows = true;
14756 projectPlanes( null );
14757
14758 };
14759
14760 this.endShadows = function () {
14761
14762 renderingShadows = false;
14763 resetGlobalState();
14764
14765 };
14766
14767 this.setState = function ( planes, clipIntersection, clipShadows, camera, cache, fromCache ) {
14768
14769 if ( ! localClippingEnabled || planes === null || planes.length === 0 || renderingShadows && ! clipShadows ) {
14770
14771 // there's no local clipping
14772
14773 if ( renderingShadows ) {
14774
14775 // there's no global clipping
14776
14777 projectPlanes( null );
14778
14779 } else {
14780
14781 resetGlobalState();
14782
14783 }
14784
14785 } else {
14786
14787 var nGlobal = renderingShadows ? 0 : numGlobalPlanes,
14788 lGlobal = nGlobal * 4,
14789
14790 dstArray = cache.clippingState || null;
14791
14792 uniform.value = dstArray; // ensure unique state
14793
14794 dstArray = projectPlanes( planes, camera, lGlobal, fromCache );
14795
14796 for ( var i = 0; i !== lGlobal; ++ i ) {
14797
14798 dstArray[ i ] = globalState[ i ];
14799
14800 }
14801
14802 cache.clippingState = dstArray;
14803 this.numIntersection = clipIntersection ? this.numPlanes : 0;
14804 this.numPlanes += nGlobal;
14805
14806 }
14807
14808
14809 };
14810
14811 function resetGlobalState() {
14812
14813 if ( uniform.value !== globalState ) {
14814
14815 uniform.value = globalState;
14816 uniform.needsUpdate = numGlobalPlanes > 0;
14817
14818 }
14819
14820 scope.numPlanes = numGlobalPlanes;
14821 scope.numIntersection = 0;
14822
14823 }
14824
14825 function projectPlanes( planes, camera, dstOffset, skipTransform ) {
14826
14827 var nPlanes = planes !== null ? planes.length : 0,
14828 dstArray = null;
14829
14830 if ( nPlanes !== 0 ) {
14831
14832 dstArray = uniform.value;
14833
14834 if ( skipTransform !== true || dstArray === null ) {
14835
14836 var flatSize = dstOffset + nPlanes * 4,
14837 viewMatrix = camera.matrixWorldInverse;
14838
14839 viewNormalMatrix.getNormalMatrix( viewMatrix );
14840
14841 if ( dstArray === null || dstArray.length < flatSize ) {
14842
14843 dstArray = new Float32Array( flatSize );
14844
14845 }
14846
14847 for ( var i = 0, i4 = dstOffset; i !== nPlanes; ++ i, i4 += 4 ) {
14848
14849 plane.copy( planes[ i ] ).applyMatrix4( viewMatrix, viewNormalMatrix );
14850
14851 plane.normal.toArray( dstArray, i4 );
14852 dstArray[ i4 + 3 ] = plane.constant;
14853
14854 }
14855
14856 }
14857
14858 uniform.value = dstArray;
14859 uniform.needsUpdate = true;
14860
14861 }
14862
14863 scope.numPlanes = nPlanes;
14864
14865 return dstArray;
14866
14867 }
14868
14869}
14870
14871/**
14872 * @author mrdoob / http://mrdoob.com/
14873 */
14874
14875function WebGLExtensions( gl ) {
14876
14877 var extensions = {};
14878
14879 return {
14880
14881 get: function ( name ) {
14882
14883 if ( extensions[ name ] !== undefined ) {
14884
14885 return extensions[ name ];
14886
14887 }
14888
14889 var extension;
14890
14891 switch ( name ) {
14892
14893 case 'WEBGL_depth_texture':
14894 extension = gl.getExtension( 'WEBGL_depth_texture' ) || gl.getExtension( 'MOZ_WEBGL_depth_texture' ) || gl.getExtension( 'WEBKIT_WEBGL_depth_texture' );
14895 break;
14896
14897 case 'EXT_texture_filter_anisotropic':
14898 extension = gl.getExtension( 'EXT_texture_filter_anisotropic' ) || gl.getExtension( 'MOZ_EXT_texture_filter_anisotropic' ) || gl.getExtension( 'WEBKIT_EXT_texture_filter_anisotropic' );
14899 break;
14900
14901 case 'WEBGL_compressed_texture_s3tc':
14902 extension = gl.getExtension( 'WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'MOZ_WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_s3tc' );
14903 break;
14904
14905 case 'WEBGL_compressed_texture_pvrtc':
14906 extension = gl.getExtension( 'WEBGL_compressed_texture_pvrtc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_pvrtc' );
14907 break;
14908
14909 default:
14910 extension = gl.getExtension( name );
14911
14912 }
14913
14914 if ( extension === null ) {
14915
14916 console.warn( 'THREE.WebGLRenderer: ' + name + ' extension not supported.' );
14917
14918 }
14919
14920 extensions[ name ] = extension;
14921
14922 return extension;
14923
14924 }
14925
14926 };
14927
14928}
14929
14930/**
14931 * @author mrdoob / http://mrdoob.com/
14932 */
14933
14934function WebGLGeometries( gl, attributes, info ) {
14935
14936 var geometries = {};
14937 var wireframeAttributes = {};
14938
14939 function onGeometryDispose( event ) {
14940
14941 var geometry = event.target;
14942 var buffergeometry = geometries[ geometry.id ];
14943
14944 if ( buffergeometry.index !== null ) {
14945
14946 attributes.remove( buffergeometry.index );
14947
14948 }
14949
14950 for ( var name in buffergeometry.attributes ) {
14951
14952 attributes.remove( buffergeometry.attributes[ name ] );
14953
14954 }
14955
14956 geometry.removeEventListener( 'dispose', onGeometryDispose );
14957
14958 delete geometries[ geometry.id ];
14959
14960 // TODO Remove duplicate code
14961
14962 var attribute = wireframeAttributes[ geometry.id ];
14963
14964 if ( attribute ) {
14965
14966 attributes.remove( attribute );
14967 delete wireframeAttributes[ geometry.id ];
14968
14969 }
14970
14971 attribute = wireframeAttributes[ buffergeometry.id ];
14972
14973 if ( attribute ) {
14974
14975 attributes.remove( attribute );
14976 delete wireframeAttributes[ buffergeometry.id ];
14977
14978 }
14979
14980 //
14981
14982 info.memory.geometries --;
14983
14984 }
14985
14986 function get( object, geometry ) {
14987
14988 var buffergeometry = geometries[ geometry.id ];
14989
14990 if ( buffergeometry ) return buffergeometry;
14991
14992 geometry.addEventListener( 'dispose', onGeometryDispose );
14993
14994 if ( geometry.isBufferGeometry ) {
14995
14996 buffergeometry = geometry;
14997
14998 } else if ( geometry.isGeometry ) {
14999
15000 if ( geometry._bufferGeometry === undefined ) {
15001
15002 geometry._bufferGeometry = new BufferGeometry().setFromObject( object );
15003
15004 }
15005
15006 buffergeometry = geometry._bufferGeometry;
15007
15008 }
15009
15010 geometries[ geometry.id ] = buffergeometry;
15011
15012 info.memory.geometries ++;
15013
15014 return buffergeometry;
15015
15016 }
15017
15018 function update( geometry ) {
15019
15020 var index = geometry.index;
15021 var geometryAttributes = geometry.attributes;
15022
15023 if ( index !== null ) {
15024
15025 attributes.update( index, gl.ELEMENT_ARRAY_BUFFER );
15026
15027 }
15028
15029 for ( var name in geometryAttributes ) {
15030
15031 attributes.update( geometryAttributes[ name ], gl.ARRAY_BUFFER );
15032
15033 }
15034
15035 // morph targets
15036
15037 var morphAttributes = geometry.morphAttributes;
15038
15039 for ( var name in morphAttributes ) {
15040
15041 var array = morphAttributes[ name ];
15042
15043 for ( var i = 0, l = array.length; i < l; i ++ ) {
15044
15045 attributes.update( array[ i ], gl.ARRAY_BUFFER );
15046
15047 }
15048
15049 }
15050
15051 }
15052
15053 function getWireframeAttribute( geometry ) {
15054
15055 var attribute = wireframeAttributes[ geometry.id ];
15056
15057 if ( attribute ) return attribute;
15058
15059 var indices = [];
15060
15061 var geometryIndex = geometry.index;
15062 var geometryAttributes = geometry.attributes;
15063
15064 // console.time( 'wireframe' );
15065
15066 if ( geometryIndex !== null ) {
15067
15068 var array = geometryIndex.array;
15069
15070 for ( var i = 0, l = array.length; i < l; i += 3 ) {
15071
15072 var a = array[ i + 0 ];
15073 var b = array[ i + 1 ];
15074 var c = array[ i + 2 ];
15075
15076 indices.push( a, b, b, c, c, a );
15077
15078 }
15079
15080 } else {
15081
15082 var array = geometryAttributes.position.array;
15083
15084 for ( var i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) {
15085
15086 var a = i + 0;
15087 var b = i + 1;
15088 var c = i + 2;
15089
15090 indices.push( a, b, b, c, c, a );
15091
15092 }
15093
15094 }
15095
15096 // console.timeEnd( 'wireframe' );
15097
15098 attribute = new ( arrayMax( indices ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 );
15099
15100 attributes.update( attribute, gl.ELEMENT_ARRAY_BUFFER );
15101
15102 wireframeAttributes[ geometry.id ] = attribute;
15103
15104 return attribute;
15105
15106 }
15107
15108 return {
15109
15110 get: get,
15111 update: update,
15112
15113 getWireframeAttribute: getWireframeAttribute
15114
15115 };
15116
15117}
15118
15119/**
15120 * @author mrdoob / http://mrdoob.com/
15121 */
15122
15123function WebGLIndexedBufferRenderer( gl, extensions, info ) {
15124
15125 var mode;
15126
15127 function setMode( value ) {
15128
15129 mode = value;
15130
15131 }
15132
15133 var type, bytesPerElement;
15134
15135 function setIndex( value ) {
15136
15137 type = value.type;
15138 bytesPerElement = value.bytesPerElement;
15139
15140 }
15141
15142 function render( start, count ) {
15143
15144 gl.drawElements( mode, count, type, start * bytesPerElement );
15145
15146 info.update( count, mode );
15147
15148 }
15149
15150 function renderInstances( geometry, start, count ) {
15151
15152 var extension = extensions.get( 'ANGLE_instanced_arrays' );
15153
15154 if ( extension === null ) {
15155
15156 console.error( 'THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
15157 return;
15158
15159 }
15160
15161 extension.drawElementsInstancedANGLE( mode, count, type, start * bytesPerElement, geometry.maxInstancedCount );
15162
15163 info.update( count, mode, geometry.maxInstancedCount );
15164
15165 }
15166
15167 //
15168
15169 this.setMode = setMode;
15170 this.setIndex = setIndex;
15171 this.render = render;
15172 this.renderInstances = renderInstances;
15173
15174}
15175
15176/**
15177 * @author Mugen87 / https://github.com/Mugen87
15178 */
15179
15180function WebGLInfo( gl ) {
15181
15182 var memory = {
15183 geometries: 0,
15184 textures: 0
15185 };
15186
15187 var render = {
15188 frame: 0,
15189 calls: 0,
15190 triangles: 0,
15191 points: 0,
15192 lines: 0
15193 };
15194
15195 function update( count, mode, instanceCount ) {
15196
15197 instanceCount = instanceCount || 1;
15198
15199 render.calls ++;
15200
15201 switch ( mode ) {
15202
15203 case gl.TRIANGLES:
15204 render.triangles += instanceCount * ( count / 3 );
15205 break;
15206
15207 case gl.TRIANGLE_STRIP:
15208 case gl.TRIANGLE_FAN:
15209 render.triangles += instanceCount * ( count - 2 );
15210 break;
15211
15212 case gl.LINES:
15213 render.lines += instanceCount * ( count / 2 );
15214 break;
15215
15216 case gl.LINE_STRIP:
15217 render.lines += instanceCount * ( count - 1 );
15218 break;
15219
15220 case gl.LINE_LOOP:
15221 render.lines += instanceCount * count;
15222 break;
15223
15224 case gl.POINTS:
15225 render.points += instanceCount * count;
15226 break;
15227
15228 default:
15229 console.error( 'THREE.WebGLInfo: Unknown draw mode:', mode );
15230 break;
15231
15232 }
15233
15234 }
15235
15236 function reset() {
15237
15238 render.frame ++;
15239 render.calls = 0;
15240 render.triangles = 0;
15241 render.points = 0;
15242 render.lines = 0;
15243
15244 }
15245
15246 return {
15247 memory: memory,
15248 render: render,
15249 programs: null,
15250 autoReset: true,
15251 reset: reset,
15252 update: update
15253 };
15254
15255}
15256
15257/**
15258 * @author mrdoob / http://mrdoob.com/
15259 */
15260
15261function absNumericalSort( a, b ) {
15262
15263 return Math.abs( b[ 1 ] ) - Math.abs( a[ 1 ] );
15264
15265}
15266
15267function WebGLMorphtargets( gl ) {
15268
15269 var influencesList = {};
15270 var morphInfluences = new Float32Array( 8 );
15271
15272 function update( object, geometry, material, program ) {
15273
15274 var objectInfluences = object.morphTargetInfluences;
15275
15276 var length = objectInfluences.length;
15277
15278 var influences = influencesList[ geometry.id ];
15279
15280 if ( influences === undefined ) {
15281
15282 // initialise list
15283
15284 influences = [];
15285
15286 for ( var i = 0; i < length; i ++ ) {
15287
15288 influences[ i ] = [ i, 0 ];
15289
15290 }
15291
15292 influencesList[ geometry.id ] = influences;
15293
15294 }
15295
15296 var morphTargets = material.morphTargets && geometry.morphAttributes.position;
15297 var morphNormals = material.morphNormals && geometry.morphAttributes.normal;
15298
15299 // Remove current morphAttributes
15300
15301 for ( var i = 0; i < length; i ++ ) {
15302
15303 var influence = influences[ i ];
15304
15305 if ( influence[ 1 ] !== 0 ) {
15306
15307 if ( morphTargets ) geometry.removeAttribute( 'morphTarget' + i );
15308 if ( morphNormals ) geometry.removeAttribute( 'morphNormal' + i );
15309
15310 }
15311
15312 }
15313
15314 // Collect influences
15315
15316 for ( var i = 0; i < length; i ++ ) {
15317
15318 var influence = influences[ i ];
15319
15320 influence[ 0 ] = i;
15321 influence[ 1 ] = objectInfluences[ i ];
15322
15323 }
15324
15325 influences.sort( absNumericalSort );
15326
15327 // Add morphAttributes
15328
15329 for ( var i = 0; i < 8; i ++ ) {
15330
15331 var influence = influences[ i ];
15332
15333 if ( influence ) {
15334
15335 var index = influence[ 0 ];
15336 var value = influence[ 1 ];
15337
15338 if ( value ) {
15339
15340 if ( morphTargets ) geometry.addAttribute( 'morphTarget' + i, morphTargets[ index ] );
15341 if ( morphNormals ) geometry.addAttribute( 'morphNormal' + i, morphNormals[ index ] );
15342
15343 morphInfluences[ i ] = value;
15344 continue;
15345
15346 }
15347
15348 }
15349
15350 morphInfluences[ i ] = 0;
15351
15352 }
15353
15354 program.getUniforms().setValue( gl, 'morphTargetInfluences', morphInfluences );
15355
15356 }
15357
15358 return {
15359
15360 update: update
15361
15362 };
15363
15364}
15365
15366/**
15367 * @author mrdoob / http://mrdoob.com/
15368 */
15369
15370function WebGLObjects( geometries, info ) {
15371
15372 var updateList = {};
15373
15374 function update( object ) {
15375
15376 var frame = info.render.frame;
15377
15378 var geometry = object.geometry;
15379 var buffergeometry = geometries.get( object, geometry );
15380
15381 // Update once per frame
15382
15383 if ( updateList[ buffergeometry.id ] !== frame ) {
15384
15385 if ( geometry.isGeometry ) {
15386
15387 buffergeometry.updateFromObject( object );
15388
15389 }
15390
15391 geometries.update( buffergeometry );
15392
15393 updateList[ buffergeometry.id ] = frame;
15394
15395 }
15396
15397 return buffergeometry;
15398
15399 }
15400
15401 function dispose() {
15402
15403 updateList = {};
15404
15405 }
15406
15407 return {
15408
15409 update: update,
15410 dispose: dispose
15411
15412 };
15413
15414}
15415
15416/**
15417 * @author mrdoob / http://mrdoob.com/
15418 */
15419
15420function CubeTexture( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) {
15421
15422 images = images !== undefined ? images : [];
15423 mapping = mapping !== undefined ? mapping : CubeReflectionMapping;
15424
15425 Texture.call( this, images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
15426
15427 this.flipY = false;
15428
15429}
15430
15431CubeTexture.prototype = Object.create( Texture.prototype );
15432CubeTexture.prototype.constructor = CubeTexture;
15433
15434CubeTexture.prototype.isCubeTexture = true;
15435
15436Object.defineProperty( CubeTexture.prototype, 'images', {
15437
15438 get: function () {
15439
15440 return this.image;
15441
15442 },
15443
15444 set: function ( value ) {
15445
15446 this.image = value;
15447
15448 }
15449
15450} );
15451
15452/**
15453 * @author tschw
15454 *
15455 * Uniforms of a program.
15456 * Those form a tree structure with a special top-level container for the root,
15457 * which you get by calling 'new WebGLUniforms( gl, program, renderer )'.
15458 *
15459 *
15460 * Properties of inner nodes including the top-level container:
15461 *
15462 * .seq - array of nested uniforms
15463 * .map - nested uniforms by name
15464 *
15465 *
15466 * Methods of all nodes except the top-level container:
15467 *
15468 * .setValue( gl, value, [renderer] )
15469 *
15470 * uploads a uniform value(s)
15471 * the 'renderer' parameter is needed for sampler uniforms
15472 *
15473 *
15474 * Static methods of the top-level container (renderer factorizations):
15475 *
15476 * .upload( gl, seq, values, renderer )
15477 *
15478 * sets uniforms in 'seq' to 'values[id].value'
15479 *
15480 * .seqWithValue( seq, values ) : filteredSeq
15481 *
15482 * filters 'seq' entries with corresponding entry in values
15483 *
15484 *
15485 * Methods of the top-level container (renderer factorizations):
15486 *
15487 * .setValue( gl, name, value )
15488 *
15489 * sets uniform with name 'name' to 'value'
15490 *
15491 * .set( gl, obj, prop )
15492 *
15493 * sets uniform from object and property with same name than uniform
15494 *
15495 * .setOptional( gl, obj, prop )
15496 *
15497 * like .set for an optional property of the object
15498 *
15499 */
15500
15501var emptyTexture = new Texture();
15502var emptyCubeTexture = new CubeTexture();
15503
15504// --- Base for inner nodes (including the root) ---
15505
15506function UniformContainer() {
15507
15508 this.seq = [];
15509 this.map = {};
15510
15511}
15512
15513// --- Utilities ---
15514
15515// Array Caches (provide typed arrays for temporary by size)
15516
15517var arrayCacheF32 = [];
15518var arrayCacheI32 = [];
15519
15520// Float32Array caches used for uploading Matrix uniforms
15521
15522var mat4array = new Float32Array( 16 );
15523var mat3array = new Float32Array( 9 );
15524
15525// Flattening for arrays of vectors and matrices
15526
15527function flatten( array, nBlocks, blockSize ) {
15528
15529 var firstElem = array[ 0 ];
15530
15531 if ( firstElem <= 0 || firstElem > 0 ) return array;
15532 // unoptimized: ! isNaN( firstElem )
15533 // see http://jacksondunstan.com/articles/983
15534
15535 var n = nBlocks * blockSize,
15536 r = arrayCacheF32[ n ];
15537
15538 if ( r === undefined ) {
15539
15540 r = new Float32Array( n );
15541 arrayCacheF32[ n ] = r;
15542
15543 }
15544
15545 if ( nBlocks !== 0 ) {
15546
15547 firstElem.toArray( r, 0 );
15548
15549 for ( var i = 1, offset = 0; i !== nBlocks; ++ i ) {
15550
15551 offset += blockSize;
15552 array[ i ].toArray( r, offset );
15553
15554 }
15555
15556 }
15557
15558 return r;
15559
15560}
15561
15562// Texture unit allocation
15563
15564function allocTexUnits( renderer, n ) {
15565
15566 var r = arrayCacheI32[ n ];
15567
15568 if ( r === undefined ) {
15569
15570 r = new Int32Array( n );
15571 arrayCacheI32[ n ] = r;
15572
15573 }
15574
15575 for ( var i = 0; i !== n; ++ i )
15576 r[ i ] = renderer.allocTextureUnit();
15577
15578 return r;
15579
15580}
15581
15582// --- Setters ---
15583
15584// Note: Defining these methods externally, because they come in a bunch
15585// and this way their names minify.
15586
15587// Single scalar
15588
15589function setValue1f( gl, v ) {
15590
15591 gl.uniform1f( this.addr, v );
15592
15593}
15594
15595function setValue1i( gl, v ) {
15596
15597 gl.uniform1i( this.addr, v );
15598
15599}
15600
15601// Single float vector (from flat array or THREE.VectorN)
15602
15603function setValue2fv( gl, v ) {
15604
15605 if ( v.x === undefined ) {
15606
15607 gl.uniform2fv( this.addr, v );
15608
15609 } else {
15610
15611 gl.uniform2f( this.addr, v.x, v.y );
15612
15613 }
15614
15615}
15616
15617function setValue3fv( gl, v ) {
15618
15619 if ( v.x !== undefined ) {
15620
15621 gl.uniform3f( this.addr, v.x, v.y, v.z );
15622
15623 } else if ( v.r !== undefined ) {
15624
15625 gl.uniform3f( this.addr, v.r, v.g, v.b );
15626
15627 } else {
15628
15629 gl.uniform3fv( this.addr, v );
15630
15631 }
15632
15633}
15634
15635function setValue4fv( gl, v ) {
15636
15637 if ( v.x === undefined ) {
15638
15639 gl.uniform4fv( this.addr, v );
15640
15641 } else {
15642
15643 gl.uniform4f( this.addr, v.x, v.y, v.z, v.w );
15644
15645 }
15646
15647}
15648
15649// Single matrix (from flat array or MatrixN)
15650
15651function setValue2fm( gl, v ) {
15652
15653 gl.uniformMatrix2fv( this.addr, false, v.elements || v );
15654
15655}
15656
15657function setValue3fm( gl, v ) {
15658
15659 if ( v.elements === undefined ) {
15660
15661 gl.uniformMatrix3fv( this.addr, false, v );
15662
15663 } else {
15664
15665 mat3array.set( v.elements );
15666 gl.uniformMatrix3fv( this.addr, false, mat3array );
15667
15668 }
15669
15670}
15671
15672function setValue4fm( gl, v ) {
15673
15674 if ( v.elements === undefined ) {
15675
15676 gl.uniformMatrix4fv( this.addr, false, v );
15677
15678 } else {
15679
15680 mat4array.set( v.elements );
15681 gl.uniformMatrix4fv( this.addr, false, mat4array );
15682
15683 }
15684
15685}
15686
15687// Single texture (2D / Cube)
15688
15689function setValueT1( gl, v, renderer ) {
15690
15691 var unit = renderer.allocTextureUnit();
15692 gl.uniform1i( this.addr, unit );
15693 renderer.setTexture2D( v || emptyTexture, unit );
15694
15695}
15696
15697function setValueT6( gl, v, renderer ) {
15698
15699 var unit = renderer.allocTextureUnit();
15700 gl.uniform1i( this.addr, unit );
15701 renderer.setTextureCube( v || emptyCubeTexture, unit );
15702
15703}
15704
15705// Integer / Boolean vectors or arrays thereof (always flat arrays)
15706
15707function setValue2iv( gl, v ) {
15708
15709 gl.uniform2iv( this.addr, v );
15710
15711}
15712
15713function setValue3iv( gl, v ) {
15714
15715 gl.uniform3iv( this.addr, v );
15716
15717}
15718
15719function setValue4iv( gl, v ) {
15720
15721 gl.uniform4iv( this.addr, v );
15722
15723}
15724
15725// Helper to pick the right setter for the singular case
15726
15727function getSingularSetter( type ) {
15728
15729 switch ( type ) {
15730
15731 case 0x1406: return setValue1f; // FLOAT
15732 case 0x8b50: return setValue2fv; // _VEC2
15733 case 0x8b51: return setValue3fv; // _VEC3
15734 case 0x8b52: return setValue4fv; // _VEC4
15735
15736 case 0x8b5a: return setValue2fm; // _MAT2
15737 case 0x8b5b: return setValue3fm; // _MAT3
15738 case 0x8b5c: return setValue4fm; // _MAT4
15739
15740 case 0x8b5e: case 0x8d66: return setValueT1; // SAMPLER_2D, SAMPLER_EXTERNAL_OES
15741 case 0x8b60: return setValueT6; // SAMPLER_CUBE
15742
15743 case 0x1404: case 0x8b56: return setValue1i; // INT, BOOL
15744 case 0x8b53: case 0x8b57: return setValue2iv; // _VEC2
15745 case 0x8b54: case 0x8b58: return setValue3iv; // _VEC3
15746 case 0x8b55: case 0x8b59: return setValue4iv; // _VEC4
15747
15748 }
15749
15750}
15751
15752// Array of scalars
15753
15754function setValue1fv( gl, v ) {
15755
15756 gl.uniform1fv( this.addr, v );
15757
15758}
15759function setValue1iv( gl, v ) {
15760
15761 gl.uniform1iv( this.addr, v );
15762
15763}
15764
15765// Array of vectors (flat or from THREE classes)
15766
15767function setValueV2a( gl, v ) {
15768
15769 gl.uniform2fv( this.addr, flatten( v, this.size, 2 ) );
15770
15771}
15772
15773function setValueV3a( gl, v ) {
15774
15775 gl.uniform3fv( this.addr, flatten( v, this.size, 3 ) );
15776
15777}
15778
15779function setValueV4a( gl, v ) {
15780
15781 gl.uniform4fv( this.addr, flatten( v, this.size, 4 ) );
15782
15783}
15784
15785// Array of matrices (flat or from THREE clases)
15786
15787function setValueM2a( gl, v ) {
15788
15789 gl.uniformMatrix2fv( this.addr, false, flatten( v, this.size, 4 ) );
15790
15791}
15792
15793function setValueM3a( gl, v ) {
15794
15795 gl.uniformMatrix3fv( this.addr, false, flatten( v, this.size, 9 ) );
15796
15797}
15798
15799function setValueM4a( gl, v ) {
15800
15801 gl.uniformMatrix4fv( this.addr, false, flatten( v, this.size, 16 ) );
15802
15803}
15804
15805// Array of textures (2D / Cube)
15806
15807function setValueT1a( gl, v, renderer ) {
15808
15809 var n = v.length,
15810 units = allocTexUnits( renderer, n );
15811
15812 gl.uniform1iv( this.addr, units );
15813
15814 for ( var i = 0; i !== n; ++ i ) {
15815
15816 renderer.setTexture2D( v[ i ] || emptyTexture, units[ i ] );
15817
15818 }
15819
15820}
15821
15822function setValueT6a( gl, v, renderer ) {
15823
15824 var n = v.length,
15825 units = allocTexUnits( renderer, n );
15826
15827 gl.uniform1iv( this.addr, units );
15828
15829 for ( var i = 0; i !== n; ++ i ) {
15830
15831 renderer.setTextureCube( v[ i ] || emptyCubeTexture, units[ i ] );
15832
15833 }
15834
15835}
15836
15837// Helper to pick the right setter for a pure (bottom-level) array
15838
15839function getPureArraySetter( type ) {
15840
15841 switch ( type ) {
15842
15843 case 0x1406: return setValue1fv; // FLOAT
15844 case 0x8b50: return setValueV2a; // _VEC2
15845 case 0x8b51: return setValueV3a; // _VEC3
15846 case 0x8b52: return setValueV4a; // _VEC4
15847
15848 case 0x8b5a: return setValueM2a; // _MAT2
15849 case 0x8b5b: return setValueM3a; // _MAT3
15850 case 0x8b5c: return setValueM4a; // _MAT4
15851
15852 case 0x8b5e: return setValueT1a; // SAMPLER_2D
15853 case 0x8b60: return setValueT6a; // SAMPLER_CUBE
15854
15855 case 0x1404: case 0x8b56: return setValue1iv; // INT, BOOL
15856 case 0x8b53: case 0x8b57: return setValue2iv; // _VEC2
15857 case 0x8b54: case 0x8b58: return setValue3iv; // _VEC3
15858 case 0x8b55: case 0x8b59: return setValue4iv; // _VEC4
15859
15860 }
15861
15862}
15863
15864// --- Uniform Classes ---
15865
15866function SingleUniform( id, activeInfo, addr ) {
15867
15868 this.id = id;
15869 this.addr = addr;
15870 this.setValue = getSingularSetter( activeInfo.type );
15871
15872 // this.path = activeInfo.name; // DEBUG
15873
15874}
15875
15876function PureArrayUniform( id, activeInfo, addr ) {
15877
15878 this.id = id;
15879 this.addr = addr;
15880 this.size = activeInfo.size;
15881 this.setValue = getPureArraySetter( activeInfo.type );
15882
15883 // this.path = activeInfo.name; // DEBUG
15884
15885}
15886
15887function StructuredUniform( id ) {
15888
15889 this.id = id;
15890
15891 UniformContainer.call( this ); // mix-in
15892
15893}
15894
15895StructuredUniform.prototype.setValue = function ( gl, value ) {
15896
15897 // Note: Don't need an extra 'renderer' parameter, since samplers
15898 // are not allowed in structured uniforms.
15899
15900 var seq = this.seq;
15901
15902 for ( var i = 0, n = seq.length; i !== n; ++ i ) {
15903
15904 var u = seq[ i ];
15905 u.setValue( gl, value[ u.id ] );
15906
15907 }
15908
15909};
15910
15911// --- Top-level ---
15912
15913// Parser - builds up the property tree from the path strings
15914
15915var RePathPart = /([\w\d_]+)(\])?(\[|\.)?/g;
15916
15917// extracts
15918// - the identifier (member name or array index)
15919// - followed by an optional right bracket (found when array index)
15920// - followed by an optional left bracket or dot (type of subscript)
15921//
15922// Note: These portions can be read in a non-overlapping fashion and
15923// allow straightforward parsing of the hierarchy that WebGL encodes
15924// in the uniform names.
15925
15926function addUniform( container, uniformObject ) {
15927
15928 container.seq.push( uniformObject );
15929 container.map[ uniformObject.id ] = uniformObject;
15930
15931}
15932
15933function parseUniform( activeInfo, addr, container ) {
15934
15935 var path = activeInfo.name,
15936 pathLength = path.length;
15937
15938 // reset RegExp object, because of the early exit of a previous run
15939 RePathPart.lastIndex = 0;
15940
15941 for ( ; ; ) {
15942
15943 var match = RePathPart.exec( path ),
15944 matchEnd = RePathPart.lastIndex,
15945
15946 id = match[ 1 ],
15947 idIsIndex = match[ 2 ] === ']',
15948 subscript = match[ 3 ];
15949
15950 if ( idIsIndex ) id = id | 0; // convert to integer
15951
15952 if ( subscript === undefined || subscript === '[' && matchEnd + 2 === pathLength ) {
15953
15954 // bare name or "pure" bottom-level array "[0]" suffix
15955
15956 addUniform( container, subscript === undefined ?
15957 new SingleUniform( id, activeInfo, addr ) :
15958 new PureArrayUniform( id, activeInfo, addr ) );
15959
15960 break;
15961
15962 } else {
15963
15964 // step into inner node / create it in case it doesn't exist
15965
15966 var map = container.map, next = map[ id ];
15967
15968 if ( next === undefined ) {
15969
15970 next = new StructuredUniform( id );
15971 addUniform( container, next );
15972
15973 }
15974
15975 container = next;
15976
15977 }
15978
15979 }
15980
15981}
15982
15983// Root Container
15984
15985function WebGLUniforms( gl, program, renderer ) {
15986
15987 UniformContainer.call( this );
15988
15989 this.renderer = renderer;
15990
15991 var n = gl.getProgramParameter( program, gl.ACTIVE_UNIFORMS );
15992
15993 for ( var i = 0; i < n; ++ i ) {
15994
15995 var info = gl.getActiveUniform( program, i ),
15996 addr = gl.getUniformLocation( program, info.name );
15997
15998 parseUniform( info, addr, this );
15999
16000 }
16001
16002}
16003
16004WebGLUniforms.prototype.setValue = function ( gl, name, value ) {
16005
16006 var u = this.map[ name ];
16007
16008 if ( u !== undefined ) u.setValue( gl, value, this.renderer );
16009
16010};
16011
16012WebGLUniforms.prototype.setOptional = function ( gl, object, name ) {
16013
16014 var v = object[ name ];
16015
16016 if ( v !== undefined ) this.setValue( gl, name, v );
16017
16018};
16019
16020
16021// Static interface
16022
16023WebGLUniforms.upload = function ( gl, seq, values, renderer ) {
16024
16025 for ( var i = 0, n = seq.length; i !== n; ++ i ) {
16026
16027 var u = seq[ i ],
16028 v = values[ u.id ];
16029
16030 if ( v.needsUpdate !== false ) {
16031
16032 // note: always updating when .needsUpdate is undefined
16033 u.setValue( gl, v.value, renderer );
16034
16035 }
16036
16037 }
16038
16039};
16040
16041WebGLUniforms.seqWithValue = function ( seq, values ) {
16042
16043 var r = [];
16044
16045 for ( var i = 0, n = seq.length; i !== n; ++ i ) {
16046
16047 var u = seq[ i ];
16048 if ( u.id in values ) r.push( u );
16049
16050 }
16051
16052 return r;
16053
16054};
16055
16056/**
16057 * @author mrdoob / http://mrdoob.com/
16058 */
16059
16060function addLineNumbers( string ) {
16061
16062 var lines = string.split( '\n' );
16063
16064 for ( var i = 0; i < lines.length; i ++ ) {
16065
16066 lines[ i ] = ( i + 1 ) + ': ' + lines[ i ];
16067
16068 }
16069
16070 return lines.join( '\n' );
16071
16072}
16073
16074function WebGLShader( gl, type, string ) {
16075
16076 var shader = gl.createShader( type );
16077
16078 gl.shaderSource( shader, string );
16079 gl.compileShader( shader );
16080
16081 if ( gl.getShaderParameter( shader, gl.COMPILE_STATUS ) === false ) {
16082
16083 console.error( 'THREE.WebGLShader: Shader couldn\'t compile.' );
16084
16085 }
16086
16087 if ( gl.getShaderInfoLog( shader ) !== '' ) {
16088
16089 console.warn( 'THREE.WebGLShader: gl.getShaderInfoLog()', type === gl.VERTEX_SHADER ? 'vertex' : 'fragment', gl.getShaderInfoLog( shader ), addLineNumbers( string ) );
16090
16091 }
16092
16093 // --enable-privileged-webgl-extension
16094 // console.log( type, gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) );
16095
16096 return shader;
16097
16098}
16099
16100/**
16101 * @author mrdoob / http://mrdoob.com/
16102 */
16103
16104var programIdCount = 0;
16105
16106function getEncodingComponents( encoding ) {
16107
16108 switch ( encoding ) {
16109
16110 case LinearEncoding:
16111 return [ 'Linear', '( value )' ];
16112 case sRGBEncoding:
16113 return [ 'sRGB', '( value )' ];
16114 case RGBEEncoding:
16115 return [ 'RGBE', '( value )' ];
16116 case RGBM7Encoding:
16117 return [ 'RGBM', '( value, 7.0 )' ];
16118 case RGBM16Encoding:
16119 return [ 'RGBM', '( value, 16.0 )' ];
16120 case RGBDEncoding:
16121 return [ 'RGBD', '( value, 256.0 )' ];
16122 case GammaEncoding:
16123 return [ 'Gamma', '( value, float( GAMMA_FACTOR ) )' ];
16124 default:
16125 throw new Error( 'unsupported encoding: ' + encoding );
16126
16127 }
16128
16129}
16130
16131function getTexelDecodingFunction( functionName, encoding ) {
16132
16133 var components = getEncodingComponents( encoding );
16134 return 'vec4 ' + functionName + '( vec4 value ) { return ' + components[ 0 ] + 'ToLinear' + components[ 1 ] + '; }';
16135
16136}
16137
16138function getTexelEncodingFunction( functionName, encoding ) {
16139
16140 var components = getEncodingComponents( encoding );
16141 return 'vec4 ' + functionName + '( vec4 value ) { return LinearTo' + components[ 0 ] + components[ 1 ] + '; }';
16142
16143}
16144
16145function getToneMappingFunction( functionName, toneMapping ) {
16146
16147 var toneMappingName;
16148
16149 switch ( toneMapping ) {
16150
16151 case LinearToneMapping:
16152 toneMappingName = 'Linear';
16153 break;
16154
16155 case ReinhardToneMapping:
16156 toneMappingName = 'Reinhard';
16157 break;
16158
16159 case Uncharted2ToneMapping:
16160 toneMappingName = 'Uncharted2';
16161 break;
16162
16163 case CineonToneMapping:
16164 toneMappingName = 'OptimizedCineon';
16165 break;
16166
16167 default:
16168 throw new Error( 'unsupported toneMapping: ' + toneMapping );
16169
16170 }
16171
16172 return 'vec3 ' + functionName + '( vec3 color ) { return ' + toneMappingName + 'ToneMapping( color ); }';
16173
16174}
16175
16176function generateExtensions( extensions, parameters, rendererExtensions ) {
16177
16178 extensions = extensions || {};
16179
16180 var chunks = [
16181 ( extensions.derivatives || parameters.envMapCubeUV || parameters.bumpMap || parameters.normalMap || parameters.flatShading ) ? '#extension GL_OES_standard_derivatives : enable' : '',
16182 ( extensions.fragDepth || parameters.logarithmicDepthBuffer ) && rendererExtensions.get( 'EXT_frag_depth' ) ? '#extension GL_EXT_frag_depth : enable' : '',
16183 ( extensions.drawBuffers ) && rendererExtensions.get( 'WEBGL_draw_buffers' ) ? '#extension GL_EXT_draw_buffers : require' : '',
16184 ( extensions.shaderTextureLOD || parameters.envMap ) && rendererExtensions.get( 'EXT_shader_texture_lod' ) ? '#extension GL_EXT_shader_texture_lod : enable' : ''
16185 ];
16186
16187 return chunks.filter( filterEmptyLine ).join( '\n' );
16188
16189}
16190
16191function generateDefines( defines ) {
16192
16193 var chunks = [];
16194
16195 for ( var name in defines ) {
16196
16197 var value = defines[ name ];
16198
16199 if ( value === false ) continue;
16200
16201 chunks.push( '#define ' + name + ' ' + value );
16202
16203 }
16204
16205 return chunks.join( '\n' );
16206
16207}
16208
16209function fetchAttributeLocations( gl, program ) {
16210
16211 var attributes = {};
16212
16213 var n = gl.getProgramParameter( program, gl.ACTIVE_ATTRIBUTES );
16214
16215 for ( var i = 0; i < n; i ++ ) {
16216
16217 var info = gl.getActiveAttrib( program, i );
16218 var name = info.name;
16219
16220 // console.log( 'THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:', name, i );
16221
16222 attributes[ name ] = gl.getAttribLocation( program, name );
16223
16224 }
16225
16226 return attributes;
16227
16228}
16229
16230function filterEmptyLine( string ) {
16231
16232 return string !== '';
16233
16234}
16235
16236function replaceLightNums( string, parameters ) {
16237
16238 return string
16239 .replace( /NUM_DIR_LIGHTS/g, parameters.numDirLights )
16240 .replace( /NUM_SPOT_LIGHTS/g, parameters.numSpotLights )
16241 .replace( /NUM_RECT_AREA_LIGHTS/g, parameters.numRectAreaLights )
16242 .replace( /NUM_POINT_LIGHTS/g, parameters.numPointLights )
16243 .replace( /NUM_HEMI_LIGHTS/g, parameters.numHemiLights );
16244
16245}
16246
16247function replaceClippingPlaneNums( string, parameters ) {
16248
16249 return string
16250 .replace( /NUM_CLIPPING_PLANES/g, parameters.numClippingPlanes )
16251 .replace( /UNION_CLIPPING_PLANES/g, ( parameters.numClippingPlanes - parameters.numClipIntersection ) );
16252
16253}
16254
16255function parseIncludes( string ) {
16256
16257 var pattern = /^[ \t]*#include +<([\w\d.]+)>/gm;
16258
16259 function replace( match, include ) {
16260
16261 var replace = ShaderChunk[ include ];
16262
16263 if ( replace === undefined ) {
16264
16265 throw new Error( 'Can not resolve #include <' + include + '>' );
16266
16267 }
16268
16269 return parseIncludes( replace );
16270
16271 }
16272
16273 return string.replace( pattern, replace );
16274
16275}
16276
16277function unrollLoops( string ) {
16278
16279 var pattern = /#pragma unroll_loop[\s]+?for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g;
16280
16281 function replace( match, start, end, snippet ) {
16282
16283 var unroll = '';
16284
16285 for ( var i = parseInt( start ); i < parseInt( end ); i ++ ) {
16286
16287 unroll += snippet.replace( /\[ i \]/g, '[ ' + i + ' ]' );
16288
16289 }
16290
16291 return unroll;
16292
16293 }
16294
16295 return string.replace( pattern, replace );
16296
16297}
16298
16299function WebGLProgram( renderer, extensions, code, material, shader, parameters ) {
16300
16301 var gl = renderer.context;
16302
16303 var defines = material.defines;
16304
16305 var vertexShader = shader.vertexShader;
16306 var fragmentShader = shader.fragmentShader;
16307
16308 var shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC';
16309
16310 if ( parameters.shadowMapType === PCFShadowMap ) {
16311
16312 shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF';
16313
16314 } else if ( parameters.shadowMapType === PCFSoftShadowMap ) {
16315
16316 shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT';
16317
16318 }
16319
16320 var envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
16321 var envMapModeDefine = 'ENVMAP_MODE_REFLECTION';
16322 var envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
16323
16324 if ( parameters.envMap ) {
16325
16326 switch ( material.envMap.mapping ) {
16327
16328 case CubeReflectionMapping:
16329 case CubeRefractionMapping:
16330 envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
16331 break;
16332
16333 case CubeUVReflectionMapping:
16334 case CubeUVRefractionMapping:
16335 envMapTypeDefine = 'ENVMAP_TYPE_CUBE_UV';
16336 break;
16337
16338 case EquirectangularReflectionMapping:
16339 case EquirectangularRefractionMapping:
16340 envMapTypeDefine = 'ENVMAP_TYPE_EQUIREC';
16341 break;
16342
16343 case SphericalReflectionMapping:
16344 envMapTypeDefine = 'ENVMAP_TYPE_SPHERE';
16345 break;
16346
16347 }
16348
16349 switch ( material.envMap.mapping ) {
16350
16351 case CubeRefractionMapping:
16352 case EquirectangularRefractionMapping:
16353 envMapModeDefine = 'ENVMAP_MODE_REFRACTION';
16354 break;
16355
16356 }
16357
16358 switch ( material.combine ) {
16359
16360 case MultiplyOperation:
16361 envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
16362 break;
16363
16364 case MixOperation:
16365 envMapBlendingDefine = 'ENVMAP_BLENDING_MIX';
16366 break;
16367
16368 case AddOperation:
16369 envMapBlendingDefine = 'ENVMAP_BLENDING_ADD';
16370 break;
16371
16372 }
16373
16374 }
16375
16376 var gammaFactorDefine = ( renderer.gammaFactor > 0 ) ? renderer.gammaFactor : 1.0;
16377
16378 // console.log( 'building new program ' );
16379
16380 //
16381
16382 var customExtensions = generateExtensions( material.extensions, parameters, extensions );
16383
16384 var customDefines = generateDefines( defines );
16385
16386 //
16387
16388 var program = gl.createProgram();
16389
16390 var prefixVertex, prefixFragment;
16391
16392 if ( material.isRawShaderMaterial ) {
16393
16394 prefixVertex = [
16395
16396 customDefines
16397
16398 ].filter( filterEmptyLine ).join( '\n' );
16399
16400 if ( prefixVertex.length > 0 ) {
16401
16402 prefixVertex += '\n';
16403
16404 }
16405
16406 prefixFragment = [
16407
16408 customExtensions,
16409 customDefines
16410
16411 ].filter( filterEmptyLine ).join( '\n' );
16412
16413 if ( prefixFragment.length > 0 ) {
16414
16415 prefixFragment += '\n';
16416
16417 }
16418
16419 } else {
16420
16421 prefixVertex = [
16422
16423 'precision ' + parameters.precision + ' float;',
16424 'precision ' + parameters.precision + ' int;',
16425
16426 '#define SHADER_NAME ' + shader.name,
16427
16428 customDefines,
16429
16430 parameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '',
16431
16432 '#define GAMMA_FACTOR ' + gammaFactorDefine,
16433
16434 '#define MAX_BONES ' + parameters.maxBones,
16435 ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',
16436 ( parameters.useFog && parameters.fogExp ) ? '#define FOG_EXP2' : '',
16437
16438 parameters.map ? '#define USE_MAP' : '',
16439 parameters.envMap ? '#define USE_ENVMAP' : '',
16440 parameters.envMap ? '#define ' + envMapModeDefine : '',
16441 parameters.lightMap ? '#define USE_LIGHTMAP' : '',
16442 parameters.aoMap ? '#define USE_AOMAP' : '',
16443 parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
16444 parameters.bumpMap ? '#define USE_BUMPMAP' : '',
16445 parameters.normalMap ? '#define USE_NORMALMAP' : '',
16446 parameters.displacementMap && parameters.supportsVertexTextures ? '#define USE_DISPLACEMENTMAP' : '',
16447 parameters.specularMap ? '#define USE_SPECULARMAP' : '',
16448 parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
16449 parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
16450 parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
16451 parameters.vertexColors ? '#define USE_COLOR' : '',
16452
16453 parameters.flatShading ? '#define FLAT_SHADED' : '',
16454
16455 parameters.skinning ? '#define USE_SKINNING' : '',
16456 parameters.useVertexTexture ? '#define BONE_TEXTURE' : '',
16457
16458 parameters.morphTargets ? '#define USE_MORPHTARGETS' : '',
16459 parameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '',
16460 parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
16461 parameters.flipSided ? '#define FLIP_SIDED' : '',
16462
16463 parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
16464 parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
16465
16466 parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '',
16467
16468 parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
16469 parameters.logarithmicDepthBuffer && extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
16470
16471 'uniform mat4 modelMatrix;',
16472 'uniform mat4 modelViewMatrix;',
16473 'uniform mat4 projectionMatrix;',
16474 'uniform mat4 viewMatrix;',
16475 'uniform mat3 normalMatrix;',
16476 'uniform vec3 cameraPosition;',
16477
16478 'attribute vec3 position;',
16479 'attribute vec3 normal;',
16480 'attribute vec2 uv;',
16481
16482 '#ifdef USE_COLOR',
16483
16484 ' attribute vec3 color;',
16485
16486 '#endif',
16487
16488 '#ifdef USE_MORPHTARGETS',
16489
16490 ' attribute vec3 morphTarget0;',
16491 ' attribute vec3 morphTarget1;',
16492 ' attribute vec3 morphTarget2;',
16493 ' attribute vec3 morphTarget3;',
16494
16495 ' #ifdef USE_MORPHNORMALS',
16496
16497 ' attribute vec3 morphNormal0;',
16498 ' attribute vec3 morphNormal1;',
16499 ' attribute vec3 morphNormal2;',
16500 ' attribute vec3 morphNormal3;',
16501
16502 ' #else',
16503
16504 ' attribute vec3 morphTarget4;',
16505 ' attribute vec3 morphTarget5;',
16506 ' attribute vec3 morphTarget6;',
16507 ' attribute vec3 morphTarget7;',
16508
16509 ' #endif',
16510
16511 '#endif',
16512
16513 '#ifdef USE_SKINNING',
16514
16515 ' attribute vec4 skinIndex;',
16516 ' attribute vec4 skinWeight;',
16517
16518 '#endif',
16519
16520 '\n'
16521
16522 ].filter( filterEmptyLine ).join( '\n' );
16523
16524 prefixFragment = [
16525
16526 customExtensions,
16527
16528 'precision ' + parameters.precision + ' float;',
16529 'precision ' + parameters.precision + ' int;',
16530
16531 '#define SHADER_NAME ' + shader.name,
16532
16533 customDefines,
16534
16535 parameters.alphaTest ? '#define ALPHATEST ' + parameters.alphaTest : '',
16536
16537 '#define GAMMA_FACTOR ' + gammaFactorDefine,
16538
16539 ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',
16540 ( parameters.useFog && parameters.fogExp ) ? '#define FOG_EXP2' : '',
16541
16542 parameters.map ? '#define USE_MAP' : '',
16543 parameters.envMap ? '#define USE_ENVMAP' : '',
16544 parameters.envMap ? '#define ' + envMapTypeDefine : '',
16545 parameters.envMap ? '#define ' + envMapModeDefine : '',
16546 parameters.envMap ? '#define ' + envMapBlendingDefine : '',
16547 parameters.lightMap ? '#define USE_LIGHTMAP' : '',
16548 parameters.aoMap ? '#define USE_AOMAP' : '',
16549 parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
16550 parameters.bumpMap ? '#define USE_BUMPMAP' : '',
16551 parameters.normalMap ? '#define USE_NORMALMAP' : '',
16552 parameters.specularMap ? '#define USE_SPECULARMAP' : '',
16553 parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
16554 parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
16555 parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
16556 parameters.vertexColors ? '#define USE_COLOR' : '',
16557
16558 parameters.gradientMap ? '#define USE_GRADIENTMAP' : '',
16559
16560 parameters.flatShading ? '#define FLAT_SHADED' : '',
16561
16562 parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
16563 parameters.flipSided ? '#define FLIP_SIDED' : '',
16564
16565 parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
16566 parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
16567
16568 parameters.premultipliedAlpha ? '#define PREMULTIPLIED_ALPHA' : '',
16569
16570 parameters.physicallyCorrectLights ? '#define PHYSICALLY_CORRECT_LIGHTS' : '',
16571
16572 parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
16573 parameters.logarithmicDepthBuffer && extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
16574
16575 parameters.envMap && extensions.get( 'EXT_shader_texture_lod' ) ? '#define TEXTURE_LOD_EXT' : '',
16576
16577 'uniform mat4 viewMatrix;',
16578 'uniform vec3 cameraPosition;',
16579
16580 ( parameters.toneMapping !== NoToneMapping ) ? '#define TONE_MAPPING' : '',
16581 ( parameters.toneMapping !== NoToneMapping ) ? ShaderChunk[ 'tonemapping_pars_fragment' ] : '', // this code is required here because it is used by the toneMapping() function defined below
16582 ( parameters.toneMapping !== NoToneMapping ) ? getToneMappingFunction( 'toneMapping', parameters.toneMapping ) : '',
16583
16584 parameters.dithering ? '#define DITHERING' : '',
16585
16586 ( parameters.outputEncoding || parameters.mapEncoding || parameters.envMapEncoding || parameters.emissiveMapEncoding ) ? ShaderChunk[ 'encodings_pars_fragment' ] : '', // this code is required here because it is used by the various encoding/decoding function defined below
16587 parameters.mapEncoding ? getTexelDecodingFunction( 'mapTexelToLinear', parameters.mapEncoding ) : '',
16588 parameters.envMapEncoding ? getTexelDecodingFunction( 'envMapTexelToLinear', parameters.envMapEncoding ) : '',
16589 parameters.emissiveMapEncoding ? getTexelDecodingFunction( 'emissiveMapTexelToLinear', parameters.emissiveMapEncoding ) : '',
16590 parameters.outputEncoding ? getTexelEncodingFunction( 'linearToOutputTexel', parameters.outputEncoding ) : '',
16591
16592 parameters.depthPacking ? '#define DEPTH_PACKING ' + material.depthPacking : '',
16593
16594 '\n'
16595
16596 ].filter( filterEmptyLine ).join( '\n' );
16597
16598 }
16599
16600 vertexShader = parseIncludes( vertexShader );
16601 vertexShader = replaceLightNums( vertexShader, parameters );
16602 vertexShader = replaceClippingPlaneNums( vertexShader, parameters );
16603
16604 fragmentShader = parseIncludes( fragmentShader );
16605 fragmentShader = replaceLightNums( fragmentShader, parameters );
16606 fragmentShader = replaceClippingPlaneNums( fragmentShader, parameters );
16607
16608 vertexShader = unrollLoops( vertexShader );
16609 fragmentShader = unrollLoops( fragmentShader );
16610
16611 var vertexGlsl = prefixVertex + vertexShader;
16612 var fragmentGlsl = prefixFragment + fragmentShader;
16613
16614 // console.log( '*VERTEX*', vertexGlsl );
16615 // console.log( '*FRAGMENT*', fragmentGlsl );
16616
16617 var glVertexShader = WebGLShader( gl, gl.VERTEX_SHADER, vertexGlsl );
16618 var glFragmentShader = WebGLShader( gl, gl.FRAGMENT_SHADER, fragmentGlsl );
16619
16620 gl.attachShader( program, glVertexShader );
16621 gl.attachShader( program, glFragmentShader );
16622
16623 // Force a particular attribute to index 0.
16624
16625 if ( material.index0AttributeName !== undefined ) {
16626
16627 gl.bindAttribLocation( program, 0, material.index0AttributeName );
16628
16629 } else if ( parameters.morphTargets === true ) {
16630
16631 // programs with morphTargets displace position out of attribute 0
16632 gl.bindAttribLocation( program, 0, 'position' );
16633
16634 }
16635
16636 gl.linkProgram( program );
16637
16638 var programLog = gl.getProgramInfoLog( program ).trim();
16639 var vertexLog = gl.getShaderInfoLog( glVertexShader ).trim();
16640 var fragmentLog = gl.getShaderInfoLog( glFragmentShader ).trim();
16641
16642 var runnable = true;
16643 var haveDiagnostics = true;
16644
16645 // console.log( '**VERTEX**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( glVertexShader ) );
16646 // console.log( '**FRAGMENT**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( glFragmentShader ) );
16647
16648 if ( gl.getProgramParameter( program, gl.LINK_STATUS ) === false ) {
16649
16650 runnable = false;
16651
16652 console.error( 'THREE.WebGLProgram: shader error: ', gl.getError(), 'gl.VALIDATE_STATUS', gl.getProgramParameter( program, gl.VALIDATE_STATUS ), 'gl.getProgramInfoLog', programLog, vertexLog, fragmentLog );
16653
16654 } else if ( programLog !== '' ) {
16655
16656 console.warn( 'THREE.WebGLProgram: gl.getProgramInfoLog()', programLog );
16657
16658 } else if ( vertexLog === '' || fragmentLog === '' ) {
16659
16660 haveDiagnostics = false;
16661
16662 }
16663
16664 if ( haveDiagnostics ) {
16665
16666 this.diagnostics = {
16667
16668 runnable: runnable,
16669 material: material,
16670
16671 programLog: programLog,
16672
16673 vertexShader: {
16674
16675 log: vertexLog,
16676 prefix: prefixVertex
16677
16678 },
16679
16680 fragmentShader: {
16681
16682 log: fragmentLog,
16683 prefix: prefixFragment
16684
16685 }
16686
16687 };
16688
16689 }
16690
16691 // clean up
16692
16693 gl.deleteShader( glVertexShader );
16694 gl.deleteShader( glFragmentShader );
16695
16696 // set up caching for uniform locations
16697
16698 var cachedUniforms;
16699
16700 this.getUniforms = function () {
16701
16702 if ( cachedUniforms === undefined ) {
16703
16704 cachedUniforms = new WebGLUniforms( gl, program, renderer );
16705
16706 }
16707
16708 return cachedUniforms;
16709
16710 };
16711
16712 // set up caching for attribute locations
16713
16714 var cachedAttributes;
16715
16716 this.getAttributes = function () {
16717
16718 if ( cachedAttributes === undefined ) {
16719
16720 cachedAttributes = fetchAttributeLocations( gl, program );
16721
16722 }
16723
16724 return cachedAttributes;
16725
16726 };
16727
16728 // free resource
16729
16730 this.destroy = function () {
16731
16732 gl.deleteProgram( program );
16733 this.program = undefined;
16734
16735 };
16736
16737 // DEPRECATED
16738
16739 Object.defineProperties( this, {
16740
16741 uniforms: {
16742 get: function () {
16743
16744 console.warn( 'THREE.WebGLProgram: .uniforms is now .getUniforms().' );
16745 return this.getUniforms();
16746
16747 }
16748 },
16749
16750 attributes: {
16751 get: function () {
16752
16753 console.warn( 'THREE.WebGLProgram: .attributes is now .getAttributes().' );
16754 return this.getAttributes();
16755
16756 }
16757 }
16758
16759 } );
16760
16761
16762 //
16763
16764 this.name = shader.name;
16765 this.id = programIdCount ++;
16766 this.code = code;
16767 this.usedTimes = 1;
16768 this.program = program;
16769 this.vertexShader = glVertexShader;
16770 this.fragmentShader = glFragmentShader;
16771
16772 return this;
16773
16774}
16775
16776/**
16777 * @author mrdoob / http://mrdoob.com/
16778 */
16779
16780function WebGLPrograms( renderer, extensions, capabilities ) {
16781
16782 var programs = [];
16783
16784 var shaderIDs = {
16785 MeshDepthMaterial: 'depth',
16786 MeshDistanceMaterial: 'distanceRGBA',
16787 MeshNormalMaterial: 'normal',
16788 MeshBasicMaterial: 'basic',
16789 MeshLambertMaterial: 'lambert',
16790 MeshPhongMaterial: 'phong',
16791 MeshToonMaterial: 'phong',
16792 MeshStandardMaterial: 'physical',
16793 MeshPhysicalMaterial: 'physical',
16794 LineBasicMaterial: 'basic',
16795 LineDashedMaterial: 'dashed',
16796 PointsMaterial: 'points',
16797 ShadowMaterial: 'shadow'
16798 };
16799
16800 var parameterNames = [
16801 "precision", "supportsVertexTextures", "map", "mapEncoding", "envMap", "envMapMode", "envMapEncoding",
16802 "lightMap", "aoMap", "emissiveMap", "emissiveMapEncoding", "bumpMap", "normalMap", "displacementMap", "specularMap",
16803 "roughnessMap", "metalnessMap", "gradientMap",
16804 "alphaMap", "combine", "vertexColors", "fog", "useFog", "fogExp",
16805 "flatShading", "sizeAttenuation", "logarithmicDepthBuffer", "skinning",
16806 "maxBones", "useVertexTexture", "morphTargets", "morphNormals",
16807 "maxMorphTargets", "maxMorphNormals", "premultipliedAlpha",
16808 "numDirLights", "numPointLights", "numSpotLights", "numHemiLights", "numRectAreaLights",
16809 "shadowMapEnabled", "shadowMapType", "toneMapping", 'physicallyCorrectLights',
16810 "alphaTest", "doubleSided", "flipSided", "numClippingPlanes", "numClipIntersection", "depthPacking", "dithering"
16811 ];
16812
16813
16814 function allocateBones( object ) {
16815
16816 var skeleton = object.skeleton;
16817 var bones = skeleton.bones;
16818
16819 if ( capabilities.floatVertexTextures ) {
16820
16821 return 1024;
16822
16823 } else {
16824
16825 // default for when object is not specified
16826 // ( for example when prebuilding shader to be used with multiple objects )
16827 //
16828 // - leave some extra space for other uniforms
16829 // - limit here is ANGLE's 254 max uniform vectors
16830 // (up to 54 should be safe)
16831
16832 var nVertexUniforms = capabilities.maxVertexUniforms;
16833 var nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 );
16834
16835 var maxBones = Math.min( nVertexMatrices, bones.length );
16836
16837 if ( maxBones < bones.length ) {
16838
16839 console.warn( 'THREE.WebGLRenderer: Skeleton has ' + bones.length + ' bones. This GPU supports ' + maxBones + '.' );
16840 return 0;
16841
16842 }
16843
16844 return maxBones;
16845
16846 }
16847
16848 }
16849
16850 function getTextureEncodingFromMap( map, gammaOverrideLinear ) {
16851
16852 var encoding;
16853
16854 if ( ! map ) {
16855
16856 encoding = LinearEncoding;
16857
16858 } else if ( map.isTexture ) {
16859
16860 encoding = map.encoding;
16861
16862 } else if ( map.isWebGLRenderTarget ) {
16863
16864 console.warn( "THREE.WebGLPrograms.getTextureEncodingFromMap: don't use render targets as textures. Use their .texture property instead." );
16865 encoding = map.texture.encoding;
16866
16867 }
16868
16869 // add backwards compatibility for WebGLRenderer.gammaInput/gammaOutput parameter, should probably be removed at some point.
16870 if ( encoding === LinearEncoding && gammaOverrideLinear ) {
16871
16872 encoding = GammaEncoding;
16873
16874 }
16875
16876 return encoding;
16877
16878 }
16879
16880 this.getParameters = function ( material, lights, shadows, fog, nClipPlanes, nClipIntersection, object ) {
16881
16882 var shaderID = shaderIDs[ material.type ];
16883
16884 // heuristics to create shader parameters according to lights in the scene
16885 // (not to blow over maxLights budget)
16886
16887 var maxBones = object.isSkinnedMesh ? allocateBones( object ) : 0;
16888 var precision = capabilities.precision;
16889
16890 if ( material.precision !== null ) {
16891
16892 precision = capabilities.getMaxPrecision( material.precision );
16893
16894 if ( precision !== material.precision ) {
16895
16896 console.warn( 'THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.' );
16897
16898 }
16899
16900 }
16901
16902 var currentRenderTarget = renderer.getRenderTarget();
16903
16904 var parameters = {
16905
16906 shaderID: shaderID,
16907
16908 precision: precision,
16909 supportsVertexTextures: capabilities.vertexTextures,
16910 outputEncoding: getTextureEncodingFromMap( ( ! currentRenderTarget ) ? null : currentRenderTarget.texture, renderer.gammaOutput ),
16911 map: !! material.map,
16912 mapEncoding: getTextureEncodingFromMap( material.map, renderer.gammaInput ),
16913 envMap: !! material.envMap,
16914 envMapMode: material.envMap && material.envMap.mapping,
16915 envMapEncoding: getTextureEncodingFromMap( material.envMap, renderer.gammaInput ),
16916 envMapCubeUV: ( !! material.envMap ) && ( ( material.envMap.mapping === CubeUVReflectionMapping ) || ( material.envMap.mapping === CubeUVRefractionMapping ) ),
16917 lightMap: !! material.lightMap,
16918 aoMap: !! material.aoMap,
16919 emissiveMap: !! material.emissiveMap,
16920 emissiveMapEncoding: getTextureEncodingFromMap( material.emissiveMap, renderer.gammaInput ),
16921 bumpMap: !! material.bumpMap,
16922 normalMap: !! material.normalMap,
16923 displacementMap: !! material.displacementMap,
16924 roughnessMap: !! material.roughnessMap,
16925 metalnessMap: !! material.metalnessMap,
16926 specularMap: !! material.specularMap,
16927 alphaMap: !! material.alphaMap,
16928
16929 gradientMap: !! material.gradientMap,
16930
16931 combine: material.combine,
16932
16933 vertexColors: material.vertexColors,
16934
16935 fog: !! fog,
16936 useFog: material.fog,
16937 fogExp: ( fog && fog.isFogExp2 ),
16938
16939 flatShading: material.flatShading,
16940
16941 sizeAttenuation: material.sizeAttenuation,
16942 logarithmicDepthBuffer: capabilities.logarithmicDepthBuffer,
16943
16944 skinning: material.skinning && maxBones > 0,
16945 maxBones: maxBones,
16946 useVertexTexture: capabilities.floatVertexTextures,
16947
16948 morphTargets: material.morphTargets,
16949 morphNormals: material.morphNormals,
16950 maxMorphTargets: renderer.maxMorphTargets,
16951 maxMorphNormals: renderer.maxMorphNormals,
16952
16953 numDirLights: lights.directional.length,
16954 numPointLights: lights.point.length,
16955 numSpotLights: lights.spot.length,
16956 numRectAreaLights: lights.rectArea.length,
16957 numHemiLights: lights.hemi.length,
16958
16959 numClippingPlanes: nClipPlanes,
16960 numClipIntersection: nClipIntersection,
16961
16962 dithering: material.dithering,
16963
16964 shadowMapEnabled: renderer.shadowMap.enabled && object.receiveShadow && shadows.length > 0,
16965 shadowMapType: renderer.shadowMap.type,
16966
16967 toneMapping: renderer.toneMapping,
16968 physicallyCorrectLights: renderer.physicallyCorrectLights,
16969
16970 premultipliedAlpha: material.premultipliedAlpha,
16971
16972 alphaTest: material.alphaTest,
16973 doubleSided: material.side === DoubleSide,
16974 flipSided: material.side === BackSide,
16975
16976 depthPacking: ( material.depthPacking !== undefined ) ? material.depthPacking : false
16977
16978 };
16979
16980 return parameters;
16981
16982 };
16983
16984 this.getProgramCode = function ( material, parameters ) {
16985
16986 var array = [];
16987
16988 if ( parameters.shaderID ) {
16989
16990 array.push( parameters.shaderID );
16991
16992 } else {
16993
16994 array.push( material.fragmentShader );
16995 array.push( material.vertexShader );
16996
16997 }
16998
16999 if ( material.defines !== undefined ) {
17000
17001 for ( var name in material.defines ) {
17002
17003 array.push( name );
17004 array.push( material.defines[ name ] );
17005
17006 }
17007
17008 }
17009
17010 for ( var i = 0; i < parameterNames.length; i ++ ) {
17011
17012 array.push( parameters[ parameterNames[ i ] ] );
17013
17014 }
17015
17016 array.push( material.onBeforeCompile.toString() );
17017
17018 array.push( renderer.gammaOutput );
17019
17020 return array.join();
17021
17022 };
17023
17024 this.acquireProgram = function ( material, shader, parameters, code ) {
17025
17026 var program;
17027
17028 // Check if code has been already compiled
17029 for ( var p = 0, pl = programs.length; p < pl; p ++ ) {
17030
17031 var programInfo = programs[ p ];
17032
17033 if ( programInfo.code === code ) {
17034
17035 program = programInfo;
17036 ++ program.usedTimes;
17037
17038 break;
17039
17040 }
17041
17042 }
17043
17044 if ( program === undefined ) {
17045
17046 program = new WebGLProgram( renderer, extensions, code, material, shader, parameters );
17047 programs.push( program );
17048
17049 }
17050
17051 return program;
17052
17053 };
17054
17055 this.releaseProgram = function ( program ) {
17056
17057 if ( -- program.usedTimes === 0 ) {
17058
17059 // Remove from unordered set
17060 var i = programs.indexOf( program );
17061 programs[ i ] = programs[ programs.length - 1 ];
17062 programs.pop();
17063
17064 // Free WebGL resources
17065 program.destroy();
17066
17067 }
17068
17069 };
17070
17071 // Exposed for resource monitoring & error feedback via renderer.info:
17072 this.programs = programs;
17073
17074}
17075
17076/**
17077 * @author fordacious / fordacious.github.io
17078 */
17079
17080function WebGLProperties() {
17081
17082 var properties = new WeakMap();
17083
17084 function get( object ) {
17085
17086 var map = properties.get( object );
17087
17088 if ( map === undefined ) {
17089
17090 map = {};
17091 properties.set( object, map );
17092
17093 }
17094
17095 return map;
17096
17097 }
17098
17099 function remove( object ) {
17100
17101 properties.delete( object );
17102
17103 }
17104
17105 function update( object, key, value ) {
17106
17107 properties.get( object )[ key ] = value;
17108
17109 }
17110
17111 function dispose() {
17112
17113 properties = new WeakMap();
17114
17115 }
17116
17117 return {
17118 get: get,
17119 remove: remove,
17120 update: update,
17121 dispose: dispose
17122 };
17123
17124}
17125
17126/**
17127 * @author mrdoob / http://mrdoob.com/
17128 */
17129
17130function painterSortStable( a, b ) {
17131
17132 if ( a.renderOrder !== b.renderOrder ) {
17133
17134 return a.renderOrder - b.renderOrder;
17135
17136 } else if ( a.program && b.program && a.program !== b.program ) {
17137
17138 return a.program.id - b.program.id;
17139
17140 } else if ( a.material.id !== b.material.id ) {
17141
17142 return a.material.id - b.material.id;
17143
17144 } else if ( a.z !== b.z ) {
17145
17146 return a.z - b.z;
17147
17148 } else {
17149
17150 return a.id - b.id;
17151
17152 }
17153
17154}
17155
17156function reversePainterSortStable( a, b ) {
17157
17158 if ( a.renderOrder !== b.renderOrder ) {
17159
17160 return a.renderOrder - b.renderOrder;
17161
17162 } if ( a.z !== b.z ) {
17163
17164 return b.z - a.z;
17165
17166 } else {
17167
17168 return a.id - b.id;
17169
17170 }
17171
17172}
17173
17174function WebGLRenderList() {
17175
17176 var renderItems = [];
17177 var renderItemsIndex = 0;
17178
17179 var opaque = [];
17180 var transparent = [];
17181
17182 function init() {
17183
17184 renderItemsIndex = 0;
17185
17186 opaque.length = 0;
17187 transparent.length = 0;
17188
17189 }
17190
17191 function push( object, geometry, material, z, group ) {
17192
17193 var renderItem = renderItems[ renderItemsIndex ];
17194
17195 if ( renderItem === undefined ) {
17196
17197 renderItem = {
17198 id: object.id,
17199 object: object,
17200 geometry: geometry,
17201 material: material,
17202 program: material.program,
17203 renderOrder: object.renderOrder,
17204 z: z,
17205 group: group
17206 };
17207
17208 renderItems[ renderItemsIndex ] = renderItem;
17209
17210 } else {
17211
17212 renderItem.id = object.id;
17213 renderItem.object = object;
17214 renderItem.geometry = geometry;
17215 renderItem.material = material;
17216 renderItem.program = material.program;
17217 renderItem.renderOrder = object.renderOrder;
17218 renderItem.z = z;
17219 renderItem.group = group;
17220
17221 }
17222
17223 ( material.transparent === true ? transparent : opaque ).push( renderItem );
17224
17225 renderItemsIndex ++;
17226
17227 }
17228
17229 function sort() {
17230
17231 if ( opaque.length > 1 ) opaque.sort( painterSortStable );
17232 if ( transparent.length > 1 ) transparent.sort( reversePainterSortStable );
17233
17234 }
17235
17236 return {
17237 opaque: opaque,
17238 transparent: transparent,
17239
17240 init: init,
17241 push: push,
17242
17243 sort: sort
17244 };
17245
17246}
17247
17248function WebGLRenderLists() {
17249
17250 var lists = {};
17251
17252 function get( scene, camera ) {
17253
17254 var hash = scene.id + ',' + camera.id;
17255 var list = lists[ hash ];
17256
17257 if ( list === undefined ) {
17258
17259 // console.log( 'THREE.WebGLRenderLists:', hash );
17260
17261 list = new WebGLRenderList();
17262 lists[ hash ] = list;
17263
17264 }
17265
17266 return list;
17267
17268 }
17269
17270 function dispose() {
17271
17272 lists = {};
17273
17274 }
17275
17276 return {
17277 get: get,
17278 dispose: dispose
17279 };
17280
17281}
17282
17283/**
17284 * @author mrdoob / http://mrdoob.com/
17285 */
17286
17287function UniformsCache() {
17288
17289 var lights = {};
17290
17291 return {
17292
17293 get: function ( light ) {
17294
17295 if ( lights[ light.id ] !== undefined ) {
17296
17297 return lights[ light.id ];
17298
17299 }
17300
17301 var uniforms;
17302
17303 switch ( light.type ) {
17304
17305 case 'DirectionalLight':
17306 uniforms = {
17307 direction: new Vector3(),
17308 color: new Color(),
17309
17310 shadow: false,
17311 shadowBias: 0,
17312 shadowRadius: 1,
17313 shadowMapSize: new Vector2()
17314 };
17315 break;
17316
17317 case 'SpotLight':
17318 uniforms = {
17319 position: new Vector3(),
17320 direction: new Vector3(),
17321 color: new Color(),
17322 distance: 0,
17323 coneCos: 0,
17324 penumbraCos: 0,
17325 decay: 0,
17326
17327 shadow: false,
17328 shadowBias: 0,
17329 shadowRadius: 1,
17330 shadowMapSize: new Vector2()
17331 };
17332 break;
17333
17334 case 'PointLight':
17335 uniforms = {
17336 position: new Vector3(),
17337 color: new Color(),
17338 distance: 0,
17339 decay: 0,
17340
17341 shadow: false,
17342 shadowBias: 0,
17343 shadowRadius: 1,
17344 shadowMapSize: new Vector2(),
17345 shadowCameraNear: 1,
17346 shadowCameraFar: 1000
17347 };
17348 break;
17349
17350 case 'HemisphereLight':
17351 uniforms = {
17352 direction: new Vector3(),
17353 skyColor: new Color(),
17354 groundColor: new Color()
17355 };
17356 break;
17357
17358 case 'RectAreaLight':
17359 uniforms = {
17360 color: new Color(),
17361 position: new Vector3(),
17362 halfWidth: new Vector3(),
17363 halfHeight: new Vector3()
17364 // TODO (abelnation): set RectAreaLight shadow uniforms
17365 };
17366 break;
17367
17368 }
17369
17370 lights[ light.id ] = uniforms;
17371
17372 return uniforms;
17373
17374 }
17375
17376 };
17377
17378}
17379
17380var count = 0;
17381
17382function WebGLLights() {
17383
17384 var cache = new UniformsCache();
17385
17386 var state = {
17387
17388 id: count ++,
17389
17390 hash: '',
17391
17392 ambient: [ 0, 0, 0 ],
17393 directional: [],
17394 directionalShadowMap: [],
17395 directionalShadowMatrix: [],
17396 spot: [],
17397 spotShadowMap: [],
17398 spotShadowMatrix: [],
17399 rectArea: [],
17400 point: [],
17401 pointShadowMap: [],
17402 pointShadowMatrix: [],
17403 hemi: []
17404
17405 };
17406
17407 var vector3 = new Vector3();
17408 var matrix4 = new Matrix4();
17409 var matrix42 = new Matrix4();
17410
17411 function setup( lights, shadows, camera ) {
17412
17413 var r = 0, g = 0, b = 0;
17414
17415 var directionalLength = 0;
17416 var pointLength = 0;
17417 var spotLength = 0;
17418 var rectAreaLength = 0;
17419 var hemiLength = 0;
17420
17421 var viewMatrix = camera.matrixWorldInverse;
17422
17423 for ( var i = 0, l = lights.length; i < l; i ++ ) {
17424
17425 var light = lights[ i ];
17426
17427 var color = light.color;
17428 var intensity = light.intensity;
17429 var distance = light.distance;
17430
17431 var shadowMap = ( light.shadow && light.shadow.map ) ? light.shadow.map.texture : null;
17432
17433 if ( light.isAmbientLight ) {
17434
17435 r += color.r * intensity;
17436 g += color.g * intensity;
17437 b += color.b * intensity;
17438
17439 } else if ( light.isDirectionalLight ) {
17440
17441 var uniforms = cache.get( light );
17442
17443 uniforms.color.copy( light.color ).multiplyScalar( light.intensity );
17444 uniforms.direction.setFromMatrixPosition( light.matrixWorld );
17445 vector3.setFromMatrixPosition( light.target.matrixWorld );
17446 uniforms.direction.sub( vector3 );
17447 uniforms.direction.transformDirection( viewMatrix );
17448
17449 uniforms.shadow = light.castShadow;
17450
17451 if ( light.castShadow ) {
17452
17453 var shadow = light.shadow;
17454
17455 uniforms.shadowBias = shadow.bias;
17456 uniforms.shadowRadius = shadow.radius;
17457 uniforms.shadowMapSize = shadow.mapSize;
17458
17459 }
17460
17461 state.directionalShadowMap[ directionalLength ] = shadowMap;
17462 state.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix;
17463 state.directional[ directionalLength ] = uniforms;
17464
17465 directionalLength ++;
17466
17467 } else if ( light.isSpotLight ) {
17468
17469 var uniforms = cache.get( light );
17470
17471 uniforms.position.setFromMatrixPosition( light.matrixWorld );
17472 uniforms.position.applyMatrix4( viewMatrix );
17473
17474 uniforms.color.copy( color ).multiplyScalar( intensity );
17475 uniforms.distance = distance;
17476
17477 uniforms.direction.setFromMatrixPosition( light.matrixWorld );
17478 vector3.setFromMatrixPosition( light.target.matrixWorld );
17479 uniforms.direction.sub( vector3 );
17480 uniforms.direction.transformDirection( viewMatrix );
17481
17482 uniforms.coneCos = Math.cos( light.angle );
17483 uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) );
17484 uniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay;
17485
17486 uniforms.shadow = light.castShadow;
17487
17488 if ( light.castShadow ) {
17489
17490 var shadow = light.shadow;
17491
17492 uniforms.shadowBias = shadow.bias;
17493 uniforms.shadowRadius = shadow.radius;
17494 uniforms.shadowMapSize = shadow.mapSize;
17495
17496 }
17497
17498 state.spotShadowMap[ spotLength ] = shadowMap;
17499 state.spotShadowMatrix[ spotLength ] = light.shadow.matrix;
17500 state.spot[ spotLength ] = uniforms;
17501
17502 spotLength ++;
17503
17504 } else if ( light.isRectAreaLight ) {
17505
17506 var uniforms = cache.get( light );
17507
17508 // (a) intensity is the total visible light emitted
17509 //uniforms.color.copy( color ).multiplyScalar( intensity / ( light.width * light.height * Math.PI ) );
17510
17511 // (b) intensity is the brightness of the light
17512 uniforms.color.copy( color ).multiplyScalar( intensity );
17513
17514 uniforms.position.setFromMatrixPosition( light.matrixWorld );
17515 uniforms.position.applyMatrix4( viewMatrix );
17516
17517 // extract local rotation of light to derive width/height half vectors
17518 matrix42.identity();
17519 matrix4.copy( light.matrixWorld );
17520 matrix4.premultiply( viewMatrix );
17521 matrix42.extractRotation( matrix4 );
17522
17523 uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 );
17524 uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 );
17525
17526 uniforms.halfWidth.applyMatrix4( matrix42 );
17527 uniforms.halfHeight.applyMatrix4( matrix42 );
17528
17529 // TODO (abelnation): RectAreaLight distance?
17530 // uniforms.distance = distance;
17531
17532 state.rectArea[ rectAreaLength ] = uniforms;
17533
17534 rectAreaLength ++;
17535
17536 } else if ( light.isPointLight ) {
17537
17538 var uniforms = cache.get( light );
17539
17540 uniforms.position.setFromMatrixPosition( light.matrixWorld );
17541 uniforms.position.applyMatrix4( viewMatrix );
17542
17543 uniforms.color.copy( light.color ).multiplyScalar( light.intensity );
17544 uniforms.distance = light.distance;
17545 uniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay;
17546
17547 uniforms.shadow = light.castShadow;
17548
17549 if ( light.castShadow ) {
17550
17551 var shadow = light.shadow;
17552
17553 uniforms.shadowBias = shadow.bias;
17554 uniforms.shadowRadius = shadow.radius;
17555 uniforms.shadowMapSize = shadow.mapSize;
17556 uniforms.shadowCameraNear = shadow.camera.near;
17557 uniforms.shadowCameraFar = shadow.camera.far;
17558
17559 }
17560
17561 state.pointShadowMap[ pointLength ] = shadowMap;
17562 state.pointShadowMatrix[ pointLength ] = light.shadow.matrix;
17563 state.point[ pointLength ] = uniforms;
17564
17565 pointLength ++;
17566
17567 } else if ( light.isHemisphereLight ) {
17568
17569 var uniforms = cache.get( light );
17570
17571 uniforms.direction.setFromMatrixPosition( light.matrixWorld );
17572 uniforms.direction.transformDirection( viewMatrix );
17573 uniforms.direction.normalize();
17574
17575 uniforms.skyColor.copy( light.color ).multiplyScalar( intensity );
17576 uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity );
17577
17578 state.hemi[ hemiLength ] = uniforms;
17579
17580 hemiLength ++;
17581
17582 }
17583
17584 }
17585
17586 state.ambient[ 0 ] = r;
17587 state.ambient[ 1 ] = g;
17588 state.ambient[ 2 ] = b;
17589
17590 state.directional.length = directionalLength;
17591 state.spot.length = spotLength;
17592 state.rectArea.length = rectAreaLength;
17593 state.point.length = pointLength;
17594 state.hemi.length = hemiLength;
17595
17596 state.hash = state.id + ',' + directionalLength + ',' + pointLength + ',' + spotLength + ',' + rectAreaLength + ',' + hemiLength + ',' + shadows.length;
17597
17598 }
17599
17600 return {
17601 setup: setup,
17602 state: state
17603 };
17604
17605}
17606
17607/**
17608 * @author Mugen87 / https://github.com/Mugen87
17609 */
17610
17611function WebGLRenderState() {
17612
17613 var lights = new WebGLLights();
17614
17615 var lightsArray = [];
17616 var shadowsArray = [];
17617 var spritesArray = [];
17618
17619 function init() {
17620
17621 lightsArray.length = 0;
17622 shadowsArray.length = 0;
17623 spritesArray.length = 0;
17624
17625 }
17626
17627 function pushLight( light ) {
17628
17629 lightsArray.push( light );
17630
17631 }
17632
17633 function pushShadow( shadowLight ) {
17634
17635 shadowsArray.push( shadowLight );
17636
17637 }
17638
17639 function pushSprite( shadowLight ) {
17640
17641 spritesArray.push( shadowLight );
17642
17643 }
17644
17645 function setupLights( camera ) {
17646
17647 lights.setup( lightsArray, shadowsArray, camera );
17648
17649 }
17650
17651 var state = {
17652 lightsArray: lightsArray,
17653 shadowsArray: shadowsArray,
17654 spritesArray: spritesArray,
17655
17656 lights: lights
17657 };
17658
17659 return {
17660 init: init,
17661 state: state,
17662 setupLights: setupLights,
17663
17664 pushLight: pushLight,
17665 pushShadow: pushShadow,
17666 pushSprite: pushSprite
17667 };
17668
17669}
17670
17671function WebGLRenderStates() {
17672
17673 var renderStates = {};
17674
17675 function get( scene, camera ) {
17676
17677 var hash = scene.id + ',' + camera.id;
17678
17679 var renderState = renderStates[ hash ];
17680
17681 if ( renderState === undefined ) {
17682
17683 renderState = new WebGLRenderState();
17684 renderStates[ hash ] = renderState;
17685
17686 }
17687
17688 return renderState;
17689
17690 }
17691
17692 function dispose() {
17693
17694 renderStates = {};
17695
17696 }
17697
17698 return {
17699 get: get,
17700 dispose: dispose
17701 };
17702
17703}
17704
17705/**
17706 * @author mrdoob / http://mrdoob.com/
17707 * @author alteredq / http://alteredqualia.com/
17708 * @author bhouston / https://clara.io
17709 * @author WestLangley / http://github.com/WestLangley
17710 *
17711 * parameters = {
17712 *
17713 * opacity: <float>,
17714 *
17715 * map: new THREE.Texture( <Image> ),
17716 *
17717 * alphaMap: new THREE.Texture( <Image> ),
17718 *
17719 * displacementMap: new THREE.Texture( <Image> ),
17720 * displacementScale: <float>,
17721 * displacementBias: <float>,
17722 *
17723 * wireframe: <boolean>,
17724 * wireframeLinewidth: <float>
17725 * }
17726 */
17727
17728function MeshDepthMaterial( parameters ) {
17729
17730 Material.call( this );
17731
17732 this.type = 'MeshDepthMaterial';
17733
17734 this.depthPacking = BasicDepthPacking;
17735
17736 this.skinning = false;
17737 this.morphTargets = false;
17738
17739 this.map = null;
17740
17741 this.alphaMap = null;
17742
17743 this.displacementMap = null;
17744 this.displacementScale = 1;
17745 this.displacementBias = 0;
17746
17747 this.wireframe = false;
17748 this.wireframeLinewidth = 1;
17749
17750 this.fog = false;
17751 this.lights = false;
17752
17753 this.setValues( parameters );
17754
17755}
17756
17757MeshDepthMaterial.prototype = Object.create( Material.prototype );
17758MeshDepthMaterial.prototype.constructor = MeshDepthMaterial;
17759
17760MeshDepthMaterial.prototype.isMeshDepthMaterial = true;
17761
17762MeshDepthMaterial.prototype.copy = function ( source ) {
17763
17764 Material.prototype.copy.call( this, source );
17765
17766 this.depthPacking = source.depthPacking;
17767
17768 this.skinning = source.skinning;
17769 this.morphTargets = source.morphTargets;
17770
17771 this.map = source.map;
17772
17773 this.alphaMap = source.alphaMap;
17774
17775 this.displacementMap = source.displacementMap;
17776 this.displacementScale = source.displacementScale;
17777 this.displacementBias = source.displacementBias;
17778
17779 this.wireframe = source.wireframe;
17780 this.wireframeLinewidth = source.wireframeLinewidth;
17781
17782 return this;
17783
17784};
17785
17786/**
17787 * @author WestLangley / http://github.com/WestLangley
17788 *
17789 * parameters = {
17790 *
17791 * referencePosition: <float>,
17792 * nearDistance: <float>,
17793 * farDistance: <float>,
17794 *
17795 * skinning: <bool>,
17796 * morphTargets: <bool>,
17797 *
17798 * map: new THREE.Texture( <Image> ),
17799 *
17800 * alphaMap: new THREE.Texture( <Image> ),
17801 *
17802 * displacementMap: new THREE.Texture( <Image> ),
17803 * displacementScale: <float>,
17804 * displacementBias: <float>
17805 *
17806 * }
17807 */
17808
17809function MeshDistanceMaterial( parameters ) {
17810
17811 Material.call( this );
17812
17813 this.type = 'MeshDistanceMaterial';
17814
17815 this.referencePosition = new Vector3();
17816 this.nearDistance = 1;
17817 this.farDistance = 1000;
17818
17819 this.skinning = false;
17820 this.morphTargets = false;
17821
17822 this.map = null;
17823
17824 this.alphaMap = null;
17825
17826 this.displacementMap = null;
17827 this.displacementScale = 1;
17828 this.displacementBias = 0;
17829
17830 this.fog = false;
17831 this.lights = false;
17832
17833 this.setValues( parameters );
17834
17835}
17836
17837MeshDistanceMaterial.prototype = Object.create( Material.prototype );
17838MeshDistanceMaterial.prototype.constructor = MeshDistanceMaterial;
17839
17840MeshDistanceMaterial.prototype.isMeshDistanceMaterial = true;
17841
17842MeshDistanceMaterial.prototype.copy = function ( source ) {
17843
17844 Material.prototype.copy.call( this, source );
17845
17846 this.referencePosition.copy( source.referencePosition );
17847 this.nearDistance = source.nearDistance;
17848 this.farDistance = source.farDistance;
17849
17850 this.skinning = source.skinning;
17851 this.morphTargets = source.morphTargets;
17852
17853 this.map = source.map;
17854
17855 this.alphaMap = source.alphaMap;
17856
17857 this.displacementMap = source.displacementMap;
17858 this.displacementScale = source.displacementScale;
17859 this.displacementBias = source.displacementBias;
17860
17861 return this;
17862
17863};
17864
17865/**
17866 * @author alteredq / http://alteredqualia.com/
17867 * @author mrdoob / http://mrdoob.com/
17868 */
17869
17870function WebGLShadowMap( _renderer, _objects, maxTextureSize ) {
17871
17872 var _frustum = new Frustum(),
17873 _projScreenMatrix = new Matrix4(),
17874
17875 _shadowMapSize = new Vector2(),
17876 _maxShadowMapSize = new Vector2( maxTextureSize, maxTextureSize ),
17877
17878 _lookTarget = new Vector3(),
17879 _lightPositionWorld = new Vector3(),
17880
17881 _MorphingFlag = 1,
17882 _SkinningFlag = 2,
17883
17884 _NumberOfMaterialVariants = ( _MorphingFlag | _SkinningFlag ) + 1,
17885
17886 _depthMaterials = new Array( _NumberOfMaterialVariants ),
17887 _distanceMaterials = new Array( _NumberOfMaterialVariants ),
17888
17889 _materialCache = {};
17890
17891 var shadowSide = { 0: BackSide, 1: FrontSide, 2: DoubleSide };
17892
17893 var cubeDirections = [
17894 new Vector3( 1, 0, 0 ), new Vector3( - 1, 0, 0 ), new Vector3( 0, 0, 1 ),
17895 new Vector3( 0, 0, - 1 ), new Vector3( 0, 1, 0 ), new Vector3( 0, - 1, 0 )
17896 ];
17897
17898 var cubeUps = [
17899 new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ),
17900 new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ), new Vector3( 0, 0, - 1 )
17901 ];
17902
17903 var cube2DViewPorts = [
17904 new Vector4(), new Vector4(), new Vector4(),
17905 new Vector4(), new Vector4(), new Vector4()
17906 ];
17907
17908 // init
17909
17910 for ( var i = 0; i !== _NumberOfMaterialVariants; ++ i ) {
17911
17912 var useMorphing = ( i & _MorphingFlag ) !== 0;
17913 var useSkinning = ( i & _SkinningFlag ) !== 0;
17914
17915 var depthMaterial = new MeshDepthMaterial( {
17916
17917 depthPacking: RGBADepthPacking,
17918
17919 morphTargets: useMorphing,
17920 skinning: useSkinning
17921
17922 } );
17923
17924 _depthMaterials[ i ] = depthMaterial;
17925
17926 //
17927
17928 var distanceMaterial = new MeshDistanceMaterial( {
17929
17930 morphTargets: useMorphing,
17931 skinning: useSkinning
17932
17933 } );
17934
17935 _distanceMaterials[ i ] = distanceMaterial;
17936
17937 }
17938
17939 //
17940
17941 var scope = this;
17942
17943 this.enabled = false;
17944
17945 this.autoUpdate = true;
17946 this.needsUpdate = false;
17947
17948 this.type = PCFShadowMap;
17949
17950 this.render = function ( lights, scene, camera ) {
17951
17952 if ( scope.enabled === false ) return;
17953 if ( scope.autoUpdate === false && scope.needsUpdate === false ) return;
17954
17955 if ( lights.length === 0 ) return;
17956
17957 // TODO Clean up (needed in case of contextlost)
17958 var _gl = _renderer.context;
17959 var _state = _renderer.state;
17960
17961 // Set GL state for depth map.
17962 _state.disable( _gl.BLEND );
17963 _state.buffers.color.setClear( 1, 1, 1, 1 );
17964 _state.buffers.depth.setTest( true );
17965 _state.setScissorTest( false );
17966
17967 // render depth map
17968
17969 var faceCount;
17970
17971 for ( var i = 0, il = lights.length; i < il; i ++ ) {
17972
17973 var light = lights[ i ];
17974 var shadow = light.shadow;
17975 var isPointLight = light && light.isPointLight;
17976
17977 if ( shadow === undefined ) {
17978
17979 console.warn( 'THREE.WebGLShadowMap:', light, 'has no shadow.' );
17980 continue;
17981
17982 }
17983
17984 var shadowCamera = shadow.camera;
17985
17986 _shadowMapSize.copy( shadow.mapSize );
17987 _shadowMapSize.min( _maxShadowMapSize );
17988
17989 if ( isPointLight ) {
17990
17991 var vpWidth = _shadowMapSize.x;
17992 var vpHeight = _shadowMapSize.y;
17993
17994 // These viewports map a cube-map onto a 2D texture with the
17995 // following orientation:
17996 //
17997 // xzXZ
17998 // y Y
17999 //
18000 // X - Positive x direction
18001 // x - Negative x direction
18002 // Y - Positive y direction
18003 // y - Negative y direction
18004 // Z - Positive z direction
18005 // z - Negative z direction
18006
18007 // positive X
18008 cube2DViewPorts[ 0 ].set( vpWidth * 2, vpHeight, vpWidth, vpHeight );
18009 // negative X
18010 cube2DViewPorts[ 1 ].set( 0, vpHeight, vpWidth, vpHeight );
18011 // positive Z
18012 cube2DViewPorts[ 2 ].set( vpWidth * 3, vpHeight, vpWidth, vpHeight );
18013 // negative Z
18014 cube2DViewPorts[ 3 ].set( vpWidth, vpHeight, vpWidth, vpHeight );
18015 // positive Y
18016 cube2DViewPorts[ 4 ].set( vpWidth * 3, 0, vpWidth, vpHeight );
18017 // negative Y
18018 cube2DViewPorts[ 5 ].set( vpWidth, 0, vpWidth, vpHeight );
18019
18020 _shadowMapSize.x *= 4.0;
18021 _shadowMapSize.y *= 2.0;
18022
18023 }
18024
18025 if ( shadow.map === null ) {
18026
18027 var pars = { minFilter: NearestFilter, magFilter: NearestFilter, format: RGBAFormat };
18028
18029 shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );
18030 shadow.map.texture.name = light.name + ".shadowMap";
18031
18032 shadowCamera.updateProjectionMatrix();
18033
18034 }
18035
18036 if ( shadow.isSpotLightShadow ) {
18037
18038 shadow.update( light );
18039
18040 }
18041
18042 var shadowMap = shadow.map;
18043 var shadowMatrix = shadow.matrix;
18044
18045 _lightPositionWorld.setFromMatrixPosition( light.matrixWorld );
18046 shadowCamera.position.copy( _lightPositionWorld );
18047
18048 if ( isPointLight ) {
18049
18050 faceCount = 6;
18051
18052 // for point lights we set the shadow matrix to be a translation-only matrix
18053 // equal to inverse of the light's position
18054
18055 shadowMatrix.makeTranslation( - _lightPositionWorld.x, - _lightPositionWorld.y, - _lightPositionWorld.z );
18056
18057 } else {
18058
18059 faceCount = 1;
18060
18061 _lookTarget.setFromMatrixPosition( light.target.matrixWorld );
18062 shadowCamera.lookAt( _lookTarget );
18063 shadowCamera.updateMatrixWorld();
18064
18065 // compute shadow matrix
18066
18067 shadowMatrix.set(
18068 0.5, 0.0, 0.0, 0.5,
18069 0.0, 0.5, 0.0, 0.5,
18070 0.0, 0.0, 0.5, 0.5,
18071 0.0, 0.0, 0.0, 1.0
18072 );
18073
18074 shadowMatrix.multiply( shadowCamera.projectionMatrix );
18075 shadowMatrix.multiply( shadowCamera.matrixWorldInverse );
18076
18077 }
18078
18079 _renderer.setRenderTarget( shadowMap );
18080 _renderer.clear();
18081
18082 // render shadow map for each cube face (if omni-directional) or
18083 // run a single pass if not
18084
18085 for ( var face = 0; face < faceCount; face ++ ) {
18086
18087 if ( isPointLight ) {
18088
18089 _lookTarget.copy( shadowCamera.position );
18090 _lookTarget.add( cubeDirections[ face ] );
18091 shadowCamera.up.copy( cubeUps[ face ] );
18092 shadowCamera.lookAt( _lookTarget );
18093 shadowCamera.updateMatrixWorld();
18094
18095 var vpDimensions = cube2DViewPorts[ face ];
18096 _state.viewport( vpDimensions );
18097
18098 }
18099
18100 // update camera matrices and frustum
18101
18102 _projScreenMatrix.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse );
18103 _frustum.setFromMatrix( _projScreenMatrix );
18104
18105 // set object matrices & frustum culling
18106
18107 renderObject( scene, camera, shadowCamera, isPointLight );
18108
18109 }
18110
18111 }
18112
18113 scope.needsUpdate = false;
18114
18115 };
18116
18117 function getDepthMaterial( object, material, isPointLight, lightPositionWorld, shadowCameraNear, shadowCameraFar ) {
18118
18119 var geometry = object.geometry;
18120
18121 var result = null;
18122
18123 var materialVariants = _depthMaterials;
18124 var customMaterial = object.customDepthMaterial;
18125
18126 if ( isPointLight ) {
18127
18128 materialVariants = _distanceMaterials;
18129 customMaterial = object.customDistanceMaterial;
18130
18131 }
18132
18133 if ( ! customMaterial ) {
18134
18135 var useMorphing = false;
18136
18137 if ( material.morphTargets ) {
18138
18139 if ( geometry && geometry.isBufferGeometry ) {
18140
18141 useMorphing = geometry.morphAttributes && geometry.morphAttributes.position && geometry.morphAttributes.position.length > 0;
18142
18143 } else if ( geometry && geometry.isGeometry ) {
18144
18145 useMorphing = geometry.morphTargets && geometry.morphTargets.length > 0;
18146
18147 }
18148
18149 }
18150
18151 if ( object.isSkinnedMesh && material.skinning === false ) {
18152
18153 console.warn( 'THREE.WebGLShadowMap: THREE.SkinnedMesh with material.skinning set to false:', object );
18154
18155 }
18156
18157 var useSkinning = object.isSkinnedMesh && material.skinning;
18158
18159 var variantIndex = 0;
18160
18161 if ( useMorphing ) variantIndex |= _MorphingFlag;
18162 if ( useSkinning ) variantIndex |= _SkinningFlag;
18163
18164 result = materialVariants[ variantIndex ];
18165
18166 } else {
18167
18168 result = customMaterial;
18169
18170 }
18171
18172 if ( _renderer.localClippingEnabled &&
18173 material.clipShadows === true &&
18174 material.clippingPlanes.length !== 0 ) {
18175
18176 // in this case we need a unique material instance reflecting the
18177 // appropriate state
18178
18179 var keyA = result.uuid, keyB = material.uuid;
18180
18181 var materialsForVariant = _materialCache[ keyA ];
18182
18183 if ( materialsForVariant === undefined ) {
18184
18185 materialsForVariant = {};
18186 _materialCache[ keyA ] = materialsForVariant;
18187
18188 }
18189
18190 var cachedMaterial = materialsForVariant[ keyB ];
18191
18192 if ( cachedMaterial === undefined ) {
18193
18194 cachedMaterial = result.clone();
18195 materialsForVariant[ keyB ] = cachedMaterial;
18196
18197 }
18198
18199 result = cachedMaterial;
18200
18201 }
18202
18203 result.visible = material.visible;
18204 result.wireframe = material.wireframe;
18205
18206 result.side = ( material.shadowSide != null ) ? material.shadowSide : shadowSide[ material.side ];
18207
18208 result.clipShadows = material.clipShadows;
18209 result.clippingPlanes = material.clippingPlanes;
18210 result.clipIntersection = material.clipIntersection;
18211
18212 result.wireframeLinewidth = material.wireframeLinewidth;
18213 result.linewidth = material.linewidth;
18214
18215 if ( isPointLight && result.isMeshDistanceMaterial ) {
18216
18217 result.referencePosition.copy( lightPositionWorld );
18218 result.nearDistance = shadowCameraNear;
18219 result.farDistance = shadowCameraFar;
18220
18221 }
18222
18223 return result;
18224
18225 }
18226
18227 function renderObject( object, camera, shadowCamera, isPointLight ) {
18228
18229 if ( object.visible === false ) return;
18230
18231 var visible = object.layers.test( camera.layers );
18232
18233 if ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) {
18234
18235 if ( object.castShadow && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) {
18236
18237 object.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld );
18238
18239 var geometry = _objects.update( object );
18240 var material = object.material;
18241
18242 if ( Array.isArray( material ) ) {
18243
18244 var groups = geometry.groups;
18245
18246 for ( var k = 0, kl = groups.length; k < kl; k ++ ) {
18247
18248 var group = groups[ k ];
18249 var groupMaterial = material[ group.materialIndex ];
18250
18251 if ( groupMaterial && groupMaterial.visible ) {
18252
18253 var depthMaterial = getDepthMaterial( object, groupMaterial, isPointLight, _lightPositionWorld, shadowCamera.near, shadowCamera.far );
18254 _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group );
18255
18256 }
18257
18258 }
18259
18260 } else if ( material.visible ) {
18261
18262 var depthMaterial = getDepthMaterial( object, material, isPointLight, _lightPositionWorld, shadowCamera.near, shadowCamera.far );
18263 _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null );
18264
18265 }
18266
18267 }
18268
18269 }
18270
18271 var children = object.children;
18272
18273 for ( var i = 0, l = children.length; i < l; i ++ ) {
18274
18275 renderObject( children[ i ], camera, shadowCamera, isPointLight );
18276
18277 }
18278
18279 }
18280
18281}
18282
18283/**
18284 * @author mrdoob / http://mrdoob.com/
18285 */
18286
18287function CanvasTexture( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
18288
18289 Texture.call( this, canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
18290
18291 this.needsUpdate = true;
18292
18293}
18294
18295CanvasTexture.prototype = Object.create( Texture.prototype );
18296CanvasTexture.prototype.constructor = CanvasTexture;
18297
18298/**
18299 * @author mikael emtinger / http://gomo.se/
18300 * @author alteredq / http://alteredqualia.com/
18301 */
18302
18303function WebGLSpriteRenderer( renderer, gl, state, textures, capabilities ) {
18304
18305 var vertexBuffer, elementBuffer;
18306 var program, attributes, uniforms;
18307
18308 var texture;
18309
18310 // decompose matrixWorld
18311
18312 var spritePosition = new Vector3();
18313 var spriteRotation = new Quaternion();
18314 var spriteScale = new Vector3();
18315
18316 function init() {
18317
18318 var vertices = new Float32Array( [
18319 - 0.5, - 0.5, 0, 0,
18320 0.5, - 0.5, 1, 0,
18321 0.5, 0.5, 1, 1,
18322 - 0.5, 0.5, 0, 1
18323 ] );
18324
18325 var faces = new Uint16Array( [
18326 0, 1, 2,
18327 0, 2, 3
18328 ] );
18329
18330 vertexBuffer = gl.createBuffer();
18331 elementBuffer = gl.createBuffer();
18332
18333 gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer );
18334 gl.bufferData( gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW );
18335
18336 gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer );
18337 gl.bufferData( gl.ELEMENT_ARRAY_BUFFER, faces, gl.STATIC_DRAW );
18338
18339 program = createProgram();
18340
18341 attributes = {
18342 position: gl.getAttribLocation( program, 'position' ),
18343 uv: gl.getAttribLocation( program, 'uv' )
18344 };
18345
18346 uniforms = {
18347 uvOffset: gl.getUniformLocation( program, 'uvOffset' ),
18348 uvScale: gl.getUniformLocation( program, 'uvScale' ),
18349
18350 rotation: gl.getUniformLocation( program, 'rotation' ),
18351 center: gl.getUniformLocation( program, 'center' ),
18352 scale: gl.getUniformLocation( program, 'scale' ),
18353
18354 color: gl.getUniformLocation( program, 'color' ),
18355 map: gl.getUniformLocation( program, 'map' ),
18356 opacity: gl.getUniformLocation( program, 'opacity' ),
18357
18358 modelViewMatrix: gl.getUniformLocation( program, 'modelViewMatrix' ),
18359 projectionMatrix: gl.getUniformLocation( program, 'projectionMatrix' ),
18360
18361 fogType: gl.getUniformLocation( program, 'fogType' ),
18362 fogDensity: gl.getUniformLocation( program, 'fogDensity' ),
18363 fogNear: gl.getUniformLocation( program, 'fogNear' ),
18364 fogFar: gl.getUniformLocation( program, 'fogFar' ),
18365 fogColor: gl.getUniformLocation( program, 'fogColor' ),
18366 fogDepth: gl.getUniformLocation( program, 'fogDepth' ),
18367
18368 alphaTest: gl.getUniformLocation( program, 'alphaTest' )
18369 };
18370
18371 var canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
18372 canvas.width = 8;
18373 canvas.height = 8;
18374
18375 var context = canvas.getContext( '2d' );
18376 context.fillStyle = 'white';
18377 context.fillRect( 0, 0, 8, 8 );
18378
18379 texture = new CanvasTexture( canvas );
18380
18381 }
18382
18383 this.render = function ( sprites, scene, camera ) {
18384
18385 if ( sprites.length === 0 ) return;
18386
18387 // setup gl
18388
18389 if ( program === undefined ) {
18390
18391 init();
18392
18393 }
18394
18395 state.useProgram( program );
18396
18397 state.initAttributes();
18398 state.enableAttribute( attributes.position );
18399 state.enableAttribute( attributes.uv );
18400 state.disableUnusedAttributes();
18401
18402 state.disable( gl.CULL_FACE );
18403 state.enable( gl.BLEND );
18404
18405 gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer );
18406 gl.vertexAttribPointer( attributes.position, 2, gl.FLOAT, false, 2 * 8, 0 );
18407 gl.vertexAttribPointer( attributes.uv, 2, gl.FLOAT, false, 2 * 8, 8 );
18408
18409 gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer );
18410
18411 gl.uniformMatrix4fv( uniforms.projectionMatrix, false, camera.projectionMatrix.elements );
18412
18413 state.activeTexture( gl.TEXTURE0 );
18414 gl.uniform1i( uniforms.map, 0 );
18415
18416 var oldFogType = 0;
18417 var sceneFogType = 0;
18418 var fog = scene.fog;
18419
18420 if ( fog ) {
18421
18422 gl.uniform3f( uniforms.fogColor, fog.color.r, fog.color.g, fog.color.b );
18423
18424 if ( fog.isFog ) {
18425
18426 gl.uniform1f( uniforms.fogNear, fog.near );
18427 gl.uniform1f( uniforms.fogFar, fog.far );
18428
18429 gl.uniform1i( uniforms.fogType, 1 );
18430 oldFogType = 1;
18431 sceneFogType = 1;
18432
18433 } else if ( fog.isFogExp2 ) {
18434
18435 gl.uniform1f( uniforms.fogDensity, fog.density );
18436
18437 gl.uniform1i( uniforms.fogType, 2 );
18438 oldFogType = 2;
18439 sceneFogType = 2;
18440
18441 }
18442
18443 } else {
18444
18445 gl.uniform1i( uniforms.fogType, 0 );
18446 oldFogType = 0;
18447 sceneFogType = 0;
18448
18449 }
18450
18451
18452 // update positions and sort
18453
18454 for ( var i = 0, l = sprites.length; i < l; i ++ ) {
18455
18456 var sprite = sprites[ i ];
18457
18458 sprite.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, sprite.matrixWorld );
18459 sprite.z = - sprite.modelViewMatrix.elements[ 14 ];
18460
18461 }
18462
18463 sprites.sort( painterSortStable );
18464
18465 // render all sprites
18466
18467 var scale = [];
18468 var center = [];
18469
18470 for ( var i = 0, l = sprites.length; i < l; i ++ ) {
18471
18472 var sprite = sprites[ i ];
18473 var material = sprite.material;
18474
18475 if ( material.visible === false ) continue;
18476
18477 sprite.onBeforeRender( renderer, scene, camera, undefined, material, undefined );
18478
18479 gl.uniform1f( uniforms.alphaTest, material.alphaTest );
18480 gl.uniformMatrix4fv( uniforms.modelViewMatrix, false, sprite.modelViewMatrix.elements );
18481
18482 sprite.matrixWorld.decompose( spritePosition, spriteRotation, spriteScale );
18483
18484 scale[ 0 ] = spriteScale.x;
18485 scale[ 1 ] = spriteScale.y;
18486
18487 center[ 0 ] = sprite.center.x - 0.5;
18488 center[ 1 ] = sprite.center.y - 0.5;
18489
18490 var fogType = 0;
18491
18492 if ( scene.fog && material.fog ) {
18493
18494 fogType = sceneFogType;
18495
18496 }
18497
18498 if ( oldFogType !== fogType ) {
18499
18500 gl.uniform1i( uniforms.fogType, fogType );
18501 oldFogType = fogType;
18502
18503 }
18504
18505 if ( material.map !== null ) {
18506
18507 gl.uniform2f( uniforms.uvOffset, material.map.offset.x, material.map.offset.y );
18508 gl.uniform2f( uniforms.uvScale, material.map.repeat.x, material.map.repeat.y );
18509
18510 } else {
18511
18512 gl.uniform2f( uniforms.uvOffset, 0, 0 );
18513 gl.uniform2f( uniforms.uvScale, 1, 1 );
18514
18515 }
18516
18517 gl.uniform1f( uniforms.opacity, material.opacity );
18518 gl.uniform3f( uniforms.color, material.color.r, material.color.g, material.color.b );
18519
18520 gl.uniform1f( uniforms.rotation, material.rotation );
18521 gl.uniform2fv( uniforms.center, center );
18522 gl.uniform2fv( uniforms.scale, scale );
18523
18524 state.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha );
18525 state.buffers.depth.setTest( material.depthTest );
18526 state.buffers.depth.setMask( material.depthWrite );
18527 state.buffers.color.setMask( material.colorWrite );
18528
18529 textures.setTexture2D( material.map || texture, 0 );
18530
18531 gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 );
18532
18533 sprite.onAfterRender( renderer, scene, camera, undefined, material, undefined );
18534
18535 }
18536
18537 // restore gl
18538
18539 state.enable( gl.CULL_FACE );
18540
18541 state.reset();
18542
18543 };
18544
18545 function createProgram() {
18546
18547 var program = gl.createProgram();
18548
18549 var vertexShader = gl.createShader( gl.VERTEX_SHADER );
18550 var fragmentShader = gl.createShader( gl.FRAGMENT_SHADER );
18551
18552 gl.shaderSource( vertexShader, [
18553
18554 'precision ' + capabilities.precision + ' float;',
18555
18556 '#define SHADER_NAME ' + 'SpriteMaterial',
18557
18558 'uniform mat4 modelViewMatrix;',
18559 'uniform mat4 projectionMatrix;',
18560 'uniform float rotation;',
18561 'uniform vec2 center;',
18562 'uniform vec2 scale;',
18563 'uniform vec2 uvOffset;',
18564 'uniform vec2 uvScale;',
18565
18566 'attribute vec2 position;',
18567 'attribute vec2 uv;',
18568
18569 'varying vec2 vUV;',
18570 'varying float fogDepth;',
18571
18572 'void main() {',
18573
18574 ' vUV = uvOffset + uv * uvScale;',
18575
18576 ' vec2 alignedPosition = ( position - center ) * scale;',
18577
18578 ' vec2 rotatedPosition;',
18579 ' rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;',
18580 ' rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;',
18581
18582 ' vec4 mvPosition;',
18583
18584 ' mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );',
18585 ' mvPosition.xy += rotatedPosition;',
18586
18587 ' gl_Position = projectionMatrix * mvPosition;',
18588
18589 ' fogDepth = - mvPosition.z;',
18590
18591 '}'
18592
18593 ].join( '\n' ) );
18594
18595 gl.shaderSource( fragmentShader, [
18596
18597 'precision ' + capabilities.precision + ' float;',
18598
18599 '#define SHADER_NAME ' + 'SpriteMaterial',
18600
18601 'uniform vec3 color;',
18602 'uniform sampler2D map;',
18603 'uniform float opacity;',
18604
18605 'uniform int fogType;',
18606 'uniform vec3 fogColor;',
18607 'uniform float fogDensity;',
18608 'uniform float fogNear;',
18609 'uniform float fogFar;',
18610 'uniform float alphaTest;',
18611
18612 'varying vec2 vUV;',
18613 'varying float fogDepth;',
18614
18615 'void main() {',
18616
18617 ' vec4 texture = texture2D( map, vUV );',
18618
18619 ' gl_FragColor = vec4( color * texture.xyz, texture.a * opacity );',
18620
18621 ' if ( gl_FragColor.a < alphaTest ) discard;',
18622
18623 ' if ( fogType > 0 ) {',
18624
18625 ' float fogFactor = 0.0;',
18626
18627 ' if ( fogType == 1 ) {',
18628
18629 ' fogFactor = smoothstep( fogNear, fogFar, fogDepth );',
18630
18631 ' } else {',
18632
18633 ' const float LOG2 = 1.442695;',
18634 ' fogFactor = exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 );',
18635 ' fogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );',
18636
18637 ' }',
18638
18639 ' gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );',
18640
18641 ' }',
18642
18643 '}'
18644
18645 ].join( '\n' ) );
18646
18647 gl.compileShader( vertexShader );
18648 gl.compileShader( fragmentShader );
18649
18650 gl.attachShader( program, vertexShader );
18651 gl.attachShader( program, fragmentShader );
18652
18653 gl.linkProgram( program );
18654
18655 return program;
18656
18657 }
18658
18659 function painterSortStable( a, b ) {
18660
18661 if ( a.renderOrder !== b.renderOrder ) {
18662
18663 return a.renderOrder - b.renderOrder;
18664
18665 } else if ( a.z !== b.z ) {
18666
18667 return b.z - a.z;
18668
18669 } else {
18670
18671 return b.id - a.id;
18672
18673 }
18674
18675 }
18676
18677}
18678
18679/**
18680 * @author mrdoob / http://mrdoob.com/
18681 */
18682
18683function WebGLState( gl, extensions, utils ) {
18684
18685 function ColorBuffer() {
18686
18687 var locked = false;
18688
18689 var color = new Vector4();
18690 var currentColorMask = null;
18691 var currentColorClear = new Vector4( 0, 0, 0, 0 );
18692
18693 return {
18694
18695 setMask: function ( colorMask ) {
18696
18697 if ( currentColorMask !== colorMask && ! locked ) {
18698
18699 gl.colorMask( colorMask, colorMask, colorMask, colorMask );
18700 currentColorMask = colorMask;
18701
18702 }
18703
18704 },
18705
18706 setLocked: function ( lock ) {
18707
18708 locked = lock;
18709
18710 },
18711
18712 setClear: function ( r, g, b, a, premultipliedAlpha ) {
18713
18714 if ( premultipliedAlpha === true ) {
18715
18716 r *= a; g *= a; b *= a;
18717
18718 }
18719
18720 color.set( r, g, b, a );
18721
18722 if ( currentColorClear.equals( color ) === false ) {
18723
18724 gl.clearColor( r, g, b, a );
18725 currentColorClear.copy( color );
18726
18727 }
18728
18729 },
18730
18731 reset: function () {
18732
18733 locked = false;
18734
18735 currentColorMask = null;
18736 currentColorClear.set( - 1, 0, 0, 0 ); // set to invalid state
18737
18738 }
18739
18740 };
18741
18742 }
18743
18744 function DepthBuffer() {
18745
18746 var locked = false;
18747
18748 var currentDepthMask = null;
18749 var currentDepthFunc = null;
18750 var currentDepthClear = null;
18751
18752 return {
18753
18754 setTest: function ( depthTest ) {
18755
18756 if ( depthTest ) {
18757
18758 enable( gl.DEPTH_TEST );
18759
18760 } else {
18761
18762 disable( gl.DEPTH_TEST );
18763
18764 }
18765
18766 },
18767
18768 setMask: function ( depthMask ) {
18769
18770 if ( currentDepthMask !== depthMask && ! locked ) {
18771
18772 gl.depthMask( depthMask );
18773 currentDepthMask = depthMask;
18774
18775 }
18776
18777 },
18778
18779 setFunc: function ( depthFunc ) {
18780
18781 if ( currentDepthFunc !== depthFunc ) {
18782
18783 if ( depthFunc ) {
18784
18785 switch ( depthFunc ) {
18786
18787 case NeverDepth:
18788
18789 gl.depthFunc( gl.NEVER );
18790 break;
18791
18792 case AlwaysDepth:
18793
18794 gl.depthFunc( gl.ALWAYS );
18795 break;
18796
18797 case LessDepth:
18798
18799 gl.depthFunc( gl.LESS );
18800 break;
18801
18802 case LessEqualDepth:
18803
18804 gl.depthFunc( gl.LEQUAL );
18805 break;
18806
18807 case EqualDepth:
18808
18809 gl.depthFunc( gl.EQUAL );
18810 break;
18811
18812 case GreaterEqualDepth:
18813
18814 gl.depthFunc( gl.GEQUAL );
18815 break;
18816
18817 case GreaterDepth:
18818
18819 gl.depthFunc( gl.GREATER );
18820 break;
18821
18822 case NotEqualDepth:
18823
18824 gl.depthFunc( gl.NOTEQUAL );
18825 break;
18826
18827 default:
18828
18829 gl.depthFunc( gl.LEQUAL );
18830
18831 }
18832
18833 } else {
18834
18835 gl.depthFunc( gl.LEQUAL );
18836
18837 }
18838
18839 currentDepthFunc = depthFunc;
18840
18841 }
18842
18843 },
18844
18845 setLocked: function ( lock ) {
18846
18847 locked = lock;
18848
18849 },
18850
18851 setClear: function ( depth ) {
18852
18853 if ( currentDepthClear !== depth ) {
18854
18855 gl.clearDepth( depth );
18856 currentDepthClear = depth;
18857
18858 }
18859
18860 },
18861
18862 reset: function () {
18863
18864 locked = false;
18865
18866 currentDepthMask = null;
18867 currentDepthFunc = null;
18868 currentDepthClear = null;
18869
18870 }
18871
18872 };
18873
18874 }
18875
18876 function StencilBuffer() {
18877
18878 var locked = false;
18879
18880 var currentStencilMask = null;
18881 var currentStencilFunc = null;
18882 var currentStencilRef = null;
18883 var currentStencilFuncMask = null;
18884 var currentStencilFail = null;
18885 var currentStencilZFail = null;
18886 var currentStencilZPass = null;
18887 var currentStencilClear = null;
18888
18889 return {
18890
18891 setTest: function ( stencilTest ) {
18892
18893 if ( stencilTest ) {
18894
18895 enable( gl.STENCIL_TEST );
18896
18897 } else {
18898
18899 disable( gl.STENCIL_TEST );
18900
18901 }
18902
18903 },
18904
18905 setMask: function ( stencilMask ) {
18906
18907 if ( currentStencilMask !== stencilMask && ! locked ) {
18908
18909 gl.stencilMask( stencilMask );
18910 currentStencilMask = stencilMask;
18911
18912 }
18913
18914 },
18915
18916 setFunc: function ( stencilFunc, stencilRef, stencilMask ) {
18917
18918 if ( currentStencilFunc !== stencilFunc ||
18919 currentStencilRef !== stencilRef ||
18920 currentStencilFuncMask !== stencilMask ) {
18921
18922 gl.stencilFunc( stencilFunc, stencilRef, stencilMask );
18923
18924 currentStencilFunc = stencilFunc;
18925 currentStencilRef = stencilRef;
18926 currentStencilFuncMask = stencilMask;
18927
18928 }
18929
18930 },
18931
18932 setOp: function ( stencilFail, stencilZFail, stencilZPass ) {
18933
18934 if ( currentStencilFail !== stencilFail ||
18935 currentStencilZFail !== stencilZFail ||
18936 currentStencilZPass !== stencilZPass ) {
18937
18938 gl.stencilOp( stencilFail, stencilZFail, stencilZPass );
18939
18940 currentStencilFail = stencilFail;
18941 currentStencilZFail = stencilZFail;
18942 currentStencilZPass = stencilZPass;
18943
18944 }
18945
18946 },
18947
18948 setLocked: function ( lock ) {
18949
18950 locked = lock;
18951
18952 },
18953
18954 setClear: function ( stencil ) {
18955
18956 if ( currentStencilClear !== stencil ) {
18957
18958 gl.clearStencil( stencil );
18959 currentStencilClear = stencil;
18960
18961 }
18962
18963 },
18964
18965 reset: function () {
18966
18967 locked = false;
18968
18969 currentStencilMask = null;
18970 currentStencilFunc = null;
18971 currentStencilRef = null;
18972 currentStencilFuncMask = null;
18973 currentStencilFail = null;
18974 currentStencilZFail = null;
18975 currentStencilZPass = null;
18976 currentStencilClear = null;
18977
18978 }
18979
18980 };
18981
18982 }
18983
18984 //
18985
18986 var colorBuffer = new ColorBuffer();
18987 var depthBuffer = new DepthBuffer();
18988 var stencilBuffer = new StencilBuffer();
18989
18990 var maxVertexAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS );
18991 var newAttributes = new Uint8Array( maxVertexAttributes );
18992 var enabledAttributes = new Uint8Array( maxVertexAttributes );
18993 var attributeDivisors = new Uint8Array( maxVertexAttributes );
18994
18995 var capabilities = {};
18996
18997 var compressedTextureFormats = null;
18998
18999 var currentProgram = null;
19000
19001 var currentBlending = null;
19002 var currentBlendEquation = null;
19003 var currentBlendSrc = null;
19004 var currentBlendDst = null;
19005 var currentBlendEquationAlpha = null;
19006 var currentBlendSrcAlpha = null;
19007 var currentBlendDstAlpha = null;
19008 var currentPremultipledAlpha = false;
19009
19010 var currentFlipSided = null;
19011 var currentCullFace = null;
19012
19013 var currentLineWidth = null;
19014
19015 var currentPolygonOffsetFactor = null;
19016 var currentPolygonOffsetUnits = null;
19017
19018 var maxTextures = gl.getParameter( gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS );
19019
19020 var lineWidthAvailable = false;
19021 var version = 0;
19022 var glVersion = gl.getParameter( gl.VERSION );
19023
19024 if ( glVersion.indexOf( 'WebGL' ) !== - 1 ) {
19025
19026 version = parseFloat( /^WebGL\ ([0-9])/.exec( glVersion )[ 1 ] );
19027 lineWidthAvailable = ( version >= 1.0 );
19028
19029 } else if ( glVersion.indexOf( 'OpenGL ES' ) !== - 1 ) {
19030
19031 version = parseFloat( /^OpenGL\ ES\ ([0-9])/.exec( glVersion )[ 1 ] );
19032 lineWidthAvailable = ( version >= 2.0 );
19033
19034 }
19035
19036 var currentTextureSlot = null;
19037 var currentBoundTextures = {};
19038
19039 var currentScissor = new Vector4();
19040 var currentViewport = new Vector4();
19041
19042 function createTexture( type, target, count ) {
19043
19044 var data = new Uint8Array( 4 ); // 4 is required to match default unpack alignment of 4.
19045 var texture = gl.createTexture();
19046
19047 gl.bindTexture( type, texture );
19048 gl.texParameteri( type, gl.TEXTURE_MIN_FILTER, gl.NEAREST );
19049 gl.texParameteri( type, gl.TEXTURE_MAG_FILTER, gl.NEAREST );
19050
19051 for ( var i = 0; i < count; i ++ ) {
19052
19053 gl.texImage2D( target + i, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, data );
19054
19055 }
19056
19057 return texture;
19058
19059 }
19060
19061 var emptyTextures = {};
19062 emptyTextures[ gl.TEXTURE_2D ] = createTexture( gl.TEXTURE_2D, gl.TEXTURE_2D, 1 );
19063 emptyTextures[ gl.TEXTURE_CUBE_MAP ] = createTexture( gl.TEXTURE_CUBE_MAP, gl.TEXTURE_CUBE_MAP_POSITIVE_X, 6 );
19064
19065 // init
19066
19067 colorBuffer.setClear( 0, 0, 0, 1 );
19068 depthBuffer.setClear( 1 );
19069 stencilBuffer.setClear( 0 );
19070
19071 enable( gl.DEPTH_TEST );
19072 depthBuffer.setFunc( LessEqualDepth );
19073
19074 setFlipSided( false );
19075 setCullFace( CullFaceBack );
19076 enable( gl.CULL_FACE );
19077
19078 enable( gl.BLEND );
19079 setBlending( NormalBlending );
19080
19081 //
19082
19083 function initAttributes() {
19084
19085 for ( var i = 0, l = newAttributes.length; i < l; i ++ ) {
19086
19087 newAttributes[ i ] = 0;
19088
19089 }
19090
19091 }
19092
19093 function enableAttribute( attribute ) {
19094
19095 newAttributes[ attribute ] = 1;
19096
19097 if ( enabledAttributes[ attribute ] === 0 ) {
19098
19099 gl.enableVertexAttribArray( attribute );
19100 enabledAttributes[ attribute ] = 1;
19101
19102 }
19103
19104 if ( attributeDivisors[ attribute ] !== 0 ) {
19105
19106 var extension = extensions.get( 'ANGLE_instanced_arrays' );
19107
19108 extension.vertexAttribDivisorANGLE( attribute, 0 );
19109 attributeDivisors[ attribute ] = 0;
19110
19111 }
19112
19113 }
19114
19115 function enableAttributeAndDivisor( attribute, meshPerAttribute ) {
19116
19117 newAttributes[ attribute ] = 1;
19118
19119 if ( enabledAttributes[ attribute ] === 0 ) {
19120
19121 gl.enableVertexAttribArray( attribute );
19122 enabledAttributes[ attribute ] = 1;
19123
19124 }
19125
19126 if ( attributeDivisors[ attribute ] !== meshPerAttribute ) {
19127
19128 var extension = extensions.get( 'ANGLE_instanced_arrays' );
19129
19130 extension.vertexAttribDivisorANGLE( attribute, meshPerAttribute );
19131 attributeDivisors[ attribute ] = meshPerAttribute;
19132
19133 }
19134
19135 }
19136
19137 function disableUnusedAttributes() {
19138
19139 for ( var i = 0, l = enabledAttributes.length; i !== l; ++ i ) {
19140
19141 if ( enabledAttributes[ i ] !== newAttributes[ i ] ) {
19142
19143 gl.disableVertexAttribArray( i );
19144 enabledAttributes[ i ] = 0;
19145
19146 }
19147
19148 }
19149
19150 }
19151
19152 function enable( id ) {
19153
19154 if ( capabilities[ id ] !== true ) {
19155
19156 gl.enable( id );
19157 capabilities[ id ] = true;
19158
19159 }
19160
19161 }
19162
19163 function disable( id ) {
19164
19165 if ( capabilities[ id ] !== false ) {
19166
19167 gl.disable( id );
19168 capabilities[ id ] = false;
19169
19170 }
19171
19172 }
19173
19174 function getCompressedTextureFormats() {
19175
19176 if ( compressedTextureFormats === null ) {
19177
19178 compressedTextureFormats = [];
19179
19180 if ( extensions.get( 'WEBGL_compressed_texture_pvrtc' ) ||
19181 extensions.get( 'WEBGL_compressed_texture_s3tc' ) ||
19182 extensions.get( 'WEBGL_compressed_texture_etc1' ) ||
19183 extensions.get( 'WEBGL_compressed_texture_astc' ) ) {
19184
19185 var formats = gl.getParameter( gl.COMPRESSED_TEXTURE_FORMATS );
19186
19187 for ( var i = 0; i < formats.length; i ++ ) {
19188
19189 compressedTextureFormats.push( formats[ i ] );
19190
19191 }
19192
19193 }
19194
19195 }
19196
19197 return compressedTextureFormats;
19198
19199 }
19200
19201 function useProgram( program ) {
19202
19203 if ( currentProgram !== program ) {
19204
19205 gl.useProgram( program );
19206
19207 currentProgram = program;
19208
19209 return true;
19210
19211 }
19212
19213 return false;
19214
19215 }
19216
19217 function setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, premultipliedAlpha ) {
19218
19219 if ( blending !== NoBlending ) {
19220
19221 enable( gl.BLEND );
19222
19223 } else {
19224
19225 disable( gl.BLEND );
19226
19227 }
19228
19229 if ( blending !== CustomBlending ) {
19230
19231 if ( blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha ) {
19232
19233 switch ( blending ) {
19234
19235 case AdditiveBlending:
19236
19237 if ( premultipliedAlpha ) {
19238
19239 gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD );
19240 gl.blendFuncSeparate( gl.ONE, gl.ONE, gl.ONE, gl.ONE );
19241
19242 } else {
19243
19244 gl.blendEquation( gl.FUNC_ADD );
19245 gl.blendFunc( gl.SRC_ALPHA, gl.ONE );
19246
19247 }
19248 break;
19249
19250 case SubtractiveBlending:
19251
19252 if ( premultipliedAlpha ) {
19253
19254 gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD );
19255 gl.blendFuncSeparate( gl.ZERO, gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ONE_MINUS_SRC_ALPHA );
19256
19257 } else {
19258
19259 gl.blendEquation( gl.FUNC_ADD );
19260 gl.blendFunc( gl.ZERO, gl.ONE_MINUS_SRC_COLOR );
19261
19262 }
19263 break;
19264
19265 case MultiplyBlending:
19266
19267 if ( premultipliedAlpha ) {
19268
19269 gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD );
19270 gl.blendFuncSeparate( gl.ZERO, gl.SRC_COLOR, gl.ZERO, gl.SRC_ALPHA );
19271
19272 } else {
19273
19274 gl.blendEquation( gl.FUNC_ADD );
19275 gl.blendFunc( gl.ZERO, gl.SRC_COLOR );
19276
19277 }
19278 break;
19279
19280 default:
19281
19282 if ( premultipliedAlpha ) {
19283
19284 gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD );
19285 gl.blendFuncSeparate( gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA );
19286
19287 } else {
19288
19289 gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD );
19290 gl.blendFuncSeparate( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA );
19291
19292 }
19293
19294 }
19295
19296 }
19297
19298 currentBlendEquation = null;
19299 currentBlendSrc = null;
19300 currentBlendDst = null;
19301 currentBlendEquationAlpha = null;
19302 currentBlendSrcAlpha = null;
19303 currentBlendDstAlpha = null;
19304
19305 } else {
19306
19307 blendEquationAlpha = blendEquationAlpha || blendEquation;
19308 blendSrcAlpha = blendSrcAlpha || blendSrc;
19309 blendDstAlpha = blendDstAlpha || blendDst;
19310
19311 if ( blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha ) {
19312
19313 gl.blendEquationSeparate( utils.convert( blendEquation ), utils.convert( blendEquationAlpha ) );
19314
19315 currentBlendEquation = blendEquation;
19316 currentBlendEquationAlpha = blendEquationAlpha;
19317
19318 }
19319
19320 if ( blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha ) {
19321
19322 gl.blendFuncSeparate( utils.convert( blendSrc ), utils.convert( blendDst ), utils.convert( blendSrcAlpha ), utils.convert( blendDstAlpha ) );
19323
19324 currentBlendSrc = blendSrc;
19325 currentBlendDst = blendDst;
19326 currentBlendSrcAlpha = blendSrcAlpha;
19327 currentBlendDstAlpha = blendDstAlpha;
19328
19329 }
19330
19331 }
19332
19333 currentBlending = blending;
19334 currentPremultipledAlpha = premultipliedAlpha;
19335
19336 }
19337
19338 function setMaterial( material, frontFaceCW ) {
19339
19340 material.side === DoubleSide
19341 ? disable( gl.CULL_FACE )
19342 : enable( gl.CULL_FACE );
19343
19344 var flipSided = ( material.side === BackSide );
19345 if ( frontFaceCW ) flipSided = ! flipSided;
19346
19347 setFlipSided( flipSided );
19348
19349 material.transparent === true
19350 ? setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha )
19351 : setBlending( NoBlending );
19352
19353 depthBuffer.setFunc( material.depthFunc );
19354 depthBuffer.setTest( material.depthTest );
19355 depthBuffer.setMask( material.depthWrite );
19356 colorBuffer.setMask( material.colorWrite );
19357
19358 setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
19359
19360 }
19361
19362 //
19363
19364 function setFlipSided( flipSided ) {
19365
19366 if ( currentFlipSided !== flipSided ) {
19367
19368 if ( flipSided ) {
19369
19370 gl.frontFace( gl.CW );
19371
19372 } else {
19373
19374 gl.frontFace( gl.CCW );
19375
19376 }
19377
19378 currentFlipSided = flipSided;
19379
19380 }
19381
19382 }
19383
19384 function setCullFace( cullFace ) {
19385
19386 if ( cullFace !== CullFaceNone ) {
19387
19388 enable( gl.CULL_FACE );
19389
19390 if ( cullFace !== currentCullFace ) {
19391
19392 if ( cullFace === CullFaceBack ) {
19393
19394 gl.cullFace( gl.BACK );
19395
19396 } else if ( cullFace === CullFaceFront ) {
19397
19398 gl.cullFace( gl.FRONT );
19399
19400 } else {
19401
19402 gl.cullFace( gl.FRONT_AND_BACK );
19403
19404 }
19405
19406 }
19407
19408 } else {
19409
19410 disable( gl.CULL_FACE );
19411
19412 }
19413
19414 currentCullFace = cullFace;
19415
19416 }
19417
19418 function setLineWidth( width ) {
19419
19420 if ( width !== currentLineWidth ) {
19421
19422 if ( lineWidthAvailable ) gl.lineWidth( width );
19423
19424 currentLineWidth = width;
19425
19426 }
19427
19428 }
19429
19430 function setPolygonOffset( polygonOffset, factor, units ) {
19431
19432 if ( polygonOffset ) {
19433
19434 enable( gl.POLYGON_OFFSET_FILL );
19435
19436 if ( currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units ) {
19437
19438 gl.polygonOffset( factor, units );
19439
19440 currentPolygonOffsetFactor = factor;
19441 currentPolygonOffsetUnits = units;
19442
19443 }
19444
19445 } else {
19446
19447 disable( gl.POLYGON_OFFSET_FILL );
19448
19449 }
19450
19451 }
19452
19453 function setScissorTest( scissorTest ) {
19454
19455 if ( scissorTest ) {
19456
19457 enable( gl.SCISSOR_TEST );
19458
19459 } else {
19460
19461 disable( gl.SCISSOR_TEST );
19462
19463 }
19464
19465 }
19466
19467 // texture
19468
19469 function activeTexture( webglSlot ) {
19470
19471 if ( webglSlot === undefined ) webglSlot = gl.TEXTURE0 + maxTextures - 1;
19472
19473 if ( currentTextureSlot !== webglSlot ) {
19474
19475 gl.activeTexture( webglSlot );
19476 currentTextureSlot = webglSlot;
19477
19478 }
19479
19480 }
19481
19482 function bindTexture( webglType, webglTexture ) {
19483
19484 if ( currentTextureSlot === null ) {
19485
19486 activeTexture();
19487
19488 }
19489
19490 var boundTexture = currentBoundTextures[ currentTextureSlot ];
19491
19492 if ( boundTexture === undefined ) {
19493
19494 boundTexture = { type: undefined, texture: undefined };
19495 currentBoundTextures[ currentTextureSlot ] = boundTexture;
19496
19497 }
19498
19499 if ( boundTexture.type !== webglType || boundTexture.texture !== webglTexture ) {
19500
19501 gl.bindTexture( webglType, webglTexture || emptyTextures[ webglType ] );
19502
19503 boundTexture.type = webglType;
19504 boundTexture.texture = webglTexture;
19505
19506 }
19507
19508 }
19509
19510 function compressedTexImage2D() {
19511
19512 try {
19513
19514 gl.compressedTexImage2D.apply( gl, arguments );
19515
19516 } catch ( error ) {
19517
19518 console.error( 'THREE.WebGLState:', error );
19519
19520 }
19521
19522 }
19523
19524 function texImage2D() {
19525
19526 try {
19527
19528 gl.texImage2D.apply( gl, arguments );
19529
19530 } catch ( error ) {
19531
19532 console.error( 'THREE.WebGLState:', error );
19533
19534 }
19535
19536 }
19537
19538 //
19539
19540 function scissor( scissor ) {
19541
19542 if ( currentScissor.equals( scissor ) === false ) {
19543
19544 gl.scissor( scissor.x, scissor.y, scissor.z, scissor.w );
19545 currentScissor.copy( scissor );
19546
19547 }
19548
19549 }
19550
19551 function viewport( viewport ) {
19552
19553 if ( currentViewport.equals( viewport ) === false ) {
19554
19555 gl.viewport( viewport.x, viewport.y, viewport.z, viewport.w );
19556 currentViewport.copy( viewport );
19557
19558 }
19559
19560 }
19561
19562 //
19563
19564 function reset() {
19565
19566 for ( var i = 0; i < enabledAttributes.length; i ++ ) {
19567
19568 if ( enabledAttributes[ i ] === 1 ) {
19569
19570 gl.disableVertexAttribArray( i );
19571 enabledAttributes[ i ] = 0;
19572
19573 }
19574
19575 }
19576
19577 capabilities = {};
19578
19579 compressedTextureFormats = null;
19580
19581 currentTextureSlot = null;
19582 currentBoundTextures = {};
19583
19584 currentProgram = null;
19585
19586 currentBlending = null;
19587
19588 currentFlipSided = null;
19589 currentCullFace = null;
19590
19591 colorBuffer.reset();
19592 depthBuffer.reset();
19593 stencilBuffer.reset();
19594
19595 }
19596
19597 return {
19598
19599 buffers: {
19600 color: colorBuffer,
19601 depth: depthBuffer,
19602 stencil: stencilBuffer
19603 },
19604
19605 initAttributes: initAttributes,
19606 enableAttribute: enableAttribute,
19607 enableAttributeAndDivisor: enableAttributeAndDivisor,
19608 disableUnusedAttributes: disableUnusedAttributes,
19609 enable: enable,
19610 disable: disable,
19611 getCompressedTextureFormats: getCompressedTextureFormats,
19612
19613 useProgram: useProgram,
19614
19615 setBlending: setBlending,
19616 setMaterial: setMaterial,
19617
19618 setFlipSided: setFlipSided,
19619 setCullFace: setCullFace,
19620
19621 setLineWidth: setLineWidth,
19622 setPolygonOffset: setPolygonOffset,
19623
19624 setScissorTest: setScissorTest,
19625
19626 activeTexture: activeTexture,
19627 bindTexture: bindTexture,
19628 compressedTexImage2D: compressedTexImage2D,
19629 texImage2D: texImage2D,
19630
19631 scissor: scissor,
19632 viewport: viewport,
19633
19634 reset: reset
19635
19636 };
19637
19638}
19639
19640/**
19641 * @author mrdoob / http://mrdoob.com/
19642 */
19643
19644function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ) {
19645
19646 var _isWebGL2 = ( typeof WebGL2RenderingContext !== 'undefined' && _gl instanceof WebGL2RenderingContext ); /* global WebGL2RenderingContext */
19647 var _videoTextures = {};
19648 var _canvas;
19649
19650 //
19651
19652 function clampToMaxSize( image, maxSize ) {
19653
19654 if ( image.width > maxSize || image.height > maxSize ) {
19655
19656 if ( 'data' in image ) {
19657
19658 console.warn( 'THREE.WebGLRenderer: image in DataTexture is too big (' + image.width + 'x' + image.height + ').' );
19659 return;
19660
19661 }
19662
19663 // Warning: Scaling through the canvas will only work with images that use
19664 // premultiplied alpha.
19665
19666 var scale = maxSize / Math.max( image.width, image.height );
19667
19668 var canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
19669 canvas.width = Math.floor( image.width * scale );
19670 canvas.height = Math.floor( image.height * scale );
19671
19672 var context = canvas.getContext( '2d' );
19673 context.drawImage( image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height );
19674
19675 console.warn( 'THREE.WebGLRenderer: image is too big (' + image.width + 'x' + image.height + '). Resized to ' + canvas.width + 'x' + canvas.height, image );
19676
19677 return canvas;
19678
19679 }
19680
19681 return image;
19682
19683 }
19684
19685 function isPowerOfTwo( image ) {
19686
19687 return _Math.isPowerOfTwo( image.width ) && _Math.isPowerOfTwo( image.height );
19688
19689 }
19690
19691 function makePowerOfTwo( image ) {
19692
19693 if ( image instanceof HTMLImageElement || image instanceof HTMLCanvasElement || image instanceof ImageBitmap ) {
19694
19695 if ( _canvas === undefined ) _canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
19696
19697 _canvas.width = _Math.floorPowerOfTwo( image.width );
19698 _canvas.height = _Math.floorPowerOfTwo( image.height );
19699
19700 var context = _canvas.getContext( '2d' );
19701 context.drawImage( image, 0, 0, _canvas.width, _canvas.height );
19702
19703 console.warn( 'THREE.WebGLRenderer: image is not power of two (' + image.width + 'x' + image.height + '). Resized to ' + _canvas.width + 'x' + _canvas.height, image );
19704
19705 return _canvas;
19706
19707 }
19708
19709 return image;
19710
19711 }
19712
19713 function textureNeedsPowerOfTwo( texture ) {
19714
19715 return ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) ||
19716 ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter );
19717
19718 }
19719
19720 function textureNeedsGenerateMipmaps( texture, isPowerOfTwo ) {
19721
19722 return texture.generateMipmaps && isPowerOfTwo &&
19723 texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter;
19724
19725 }
19726
19727 function generateMipmap( target, texture, width, height ) {
19728
19729 _gl.generateMipmap( target );
19730
19731 var textureProperties = properties.get( texture );
19732
19733 // Note: Math.log( x ) * Math.LOG2E used instead of Math.log2( x ) which is not supported by IE11
19734 textureProperties.__maxMipLevel = Math.log( Math.max( width, height ) ) * Math.LOG2E;
19735
19736 }
19737
19738 // Fallback filters for non-power-of-2 textures
19739
19740 function filterFallback( f ) {
19741
19742 if ( f === NearestFilter || f === NearestMipMapNearestFilter || f === NearestMipMapLinearFilter ) {
19743
19744 return _gl.NEAREST;
19745
19746 }
19747
19748 return _gl.LINEAR;
19749
19750 }
19751
19752 //
19753
19754 function onTextureDispose( event ) {
19755
19756 var texture = event.target;
19757
19758 texture.removeEventListener( 'dispose', onTextureDispose );
19759
19760 deallocateTexture( texture );
19761
19762 if ( texture.isVideoTexture ) {
19763
19764 delete _videoTextures[ texture.id ];
19765
19766 }
19767
19768 info.memory.textures --;
19769
19770 }
19771
19772 function onRenderTargetDispose( event ) {
19773
19774 var renderTarget = event.target;
19775
19776 renderTarget.removeEventListener( 'dispose', onRenderTargetDispose );
19777
19778 deallocateRenderTarget( renderTarget );
19779
19780 info.memory.textures --;
19781
19782 }
19783
19784 //
19785
19786 function deallocateTexture( texture ) {
19787
19788 var textureProperties = properties.get( texture );
19789
19790 if ( texture.image && textureProperties.__image__webglTextureCube ) {
19791
19792 // cube texture
19793
19794 _gl.deleteTexture( textureProperties.__image__webglTextureCube );
19795
19796 } else {
19797
19798 // 2D texture
19799
19800 if ( textureProperties.__webglInit === undefined ) return;
19801
19802 _gl.deleteTexture( textureProperties.__webglTexture );
19803
19804 }
19805
19806 // remove all webgl properties
19807 properties.remove( texture );
19808
19809 }
19810
19811 function deallocateRenderTarget( renderTarget ) {
19812
19813 var renderTargetProperties = properties.get( renderTarget );
19814 var textureProperties = properties.get( renderTarget.texture );
19815
19816 if ( ! renderTarget ) return;
19817
19818 if ( textureProperties.__webglTexture !== undefined ) {
19819
19820 _gl.deleteTexture( textureProperties.__webglTexture );
19821
19822 }
19823
19824 if ( renderTarget.depthTexture ) {
19825
19826 renderTarget.depthTexture.dispose();
19827
19828 }
19829
19830 if ( renderTarget.isWebGLRenderTargetCube ) {
19831
19832 for ( var i = 0; i < 6; i ++ ) {
19833
19834 _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ] );
19835 if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer[ i ] );
19836
19837 }
19838
19839 } else {
19840
19841 _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer );
19842 if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer );
19843
19844 }
19845
19846 properties.remove( renderTarget.texture );
19847 properties.remove( renderTarget );
19848
19849 }
19850
19851 //
19852
19853
19854
19855 function setTexture2D( texture, slot ) {
19856
19857 var textureProperties = properties.get( texture );
19858
19859 if ( texture.isVideoTexture ) updateVideoTexture( texture );
19860
19861 if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
19862
19863 var image = texture.image;
19864
19865 if ( image === undefined ) {
19866
19867 console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is undefined', texture );
19868
19869 } else if ( image.complete === false ) {
19870
19871 console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is incomplete', texture );
19872
19873 } else {
19874
19875 uploadTexture( textureProperties, texture, slot );
19876 return;
19877
19878 }
19879
19880 }
19881
19882 state.activeTexture( _gl.TEXTURE0 + slot );
19883 state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture );
19884
19885 }
19886
19887 function setTextureCube( texture, slot ) {
19888
19889 var textureProperties = properties.get( texture );
19890
19891 if ( texture.image.length === 6 ) {
19892
19893 if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
19894
19895 if ( ! textureProperties.__image__webglTextureCube ) {
19896
19897 texture.addEventListener( 'dispose', onTextureDispose );
19898
19899 textureProperties.__image__webglTextureCube = _gl.createTexture();
19900
19901 info.memory.textures ++;
19902
19903 }
19904
19905 state.activeTexture( _gl.TEXTURE0 + slot );
19906 state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__image__webglTextureCube );
19907
19908 _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
19909
19910 var isCompressed = ( texture && texture.isCompressedTexture );
19911 var isDataTexture = ( texture.image[ 0 ] && texture.image[ 0 ].isDataTexture );
19912
19913 var cubeImage = [];
19914
19915 for ( var i = 0; i < 6; i ++ ) {
19916
19917 if ( ! isCompressed && ! isDataTexture ) {
19918
19919 cubeImage[ i ] = clampToMaxSize( texture.image[ i ], capabilities.maxCubemapSize );
19920
19921 } else {
19922
19923 cubeImage[ i ] = isDataTexture ? texture.image[ i ].image : texture.image[ i ];
19924
19925 }
19926
19927 }
19928
19929 var image = cubeImage[ 0 ],
19930 isPowerOfTwoImage = isPowerOfTwo( image ),
19931 glFormat = utils.convert( texture.format ),
19932 glType = utils.convert( texture.type );
19933
19934 setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, isPowerOfTwoImage );
19935
19936 for ( var i = 0; i < 6; i ++ ) {
19937
19938 if ( ! isCompressed ) {
19939
19940 if ( isDataTexture ) {
19941
19942 state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data );
19943
19944 } else {
19945
19946 state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, glFormat, glType, cubeImage[ i ] );
19947
19948 }
19949
19950 } else {
19951
19952 var mipmap, mipmaps = cubeImage[ i ].mipmaps;
19953
19954 for ( var j = 0, jl = mipmaps.length; j < jl; j ++ ) {
19955
19956 mipmap = mipmaps[ j ];
19957
19958 if ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) {
19959
19960 if ( state.getCompressedTextureFormats().indexOf( glFormat ) > - 1 ) {
19961
19962 state.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, mipmap.data );
19963
19964 } else {
19965
19966 console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()' );
19967
19968 }
19969
19970 } else {
19971
19972 state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
19973
19974 }
19975
19976 }
19977
19978 }
19979
19980 }
19981
19982 if ( ! isCompressed ) {
19983
19984 textureProperties.__maxMipLevel = 0;
19985
19986 } else {
19987
19988 textureProperties.__maxMipLevel = mipmaps.length - 1;
19989
19990 }
19991
19992 if ( textureNeedsGenerateMipmaps( texture, isPowerOfTwoImage ) ) {
19993
19994 // We assume images for cube map have the same size.
19995 generateMipmap( _gl.TEXTURE_CUBE_MAP, texture, image.width, image.height );
19996
19997 }
19998
19999 textureProperties.__version = texture.version;
20000
20001 if ( texture.onUpdate ) texture.onUpdate( texture );
20002
20003 } else {
20004
20005 state.activeTexture( _gl.TEXTURE0 + slot );
20006 state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__image__webglTextureCube );
20007
20008 }
20009
20010 }
20011
20012 }
20013
20014 function setTextureCubeDynamic( texture, slot ) {
20015
20016 state.activeTexture( _gl.TEXTURE0 + slot );
20017 state.bindTexture( _gl.TEXTURE_CUBE_MAP, properties.get( texture ).__webglTexture );
20018
20019 }
20020
20021 function setTextureParameters( textureType, texture, isPowerOfTwoImage ) {
20022
20023 var extension;
20024
20025 if ( isPowerOfTwoImage ) {
20026
20027 _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, utils.convert( texture.wrapS ) );
20028 _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, utils.convert( texture.wrapT ) );
20029
20030 _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, utils.convert( texture.magFilter ) );
20031 _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, utils.convert( texture.minFilter ) );
20032
20033 } else {
20034
20035 _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE );
20036 _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE );
20037
20038 if ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) {
20039
20040 console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping.', texture );
20041
20042 }
20043
20044 _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterFallback( texture.magFilter ) );
20045 _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterFallback( texture.minFilter ) );
20046
20047 if ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ) {
20048
20049 console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.', texture );
20050
20051 }
20052
20053 }
20054
20055 extension = extensions.get( 'EXT_texture_filter_anisotropic' );
20056
20057 if ( extension ) {
20058
20059 if ( texture.type === FloatType && extensions.get( 'OES_texture_float_linear' ) === null ) return;
20060 if ( texture.type === HalfFloatType && extensions.get( 'OES_texture_half_float_linear' ) === null ) return;
20061
20062 if ( texture.anisotropy > 1 || properties.get( texture ).__currentAnisotropy ) {
20063
20064 _gl.texParameterf( textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, capabilities.getMaxAnisotropy() ) );
20065 properties.get( texture ).__currentAnisotropy = texture.anisotropy;
20066
20067 }
20068
20069 }
20070
20071 }
20072
20073 function uploadTexture( textureProperties, texture, slot ) {
20074
20075 if ( textureProperties.__webglInit === undefined ) {
20076
20077 textureProperties.__webglInit = true;
20078
20079 texture.addEventListener( 'dispose', onTextureDispose );
20080
20081 textureProperties.__webglTexture = _gl.createTexture();
20082
20083 info.memory.textures ++;
20084
20085 }
20086
20087 state.activeTexture( _gl.TEXTURE0 + slot );
20088 state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture );
20089
20090 _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
20091 _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha );
20092 _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment );
20093
20094 var image = clampToMaxSize( texture.image, capabilities.maxTextureSize );
20095
20096 if ( textureNeedsPowerOfTwo( texture ) && isPowerOfTwo( image ) === false ) {
20097
20098 image = makePowerOfTwo( image );
20099
20100 }
20101
20102 var isPowerOfTwoImage = isPowerOfTwo( image ),
20103 glFormat = utils.convert( texture.format ),
20104 glType = utils.convert( texture.type );
20105
20106 setTextureParameters( _gl.TEXTURE_2D, texture, isPowerOfTwoImage );
20107
20108 var mipmap, mipmaps = texture.mipmaps;
20109
20110 if ( texture.isDepthTexture ) {
20111
20112 // populate depth texture with dummy data
20113
20114 var internalFormat = _gl.DEPTH_COMPONENT;
20115
20116 if ( texture.type === FloatType ) {
20117
20118 if ( ! _isWebGL2 ) throw new Error( 'Float Depth Texture only supported in WebGL2.0' );
20119 internalFormat = _gl.DEPTH_COMPONENT32F;
20120
20121 } else if ( _isWebGL2 ) {
20122
20123 // WebGL 2.0 requires signed internalformat for glTexImage2D
20124 internalFormat = _gl.DEPTH_COMPONENT16;
20125
20126 }
20127
20128 if ( texture.format === DepthFormat && internalFormat === _gl.DEPTH_COMPONENT ) {
20129
20130 // The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
20131 // DEPTH_COMPONENT and type is not UNSIGNED_SHORT or UNSIGNED_INT
20132 // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
20133 if ( texture.type !== UnsignedShortType && texture.type !== UnsignedIntType ) {
20134
20135 console.warn( 'THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture.' );
20136
20137 texture.type = UnsignedShortType;
20138 glType = utils.convert( texture.type );
20139
20140 }
20141
20142 }
20143
20144 // Depth stencil textures need the DEPTH_STENCIL internal format
20145 // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
20146 if ( texture.format === DepthStencilFormat ) {
20147
20148 internalFormat = _gl.DEPTH_STENCIL;
20149
20150 // The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
20151 // DEPTH_STENCIL and type is not UNSIGNED_INT_24_8_WEBGL.
20152 // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
20153 if ( texture.type !== UnsignedInt248Type ) {
20154
20155 console.warn( 'THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture.' );
20156
20157 texture.type = UnsignedInt248Type;
20158 glType = utils.convert( texture.type );
20159
20160 }
20161
20162 }
20163
20164 state.texImage2D( _gl.TEXTURE_2D, 0, internalFormat, image.width, image.height, 0, glFormat, glType, null );
20165
20166 } else if ( texture.isDataTexture ) {
20167
20168 // use manually created mipmaps if available
20169 // if there are no manual mipmaps
20170 // set 0 level mipmap and then use GL to generate other mipmap levels
20171
20172 if ( mipmaps.length > 0 && isPowerOfTwoImage ) {
20173
20174 for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
20175
20176 mipmap = mipmaps[ i ];
20177 state.texImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
20178
20179 }
20180
20181 texture.generateMipmaps = false;
20182 textureProperties.__maxMipLevel = mipmaps.length - 1;
20183
20184 } else {
20185
20186 state.texImage2D( _gl.TEXTURE_2D, 0, glFormat, image.width, image.height, 0, glFormat, glType, image.data );
20187 textureProperties.__maxMipLevel = 0;
20188
20189 }
20190
20191 } else if ( texture.isCompressedTexture ) {
20192
20193 for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
20194
20195 mipmap = mipmaps[ i ];
20196
20197 if ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) {
20198
20199 if ( state.getCompressedTextureFormats().indexOf( glFormat ) > - 1 ) {
20200
20201 state.compressedTexImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, mipmap.data );
20202
20203 } else {
20204
20205 console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' );
20206
20207 }
20208
20209 } else {
20210
20211 state.texImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
20212
20213 }
20214
20215 }
20216
20217 textureProperties.__maxMipLevel = mipmaps.length - 1;
20218
20219 } else {
20220
20221 // regular Texture (image, video, canvas)
20222
20223 // use manually created mipmaps if available
20224 // if there are no manual mipmaps
20225 // set 0 level mipmap and then use GL to generate other mipmap levels
20226
20227 if ( mipmaps.length > 0 && isPowerOfTwoImage ) {
20228
20229 for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
20230
20231 mipmap = mipmaps[ i ];
20232 state.texImage2D( _gl.TEXTURE_2D, i, glFormat, glFormat, glType, mipmap );
20233
20234 }
20235
20236 texture.generateMipmaps = false;
20237 textureProperties.__maxMipLevel = mipmaps.length - 1;
20238
20239 } else {
20240
20241 state.texImage2D( _gl.TEXTURE_2D, 0, glFormat, glFormat, glType, image );
20242 textureProperties.__maxMipLevel = 0;
20243
20244 }
20245
20246 }
20247
20248 if ( textureNeedsGenerateMipmaps( texture, isPowerOfTwoImage ) ) {
20249
20250 generateMipmap( _gl.TEXTURE_2D, texture, image.width, image.height );
20251
20252 }
20253
20254 textureProperties.__version = texture.version;
20255
20256 if ( texture.onUpdate ) texture.onUpdate( texture );
20257
20258 }
20259
20260 // Render targets
20261
20262 // Setup storage for target texture and bind it to correct framebuffer
20263 function setupFrameBufferTexture( framebuffer, renderTarget, attachment, textureTarget ) {
20264
20265 var glFormat = utils.convert( renderTarget.texture.format );
20266 var glType = utils.convert( renderTarget.texture.type );
20267 state.texImage2D( textureTarget, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
20268 _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
20269 _gl.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( renderTarget.texture ).__webglTexture, 0 );
20270 _gl.bindFramebuffer( _gl.FRAMEBUFFER, null );
20271
20272 }
20273
20274 // Setup storage for internal depth/stencil buffers and bind to correct framebuffer
20275 function setupRenderBufferStorage( renderbuffer, renderTarget ) {
20276
20277 _gl.bindRenderbuffer( _gl.RENDERBUFFER, renderbuffer );
20278
20279 if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) {
20280
20281 _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_COMPONENT16, renderTarget.width, renderTarget.height );
20282 _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
20283
20284 } else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
20285
20286 _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_STENCIL, renderTarget.width, renderTarget.height );
20287 _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
20288
20289 } else {
20290
20291 // FIXME: We don't support !depth !stencil
20292 _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.RGBA4, renderTarget.width, renderTarget.height );
20293
20294 }
20295
20296 _gl.bindRenderbuffer( _gl.RENDERBUFFER, null );
20297
20298 }
20299
20300 // Setup resources for a Depth Texture for a FBO (needs an extension)
20301 function setupDepthTexture( framebuffer, renderTarget ) {
20302
20303 var isCube = ( renderTarget && renderTarget.isWebGLRenderTargetCube );
20304 if ( isCube ) throw new Error( 'Depth Texture with cube render targets is not supported' );
20305
20306 _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
20307
20308 if ( ! ( renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture ) ) {
20309
20310 throw new Error( 'renderTarget.depthTexture must be an instance of THREE.DepthTexture' );
20311
20312 }
20313
20314 // upload an empty depth texture with framebuffer size
20315 if ( ! properties.get( renderTarget.depthTexture ).__webglTexture ||
20316 renderTarget.depthTexture.image.width !== renderTarget.width ||
20317 renderTarget.depthTexture.image.height !== renderTarget.height ) {
20318
20319 renderTarget.depthTexture.image.width = renderTarget.width;
20320 renderTarget.depthTexture.image.height = renderTarget.height;
20321 renderTarget.depthTexture.needsUpdate = true;
20322
20323 }
20324
20325 setTexture2D( renderTarget.depthTexture, 0 );
20326
20327 var webglDepthTexture = properties.get( renderTarget.depthTexture ).__webglTexture;
20328
20329 if ( renderTarget.depthTexture.format === DepthFormat ) {
20330
20331 _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 );
20332
20333 } else if ( renderTarget.depthTexture.format === DepthStencilFormat ) {
20334
20335 _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 );
20336
20337 } else {
20338
20339 throw new Error( 'Unknown depthTexture format' );
20340
20341 }
20342
20343 }
20344
20345 // Setup GL resources for a non-texture depth buffer
20346 function setupDepthRenderbuffer( renderTarget ) {
20347
20348 var renderTargetProperties = properties.get( renderTarget );
20349
20350 var isCube = ( renderTarget.isWebGLRenderTargetCube === true );
20351
20352 if ( renderTarget.depthTexture ) {
20353
20354 if ( isCube ) throw new Error( 'target.depthTexture not supported in Cube render targets' );
20355
20356 setupDepthTexture( renderTargetProperties.__webglFramebuffer, renderTarget );
20357
20358 } else {
20359
20360 if ( isCube ) {
20361
20362 renderTargetProperties.__webglDepthbuffer = [];
20363
20364 for ( var i = 0; i < 6; i ++ ) {
20365
20366 _gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer[ i ] );
20367 renderTargetProperties.__webglDepthbuffer[ i ] = _gl.createRenderbuffer();
20368 setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer[ i ], renderTarget );
20369
20370 }
20371
20372 } else {
20373
20374 _gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer );
20375 renderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer();
20376 setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer, renderTarget );
20377
20378 }
20379
20380 }
20381
20382 _gl.bindFramebuffer( _gl.FRAMEBUFFER, null );
20383
20384 }
20385
20386 // Set up GL resources for the render target
20387 function setupRenderTarget( renderTarget ) {
20388
20389 var renderTargetProperties = properties.get( renderTarget );
20390 var textureProperties = properties.get( renderTarget.texture );
20391
20392 renderTarget.addEventListener( 'dispose', onRenderTargetDispose );
20393
20394 textureProperties.__webglTexture = _gl.createTexture();
20395
20396 info.memory.textures ++;
20397
20398 var isCube = ( renderTarget.isWebGLRenderTargetCube === true );
20399 var isTargetPowerOfTwo = isPowerOfTwo( renderTarget );
20400
20401 // Setup framebuffer
20402
20403 if ( isCube ) {
20404
20405 renderTargetProperties.__webglFramebuffer = [];
20406
20407 for ( var i = 0; i < 6; i ++ ) {
20408
20409 renderTargetProperties.__webglFramebuffer[ i ] = _gl.createFramebuffer();
20410
20411 }
20412
20413 } else {
20414
20415 renderTargetProperties.__webglFramebuffer = _gl.createFramebuffer();
20416
20417 }
20418
20419 // Setup color buffer
20420
20421 if ( isCube ) {
20422
20423 state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture );
20424 setTextureParameters( _gl.TEXTURE_CUBE_MAP, renderTarget.texture, isTargetPowerOfTwo );
20425
20426 for ( var i = 0; i < 6; i ++ ) {
20427
20428 setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ], renderTarget, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i );
20429
20430 }
20431
20432 if ( textureNeedsGenerateMipmaps( renderTarget.texture, isTargetPowerOfTwo ) ) {
20433
20434 generateMipmap( _gl.TEXTURE_CUBE_MAP, renderTarget.texture, renderTarget.width, renderTarget.height );
20435
20436 }
20437
20438 state.bindTexture( _gl.TEXTURE_CUBE_MAP, null );
20439
20440 } else {
20441
20442 state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture );
20443 setTextureParameters( _gl.TEXTURE_2D, renderTarget.texture, isTargetPowerOfTwo );
20444 setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D );
20445
20446 if ( textureNeedsGenerateMipmaps( renderTarget.texture, isTargetPowerOfTwo ) ) {
20447
20448 generateMipmap( _gl.TEXTURE_2D, renderTarget.texture, renderTarget.width, renderTarget.height );
20449
20450 }
20451
20452 state.bindTexture( _gl.TEXTURE_2D, null );
20453
20454 }
20455
20456 // Setup depth and stencil buffers
20457
20458 if ( renderTarget.depthBuffer ) {
20459
20460 setupDepthRenderbuffer( renderTarget );
20461
20462 }
20463
20464 }
20465
20466 function updateRenderTargetMipmap( renderTarget ) {
20467
20468 var texture = renderTarget.texture;
20469 var isTargetPowerOfTwo = isPowerOfTwo( renderTarget );
20470
20471 if ( textureNeedsGenerateMipmaps( texture, isTargetPowerOfTwo ) ) {
20472
20473 var target = renderTarget.isWebGLRenderTargetCube ? _gl.TEXTURE_CUBE_MAP : _gl.TEXTURE_2D;
20474 var webglTexture = properties.get( texture ).__webglTexture;
20475
20476 state.bindTexture( target, webglTexture );
20477 generateMipmap( target, texture, renderTarget.width, renderTarget.height );
20478 state.bindTexture( target, null );
20479
20480 }
20481
20482 }
20483
20484 function updateVideoTexture( texture ) {
20485
20486 var id = texture.id;
20487 var frame = info.render.frame;
20488
20489 // Check the last frame we updated the VideoTexture
20490
20491 if ( _videoTextures[ id ] !== frame ) {
20492
20493 _videoTextures[ id ] = frame;
20494 texture.update();
20495
20496 }
20497
20498 }
20499
20500 this.setTexture2D = setTexture2D;
20501 this.setTextureCube = setTextureCube;
20502 this.setTextureCubeDynamic = setTextureCubeDynamic;
20503 this.setupRenderTarget = setupRenderTarget;
20504 this.updateRenderTargetMipmap = updateRenderTargetMipmap;
20505
20506}
20507
20508/**
20509 * @author thespite / http://www.twitter.com/thespite
20510 */
20511
20512function WebGLUtils( gl, extensions ) {
20513
20514 function convert( p ) {
20515
20516 var extension;
20517
20518 if ( p === RepeatWrapping ) return gl.REPEAT;
20519 if ( p === ClampToEdgeWrapping ) return gl.CLAMP_TO_EDGE;
20520 if ( p === MirroredRepeatWrapping ) return gl.MIRRORED_REPEAT;
20521
20522 if ( p === NearestFilter ) return gl.NEAREST;
20523 if ( p === NearestMipMapNearestFilter ) return gl.NEAREST_MIPMAP_NEAREST;
20524 if ( p === NearestMipMapLinearFilter ) return gl.NEAREST_MIPMAP_LINEAR;
20525
20526 if ( p === LinearFilter ) return gl.LINEAR;
20527 if ( p === LinearMipMapNearestFilter ) return gl.LINEAR_MIPMAP_NEAREST;
20528 if ( p === LinearMipMapLinearFilter ) return gl.LINEAR_MIPMAP_LINEAR;
20529
20530 if ( p === UnsignedByteType ) return gl.UNSIGNED_BYTE;
20531 if ( p === UnsignedShort4444Type ) return gl.UNSIGNED_SHORT_4_4_4_4;
20532 if ( p === UnsignedShort5551Type ) return gl.UNSIGNED_SHORT_5_5_5_1;
20533 if ( p === UnsignedShort565Type ) return gl.UNSIGNED_SHORT_5_6_5;
20534
20535 if ( p === ByteType ) return gl.BYTE;
20536 if ( p === ShortType ) return gl.SHORT;
20537 if ( p === UnsignedShortType ) return gl.UNSIGNED_SHORT;
20538 if ( p === IntType ) return gl.INT;
20539 if ( p === UnsignedIntType ) return gl.UNSIGNED_INT;
20540 if ( p === FloatType ) return gl.FLOAT;
20541
20542 if ( p === HalfFloatType ) {
20543
20544 extension = extensions.get( 'OES_texture_half_float' );
20545
20546 if ( extension !== null ) return extension.HALF_FLOAT_OES;
20547
20548 }
20549
20550 if ( p === AlphaFormat ) return gl.ALPHA;
20551 if ( p === RGBFormat ) return gl.RGB;
20552 if ( p === RGBAFormat ) return gl.RGBA;
20553 if ( p === LuminanceFormat ) return gl.LUMINANCE;
20554 if ( p === LuminanceAlphaFormat ) return gl.LUMINANCE_ALPHA;
20555 if ( p === DepthFormat ) return gl.DEPTH_COMPONENT;
20556 if ( p === DepthStencilFormat ) return gl.DEPTH_STENCIL;
20557
20558 if ( p === AddEquation ) return gl.FUNC_ADD;
20559 if ( p === SubtractEquation ) return gl.FUNC_SUBTRACT;
20560 if ( p === ReverseSubtractEquation ) return gl.FUNC_REVERSE_SUBTRACT;
20561
20562 if ( p === ZeroFactor ) return gl.ZERO;
20563 if ( p === OneFactor ) return gl.ONE;
20564 if ( p === SrcColorFactor ) return gl.SRC_COLOR;
20565 if ( p === OneMinusSrcColorFactor ) return gl.ONE_MINUS_SRC_COLOR;
20566 if ( p === SrcAlphaFactor ) return gl.SRC_ALPHA;
20567 if ( p === OneMinusSrcAlphaFactor ) return gl.ONE_MINUS_SRC_ALPHA;
20568 if ( p === DstAlphaFactor ) return gl.DST_ALPHA;
20569 if ( p === OneMinusDstAlphaFactor ) return gl.ONE_MINUS_DST_ALPHA;
20570
20571 if ( p === DstColorFactor ) return gl.DST_COLOR;
20572 if ( p === OneMinusDstColorFactor ) return gl.ONE_MINUS_DST_COLOR;
20573 if ( p === SrcAlphaSaturateFactor ) return gl.SRC_ALPHA_SATURATE;
20574
20575 if ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format ||
20576 p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) {
20577
20578 extension = extensions.get( 'WEBGL_compressed_texture_s3tc' );
20579
20580 if ( extension !== null ) {
20581
20582 if ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT;
20583 if ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT;
20584 if ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT;
20585 if ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT;
20586
20587 }
20588
20589 }
20590
20591 if ( p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format ||
20592 p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format ) {
20593
20594 extension = extensions.get( 'WEBGL_compressed_texture_pvrtc' );
20595
20596 if ( extension !== null ) {
20597
20598 if ( p === RGB_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
20599 if ( p === RGB_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
20600 if ( p === RGBA_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
20601 if ( p === RGBA_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
20602
20603 }
20604
20605 }
20606
20607 if ( p === RGB_ETC1_Format ) {
20608
20609 extension = extensions.get( 'WEBGL_compressed_texture_etc1' );
20610
20611 if ( extension !== null ) return extension.COMPRESSED_RGB_ETC1_WEBGL;
20612
20613 }
20614
20615 if ( p === RGBA_ASTC_4x4_Format || p === RGBA_ASTC_5x4_Format || p === RGBA_ASTC_5x5_Format ||
20616 p === RGBA_ASTC_6x5_Format || p === RGBA_ASTC_6x6_Format || p === RGBA_ASTC_8x5_Format ||
20617 p === RGBA_ASTC_8x6_Format || p === RGBA_ASTC_8x8_Format || p === RGBA_ASTC_10x5_Format ||
20618 p === RGBA_ASTC_10x6_Format || p === RGBA_ASTC_10x8_Format || p === RGBA_ASTC_10x10_Format ||
20619 p === RGBA_ASTC_12x10_Format || p === RGBA_ASTC_12x12_Format ) {
20620
20621 extension = extensions.get( 'WEBGL_compressed_texture_astc' );
20622
20623 if ( extension !== null ) {
20624
20625 return p;
20626
20627 }
20628
20629 }
20630
20631 if ( p === MinEquation || p === MaxEquation ) {
20632
20633 extension = extensions.get( 'EXT_blend_minmax' );
20634
20635 if ( extension !== null ) {
20636
20637 if ( p === MinEquation ) return extension.MIN_EXT;
20638 if ( p === MaxEquation ) return extension.MAX_EXT;
20639
20640 }
20641
20642 }
20643
20644 if ( p === UnsignedInt248Type ) {
20645
20646 extension = extensions.get( 'WEBGL_depth_texture' );
20647
20648 if ( extension !== null ) return extension.UNSIGNED_INT_24_8_WEBGL;
20649
20650 }
20651
20652 return 0;
20653
20654 }
20655
20656 return { convert: convert };
20657
20658}
20659
20660/**
20661 * @author mrdoob / http://mrdoob.com/
20662 * @author greggman / http://games.greggman.com/
20663 * @author zz85 / http://www.lab4games.net/zz85/blog
20664 * @author tschw
20665 */
20666
20667function PerspectiveCamera( fov, aspect, near, far ) {
20668
20669 Camera.call( this );
20670
20671 this.type = 'PerspectiveCamera';
20672
20673 this.fov = fov !== undefined ? fov : 50;
20674 this.zoom = 1;
20675
20676 this.near = near !== undefined ? near : 0.1;
20677 this.far = far !== undefined ? far : 2000;
20678 this.focus = 10;
20679
20680 this.aspect = aspect !== undefined ? aspect : 1;
20681 this.view = null;
20682
20683 this.filmGauge = 35; // width of the film (default in millimeters)
20684 this.filmOffset = 0; // horizontal film offset (same unit as gauge)
20685
20686 this.updateProjectionMatrix();
20687
20688}
20689
20690PerspectiveCamera.prototype = Object.assign( Object.create( Camera.prototype ), {
20691
20692 constructor: PerspectiveCamera,
20693
20694 isPerspectiveCamera: true,
20695
20696 copy: function ( source, recursive ) {
20697
20698 Camera.prototype.copy.call( this, source, recursive );
20699
20700 this.fov = source.fov;
20701 this.zoom = source.zoom;
20702
20703 this.near = source.near;
20704 this.far = source.far;
20705 this.focus = source.focus;
20706
20707 this.aspect = source.aspect;
20708 this.view = source.view === null ? null : Object.assign( {}, source.view );
20709
20710 this.filmGauge = source.filmGauge;
20711 this.filmOffset = source.filmOffset;
20712
20713 return this;
20714
20715 },
20716
20717 /**
20718 * Sets the FOV by focal length in respect to the current .filmGauge.
20719 *
20720 * The default film gauge is 35, so that the focal length can be specified for
20721 * a 35mm (full frame) camera.
20722 *
20723 * Values for focal length and film gauge must have the same unit.
20724 */
20725 setFocalLength: function ( focalLength ) {
20726
20727 // see http://www.bobatkins.com/photography/technical/field_of_view.html
20728 var vExtentSlope = 0.5 * this.getFilmHeight() / focalLength;
20729
20730 this.fov = _Math.RAD2DEG * 2 * Math.atan( vExtentSlope );
20731 this.updateProjectionMatrix();
20732
20733 },
20734
20735 /**
20736 * Calculates the focal length from the current .fov and .filmGauge.
20737 */
20738 getFocalLength: function () {
20739
20740 var vExtentSlope = Math.tan( _Math.DEG2RAD * 0.5 * this.fov );
20741
20742 return 0.5 * this.getFilmHeight() / vExtentSlope;
20743
20744 },
20745
20746 getEffectiveFOV: function () {
20747
20748 return _Math.RAD2DEG * 2 * Math.atan(
20749 Math.tan( _Math.DEG2RAD * 0.5 * this.fov ) / this.zoom );
20750
20751 },
20752
20753 getFilmWidth: function () {
20754
20755 // film not completely covered in portrait format (aspect < 1)
20756 return this.filmGauge * Math.min( this.aspect, 1 );
20757
20758 },
20759
20760 getFilmHeight: function () {
20761
20762 // film not completely covered in landscape format (aspect > 1)
20763 return this.filmGauge / Math.max( this.aspect, 1 );
20764
20765 },
20766
20767 /**
20768 * Sets an offset in a larger frustum. This is useful for multi-window or
20769 * multi-monitor/multi-machine setups.
20770 *
20771 * For example, if you have 3x2 monitors and each monitor is 1920x1080 and
20772 * the monitors are in grid like this
20773 *
20774 * +---+---+---+
20775 * | A | B | C |
20776 * +---+---+---+
20777 * | D | E | F |
20778 * +---+---+---+
20779 *
20780 * then for each monitor you would call it like this
20781 *
20782 * var w = 1920;
20783 * var h = 1080;
20784 * var fullWidth = w * 3;
20785 * var fullHeight = h * 2;
20786 *
20787 * --A--
20788 * camera.setOffset( fullWidth, fullHeight, w * 0, h * 0, w, h );
20789 * --B--
20790 * camera.setOffset( fullWidth, fullHeight, w * 1, h * 0, w, h );
20791 * --C--
20792 * camera.setOffset( fullWidth, fullHeight, w * 2, h * 0, w, h );
20793 * --D--
20794 * camera.setOffset( fullWidth, fullHeight, w * 0, h * 1, w, h );
20795 * --E--
20796 * camera.setOffset( fullWidth, fullHeight, w * 1, h * 1, w, h );
20797 * --F--
20798 * camera.setOffset( fullWidth, fullHeight, w * 2, h * 1, w, h );
20799 *
20800 * Note there is no reason monitors have to be the same size or in a grid.
20801 */
20802 setViewOffset: function ( fullWidth, fullHeight, x, y, width, height ) {
20803
20804 this.aspect = fullWidth / fullHeight;
20805
20806 if ( this.view === null ) {
20807
20808 this.view = {
20809 enabled: true,
20810 fullWidth: 1,
20811 fullHeight: 1,
20812 offsetX: 0,
20813 offsetY: 0,
20814 width: 1,
20815 height: 1
20816 };
20817
20818 }
20819
20820 this.view.enabled = true;
20821 this.view.fullWidth = fullWidth;
20822 this.view.fullHeight = fullHeight;
20823 this.view.offsetX = x;
20824 this.view.offsetY = y;
20825 this.view.width = width;
20826 this.view.height = height;
20827
20828 this.updateProjectionMatrix();
20829
20830 },
20831
20832 clearViewOffset: function () {
20833
20834 if ( this.view !== null ) {
20835
20836 this.view.enabled = false;
20837
20838 }
20839
20840 this.updateProjectionMatrix();
20841
20842 },
20843
20844 updateProjectionMatrix: function () {
20845
20846 var near = this.near,
20847 top = near * Math.tan(
20848 _Math.DEG2RAD * 0.5 * this.fov ) / this.zoom,
20849 height = 2 * top,
20850 width = this.aspect * height,
20851 left = - 0.5 * width,
20852 view = this.view;
20853
20854 if ( this.view !== null && this.view.enabled ) {
20855
20856 var fullWidth = view.fullWidth,
20857 fullHeight = view.fullHeight;
20858
20859 left += view.offsetX * width / fullWidth;
20860 top -= view.offsetY * height / fullHeight;
20861 width *= view.width / fullWidth;
20862 height *= view.height / fullHeight;
20863
20864 }
20865
20866 var skew = this.filmOffset;
20867 if ( skew !== 0 ) left += near * skew / this.getFilmWidth();
20868
20869 this.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far );
20870
20871 },
20872
20873 toJSON: function ( meta ) {
20874
20875 var data = Object3D.prototype.toJSON.call( this, meta );
20876
20877 data.object.fov = this.fov;
20878 data.object.zoom = this.zoom;
20879
20880 data.object.near = this.near;
20881 data.object.far = this.far;
20882 data.object.focus = this.focus;
20883
20884 data.object.aspect = this.aspect;
20885
20886 if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
20887
20888 data.object.filmGauge = this.filmGauge;
20889 data.object.filmOffset = this.filmOffset;
20890
20891 return data;
20892
20893 }
20894
20895} );
20896
20897/**
20898 * @author mrdoob / http://mrdoob.com/
20899 */
20900
20901function ArrayCamera( array ) {
20902
20903 PerspectiveCamera.call( this );
20904
20905 this.cameras = array || [];
20906
20907}
20908
20909ArrayCamera.prototype = Object.assign( Object.create( PerspectiveCamera.prototype ), {
20910
20911 constructor: ArrayCamera,
20912
20913 isArrayCamera: true
20914
20915} );
20916
20917/**
20918 * @author mrdoob / http://mrdoob.com/
20919 */
20920
20921function WebVRManager( renderer ) {
20922
20923 var scope = this;
20924
20925 var device = null;
20926 var frameData = null;
20927
20928 var poseTarget = null;
20929
20930 var standingMatrix = new Matrix4();
20931 var standingMatrixInverse = new Matrix4();
20932
20933 if ( typeof window !== 'undefined' && 'VRFrameData' in window ) {
20934
20935 frameData = new window.VRFrameData();
20936 window.addEventListener( 'vrdisplaypresentchange', onVRDisplayPresentChange, false );
20937
20938 }
20939
20940 var matrixWorldInverse = new Matrix4();
20941 var tempQuaternion = new Quaternion();
20942 var tempPosition = new Vector3();
20943
20944 var cameraL = new PerspectiveCamera();
20945 cameraL.bounds = new Vector4( 0.0, 0.0, 0.5, 1.0 );
20946 cameraL.layers.enable( 1 );
20947
20948 var cameraR = new PerspectiveCamera();
20949 cameraR.bounds = new Vector4( 0.5, 0.0, 0.5, 1.0 );
20950 cameraR.layers.enable( 2 );
20951
20952 var cameraVR = new ArrayCamera( [ cameraL, cameraR ] );
20953 cameraVR.layers.enable( 1 );
20954 cameraVR.layers.enable( 2 );
20955
20956 //
20957
20958 function isPresenting() {
20959
20960 return device !== null && device.isPresenting === true;
20961
20962 }
20963
20964 var currentSize, currentPixelRatio;
20965
20966 function onVRDisplayPresentChange() {
20967
20968 if ( isPresenting() ) {
20969
20970 var eyeParameters = device.getEyeParameters( 'left' );
20971 var renderWidth = eyeParameters.renderWidth;
20972 var renderHeight = eyeParameters.renderHeight;
20973
20974 currentPixelRatio = renderer.getPixelRatio();
20975 currentSize = renderer.getSize();
20976
20977 renderer.setDrawingBufferSize( renderWidth * 2, renderHeight, 1 );
20978
20979 } else if ( scope.enabled ) {
20980
20981 renderer.setDrawingBufferSize( currentSize.width, currentSize.height, currentPixelRatio );
20982
20983 }
20984
20985 }
20986
20987 //
20988
20989 this.enabled = false;
20990 this.userHeight = 1.6;
20991
20992 this.getDevice = function () {
20993
20994 return device;
20995
20996 };
20997
20998 this.setDevice = function ( value ) {
20999
21000 if ( value !== undefined ) device = value;
21001
21002 };
21003
21004 this.setPoseTarget = function ( object ) {
21005
21006 if ( object !== undefined ) poseTarget = object;
21007
21008 };
21009
21010 this.getCamera = function ( camera ) {
21011
21012 if ( device === null ) return camera;
21013
21014 device.depthNear = camera.near;
21015 device.depthFar = camera.far;
21016
21017 device.getFrameData( frameData );
21018
21019 //
21020
21021 var stageParameters = device.stageParameters;
21022
21023 if ( stageParameters ) {
21024
21025 standingMatrix.fromArray( stageParameters.sittingToStandingTransform );
21026
21027 } else {
21028
21029 standingMatrix.makeTranslation( 0, scope.userHeight, 0 );
21030
21031 }
21032
21033
21034 var pose = frameData.pose;
21035 var poseObject = poseTarget !== null ? poseTarget : camera;
21036
21037 // We want to manipulate poseObject by its position and quaternion components since users may rely on them.
21038 poseObject.matrix.copy( standingMatrix );
21039 poseObject.matrix.decompose( poseObject.position, poseObject.quaternion, poseObject.scale );
21040
21041 if ( pose.orientation !== null ) {
21042
21043 tempQuaternion.fromArray( pose.orientation );
21044 poseObject.quaternion.multiply( tempQuaternion );
21045
21046 }
21047
21048 if ( pose.position !== null ) {
21049
21050 tempQuaternion.setFromRotationMatrix( standingMatrix );
21051 tempPosition.fromArray( pose.position );
21052 tempPosition.applyQuaternion( tempQuaternion );
21053 poseObject.position.add( tempPosition );
21054
21055 }
21056
21057 poseObject.updateMatrixWorld();
21058
21059 if ( device.isPresenting === false ) return camera;
21060
21061 //
21062
21063 cameraL.near = camera.near;
21064 cameraR.near = camera.near;
21065
21066 cameraL.far = camera.far;
21067 cameraR.far = camera.far;
21068
21069 cameraVR.matrixWorld.copy( camera.matrixWorld );
21070 cameraVR.matrixWorldInverse.copy( camera.matrixWorldInverse );
21071
21072 cameraL.matrixWorldInverse.fromArray( frameData.leftViewMatrix );
21073 cameraR.matrixWorldInverse.fromArray( frameData.rightViewMatrix );
21074
21075 // TODO (mrdoob) Double check this code
21076
21077 standingMatrixInverse.getInverse( standingMatrix );
21078
21079 cameraL.matrixWorldInverse.multiply( standingMatrixInverse );
21080 cameraR.matrixWorldInverse.multiply( standingMatrixInverse );
21081
21082 var parent = poseObject.parent;
21083
21084 if ( parent !== null ) {
21085
21086 matrixWorldInverse.getInverse( parent.matrixWorld );
21087
21088 cameraL.matrixWorldInverse.multiply( matrixWorldInverse );
21089 cameraR.matrixWorldInverse.multiply( matrixWorldInverse );
21090
21091 }
21092
21093 // envMap and Mirror needs camera.matrixWorld
21094
21095 cameraL.matrixWorld.getInverse( cameraL.matrixWorldInverse );
21096 cameraR.matrixWorld.getInverse( cameraR.matrixWorldInverse );
21097
21098 cameraL.projectionMatrix.fromArray( frameData.leftProjectionMatrix );
21099 cameraR.projectionMatrix.fromArray( frameData.rightProjectionMatrix );
21100
21101 // HACK (mrdoob)
21102 // https://github.com/w3c/webvr/issues/203
21103
21104 cameraVR.projectionMatrix.copy( cameraL.projectionMatrix );
21105
21106 //
21107
21108 var layers = device.getLayers();
21109
21110 if ( layers.length ) {
21111
21112 var layer = layers[ 0 ];
21113
21114 if ( layer.leftBounds !== null && layer.leftBounds.length === 4 ) {
21115
21116 cameraL.bounds.fromArray( layer.leftBounds );
21117
21118 }
21119
21120 if ( layer.rightBounds !== null && layer.rightBounds.length === 4 ) {
21121
21122 cameraR.bounds.fromArray( layer.rightBounds );
21123
21124 }
21125
21126 }
21127
21128 return cameraVR;
21129
21130 };
21131
21132 this.getStandingMatrix = function () {
21133
21134 return standingMatrix;
21135
21136 };
21137
21138 this.submitFrame = function () {
21139
21140 if ( isPresenting() ) device.submitFrame();
21141
21142 };
21143
21144 this.dispose = function () {
21145
21146 if ( typeof window !== 'undefined' ) {
21147
21148 window.removeEventListener( 'vrdisplaypresentchange', onVRDisplayPresentChange );
21149
21150 }
21151
21152 };
21153
21154}
21155
21156/**
21157 * @author supereggbert / http://www.paulbrunt.co.uk/
21158 * @author mrdoob / http://mrdoob.com/
21159 * @author alteredq / http://alteredqualia.com/
21160 * @author szimek / https://github.com/szimek/
21161 * @author tschw
21162 */
21163
21164function WebGLRenderer( parameters ) {
21165
21166 console.log( 'THREE.WebGLRenderer', REVISION );
21167
21168 parameters = parameters || {};
21169
21170 var _canvas = parameters.canvas !== undefined ? parameters.canvas : document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ),
21171 _context = parameters.context !== undefined ? parameters.context : null,
21172
21173 _alpha = parameters.alpha !== undefined ? parameters.alpha : false,
21174 _depth = parameters.depth !== undefined ? parameters.depth : true,
21175 _stencil = parameters.stencil !== undefined ? parameters.stencil : true,
21176 _antialias = parameters.antialias !== undefined ? parameters.antialias : false,
21177 _premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true,
21178 _preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false,
21179 _powerPreference = parameters.powerPreference !== undefined ? parameters.powerPreference : 'default';
21180
21181 var currentRenderList = null;
21182 var currentRenderState = null;
21183
21184 // public properties
21185
21186 this.domElement = _canvas;
21187 this.context = null;
21188
21189 // clearing
21190
21191 this.autoClear = true;
21192 this.autoClearColor = true;
21193 this.autoClearDepth = true;
21194 this.autoClearStencil = true;
21195
21196 // scene graph
21197
21198 this.sortObjects = true;
21199
21200 // user-defined clipping
21201
21202 this.clippingPlanes = [];
21203 this.localClippingEnabled = false;
21204
21205 // physically based shading
21206
21207 this.gammaFactor = 2.0; // for backwards compatibility
21208 this.gammaInput = false;
21209 this.gammaOutput = false;
21210
21211 // physical lights
21212
21213 this.physicallyCorrectLights = false;
21214
21215 // tone mapping
21216
21217 this.toneMapping = LinearToneMapping;
21218 this.toneMappingExposure = 1.0;
21219 this.toneMappingWhitePoint = 1.0;
21220
21221 // morphs
21222
21223 this.maxMorphTargets = 8;
21224 this.maxMorphNormals = 4;
21225
21226 // internal properties
21227
21228 var _this = this,
21229
21230 _isContextLost = false,
21231
21232 // internal state cache
21233
21234 _currentRenderTarget = null,
21235 _currentFramebuffer = null,
21236 _currentMaterialId = - 1,
21237 _currentGeometryProgram = '',
21238
21239 _currentCamera = null,
21240 _currentArrayCamera = null,
21241
21242 _currentViewport = new Vector4(),
21243 _currentScissor = new Vector4(),
21244 _currentScissorTest = null,
21245
21246 //
21247
21248 _usedTextureUnits = 0,
21249
21250 //
21251
21252 _width = _canvas.width,
21253 _height = _canvas.height,
21254
21255 _pixelRatio = 1,
21256
21257 _viewport = new Vector4( 0, 0, _width, _height ),
21258 _scissor = new Vector4( 0, 0, _width, _height ),
21259 _scissorTest = false,
21260
21261 // frustum
21262
21263 _frustum = new Frustum(),
21264
21265 // clipping
21266
21267 _clipping = new WebGLClipping(),
21268 _clippingEnabled = false,
21269 _localClippingEnabled = false,
21270
21271 // camera matrices cache
21272
21273 _projScreenMatrix = new Matrix4(),
21274
21275 _vector3 = new Vector3();
21276
21277 function getTargetPixelRatio() {
21278
21279 return _currentRenderTarget === null ? _pixelRatio : 1;
21280
21281 }
21282
21283 // initialize
21284
21285 var _gl;
21286
21287 try {
21288
21289 var contextAttributes = {
21290 alpha: _alpha,
21291 depth: _depth,
21292 stencil: _stencil,
21293 antialias: _antialias,
21294 premultipliedAlpha: _premultipliedAlpha,
21295 preserveDrawingBuffer: _preserveDrawingBuffer,
21296 powerPreference: _powerPreference
21297 };
21298
21299 // event listeners must be registered before WebGL context is created, see #12753
21300
21301 _canvas.addEventListener( 'webglcontextlost', onContextLost, false );
21302 _canvas.addEventListener( 'webglcontextrestored', onContextRestore, false );
21303
21304 _gl = _context || _canvas.getContext( 'webgl', contextAttributes ) || _canvas.getContext( 'experimental-webgl', contextAttributes );
21305
21306 if ( _gl === null ) {
21307
21308 if ( _canvas.getContext( 'webgl' ) !== null ) {
21309
21310 throw new Error( 'Error creating WebGL context with your selected attributes.' );
21311
21312 } else {
21313
21314 throw new Error( 'Error creating WebGL context.' );
21315
21316 }
21317
21318 }
21319
21320 // Some experimental-webgl implementations do not have getShaderPrecisionFormat
21321
21322 if ( _gl.getShaderPrecisionFormat === undefined ) {
21323
21324 _gl.getShaderPrecisionFormat = function () {
21325
21326 return { 'rangeMin': 1, 'rangeMax': 1, 'precision': 1 };
21327
21328 };
21329
21330 }
21331
21332 } catch ( error ) {
21333
21334 console.error( 'THREE.WebGLRenderer: ' + error.message );
21335
21336 }
21337
21338 var extensions, capabilities, state, info;
21339 var properties, textures, attributes, geometries, objects;
21340 var programCache, renderLists, renderStates;
21341
21342 var background, morphtargets, bufferRenderer, indexedBufferRenderer;
21343 var spriteRenderer;
21344
21345 var utils;
21346
21347 function initGLContext() {
21348
21349 extensions = new WebGLExtensions( _gl );
21350 extensions.get( 'WEBGL_depth_texture' );
21351 extensions.get( 'OES_texture_float' );
21352 extensions.get( 'OES_texture_float_linear' );
21353 extensions.get( 'OES_texture_half_float' );
21354 extensions.get( 'OES_texture_half_float_linear' );
21355 extensions.get( 'OES_standard_derivatives' );
21356 extensions.get( 'OES_element_index_uint' );
21357 extensions.get( 'ANGLE_instanced_arrays' );
21358
21359 utils = new WebGLUtils( _gl, extensions );
21360
21361 capabilities = new WebGLCapabilities( _gl, extensions, parameters );
21362
21363 state = new WebGLState( _gl, extensions, utils );
21364 state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ) );
21365 state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ) );
21366
21367 info = new WebGLInfo( _gl );
21368 properties = new WebGLProperties();
21369 textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info );
21370 attributes = new WebGLAttributes( _gl );
21371 geometries = new WebGLGeometries( _gl, attributes, info );
21372 objects = new WebGLObjects( geometries, info );
21373 morphtargets = new WebGLMorphtargets( _gl );
21374 programCache = new WebGLPrograms( _this, extensions, capabilities );
21375 renderLists = new WebGLRenderLists();
21376 renderStates = new WebGLRenderStates();
21377
21378 background = new WebGLBackground( _this, state, geometries, _premultipliedAlpha );
21379
21380 bufferRenderer = new WebGLBufferRenderer( _gl, extensions, info );
21381 indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, info );
21382
21383 spriteRenderer = new WebGLSpriteRenderer( _this, _gl, state, textures, capabilities );
21384
21385 info.programs = programCache.programs;
21386
21387 _this.context = _gl;
21388 _this.capabilities = capabilities;
21389 _this.extensions = extensions;
21390 _this.properties = properties;
21391 _this.renderLists = renderLists;
21392 _this.state = state;
21393 _this.info = info;
21394
21395 }
21396
21397 initGLContext();
21398
21399 // vr
21400
21401 var vr = new WebVRManager( _this );
21402
21403 this.vr = vr;
21404
21405 // shadow map
21406
21407 var shadowMap = new WebGLShadowMap( _this, objects, capabilities.maxTextureSize );
21408
21409 this.shadowMap = shadowMap;
21410
21411 // API
21412
21413 this.getContext = function () {
21414
21415 return _gl;
21416
21417 };
21418
21419 this.getContextAttributes = function () {
21420
21421 return _gl.getContextAttributes();
21422
21423 };
21424
21425 this.forceContextLoss = function () {
21426
21427 var extension = extensions.get( 'WEBGL_lose_context' );
21428 if ( extension ) extension.loseContext();
21429
21430 };
21431
21432 this.forceContextRestore = function () {
21433
21434 var extension = extensions.get( 'WEBGL_lose_context' );
21435 if ( extension ) extension.restoreContext();
21436
21437 };
21438
21439 this.getPixelRatio = function () {
21440
21441 return _pixelRatio;
21442
21443 };
21444
21445 this.setPixelRatio = function ( value ) {
21446
21447 if ( value === undefined ) return;
21448
21449 _pixelRatio = value;
21450
21451 this.setSize( _width, _height, false );
21452
21453 };
21454
21455 this.getSize = function () {
21456
21457 return {
21458 width: _width,
21459 height: _height
21460 };
21461
21462 };
21463
21464 this.setSize = function ( width, height, updateStyle ) {
21465
21466 var device = vr.getDevice();
21467
21468 if ( device && device.isPresenting ) {
21469
21470 console.warn( 'THREE.WebGLRenderer: Can\'t change size while VR device is presenting.' );
21471 return;
21472
21473 }
21474
21475 _width = width;
21476 _height = height;
21477
21478 _canvas.width = width * _pixelRatio;
21479 _canvas.height = height * _pixelRatio;
21480
21481 if ( updateStyle !== false ) {
21482
21483 _canvas.style.width = width + 'px';
21484 _canvas.style.height = height + 'px';
21485
21486 }
21487
21488 this.setViewport( 0, 0, width, height );
21489
21490 };
21491
21492 this.getDrawingBufferSize = function () {
21493
21494 return {
21495 width: _width * _pixelRatio,
21496 height: _height * _pixelRatio
21497 };
21498
21499 };
21500
21501 this.setDrawingBufferSize = function ( width, height, pixelRatio ) {
21502
21503 _width = width;
21504 _height = height;
21505
21506 _pixelRatio = pixelRatio;
21507
21508 _canvas.width = width * pixelRatio;
21509 _canvas.height = height * pixelRatio;
21510
21511 this.setViewport( 0, 0, width, height );
21512
21513 };
21514
21515 this.getCurrentViewport = function () {
21516
21517 return _currentViewport;
21518
21519 };
21520
21521 this.setViewport = function ( x, y, width, height ) {
21522
21523 _viewport.set( x, _height - y - height, width, height );
21524 state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ) );
21525
21526 };
21527
21528 this.setScissor = function ( x, y, width, height ) {
21529
21530 _scissor.set( x, _height - y - height, width, height );
21531 state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ) );
21532
21533 };
21534
21535 this.setScissorTest = function ( boolean ) {
21536
21537 state.setScissorTest( _scissorTest = boolean );
21538
21539 };
21540
21541 // Clearing
21542
21543 this.getClearColor = function () {
21544
21545 return background.getClearColor();
21546
21547 };
21548
21549 this.setClearColor = function () {
21550
21551 background.setClearColor.apply( background, arguments );
21552
21553 };
21554
21555 this.getClearAlpha = function () {
21556
21557 return background.getClearAlpha();
21558
21559 };
21560
21561 this.setClearAlpha = function () {
21562
21563 background.setClearAlpha.apply( background, arguments );
21564
21565 };
21566
21567 this.clear = function ( color, depth, stencil ) {
21568
21569 var bits = 0;
21570
21571 if ( color === undefined || color ) bits |= _gl.COLOR_BUFFER_BIT;
21572 if ( depth === undefined || depth ) bits |= _gl.DEPTH_BUFFER_BIT;
21573 if ( stencil === undefined || stencil ) bits |= _gl.STENCIL_BUFFER_BIT;
21574
21575 _gl.clear( bits );
21576
21577 };
21578
21579 this.clearColor = function () {
21580
21581 this.clear( true, false, false );
21582
21583 };
21584
21585 this.clearDepth = function () {
21586
21587 this.clear( false, true, false );
21588
21589 };
21590
21591 this.clearStencil = function () {
21592
21593 this.clear( false, false, true );
21594
21595 };
21596
21597 this.clearTarget = function ( renderTarget, color, depth, stencil ) {
21598
21599 this.setRenderTarget( renderTarget );
21600 this.clear( color, depth, stencil );
21601
21602 };
21603
21604 //
21605
21606 this.dispose = function () {
21607
21608 _canvas.removeEventListener( 'webglcontextlost', onContextLost, false );
21609 _canvas.removeEventListener( 'webglcontextrestored', onContextRestore, false );
21610
21611 renderLists.dispose();
21612 renderStates.dispose();
21613 properties.dispose();
21614 objects.dispose();
21615
21616 vr.dispose();
21617
21618 stopAnimation();
21619
21620 };
21621
21622 // Events
21623
21624 function onContextLost( event ) {
21625
21626 event.preventDefault();
21627
21628 console.log( 'THREE.WebGLRenderer: Context Lost.' );
21629
21630 _isContextLost = true;
21631
21632 }
21633
21634 function onContextRestore( /* event */ ) {
21635
21636 console.log( 'THREE.WebGLRenderer: Context Restored.' );
21637
21638 _isContextLost = false;
21639
21640 initGLContext();
21641
21642 }
21643
21644 function onMaterialDispose( event ) {
21645
21646 var material = event.target;
21647
21648 material.removeEventListener( 'dispose', onMaterialDispose );
21649
21650 deallocateMaterial( material );
21651
21652 }
21653
21654 // Buffer deallocation
21655
21656 function deallocateMaterial( material ) {
21657
21658 releaseMaterialProgramReference( material );
21659
21660 properties.remove( material );
21661
21662 }
21663
21664
21665 function releaseMaterialProgramReference( material ) {
21666
21667 var programInfo = properties.get( material ).program;
21668
21669 material.program = undefined;
21670
21671 if ( programInfo !== undefined ) {
21672
21673 programCache.releaseProgram( programInfo );
21674
21675 }
21676
21677 }
21678
21679 // Buffer rendering
21680
21681 function renderObjectImmediate( object, program, material ) {
21682
21683 object.render( function ( object ) {
21684
21685 _this.renderBufferImmediate( object, program, material );
21686
21687 } );
21688
21689 }
21690
21691 this.renderBufferImmediate = function ( object, program, material ) {
21692
21693 state.initAttributes();
21694
21695 var buffers = properties.get( object );
21696
21697 if ( object.hasPositions && ! buffers.position ) buffers.position = _gl.createBuffer();
21698 if ( object.hasNormals && ! buffers.normal ) buffers.normal = _gl.createBuffer();
21699 if ( object.hasUvs && ! buffers.uv ) buffers.uv = _gl.createBuffer();
21700 if ( object.hasColors && ! buffers.color ) buffers.color = _gl.createBuffer();
21701
21702 var programAttributes = program.getAttributes();
21703
21704 if ( object.hasPositions ) {
21705
21706 _gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.position );
21707 _gl.bufferData( _gl.ARRAY_BUFFER, object.positionArray, _gl.DYNAMIC_DRAW );
21708
21709 state.enableAttribute( programAttributes.position );
21710 _gl.vertexAttribPointer( programAttributes.position, 3, _gl.FLOAT, false, 0, 0 );
21711
21712 }
21713
21714 if ( object.hasNormals ) {
21715
21716 _gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.normal );
21717
21718 if ( ! material.isMeshPhongMaterial &&
21719 ! material.isMeshStandardMaterial &&
21720 ! material.isMeshNormalMaterial &&
21721 material.flatShading === true ) {
21722
21723 for ( var i = 0, l = object.count * 3; i < l; i += 9 ) {
21724
21725 var array = object.normalArray;
21726
21727 var nx = ( array[ i + 0 ] + array[ i + 3 ] + array[ i + 6 ] ) / 3;
21728 var ny = ( array[ i + 1 ] + array[ i + 4 ] + array[ i + 7 ] ) / 3;
21729 var nz = ( array[ i + 2 ] + array[ i + 5 ] + array[ i + 8 ] ) / 3;
21730
21731 array[ i + 0 ] = nx;
21732 array[ i + 1 ] = ny;
21733 array[ i + 2 ] = nz;
21734
21735 array[ i + 3 ] = nx;
21736 array[ i + 4 ] = ny;
21737 array[ i + 5 ] = nz;
21738
21739 array[ i + 6 ] = nx;
21740 array[ i + 7 ] = ny;
21741 array[ i + 8 ] = nz;
21742
21743 }
21744
21745 }
21746
21747 _gl.bufferData( _gl.ARRAY_BUFFER, object.normalArray, _gl.DYNAMIC_DRAW );
21748
21749 state.enableAttribute( programAttributes.normal );
21750
21751 _gl.vertexAttribPointer( programAttributes.normal, 3, _gl.FLOAT, false, 0, 0 );
21752
21753 }
21754
21755 if ( object.hasUvs && material.map ) {
21756
21757 _gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.uv );
21758 _gl.bufferData( _gl.ARRAY_BUFFER, object.uvArray, _gl.DYNAMIC_DRAW );
21759
21760 state.enableAttribute( programAttributes.uv );
21761
21762 _gl.vertexAttribPointer( programAttributes.uv, 2, _gl.FLOAT, false, 0, 0 );
21763
21764 }
21765
21766 if ( object.hasColors && material.vertexColors !== NoColors ) {
21767
21768 _gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.color );
21769 _gl.bufferData( _gl.ARRAY_BUFFER, object.colorArray, _gl.DYNAMIC_DRAW );
21770
21771 state.enableAttribute( programAttributes.color );
21772
21773 _gl.vertexAttribPointer( programAttributes.color, 3, _gl.FLOAT, false, 0, 0 );
21774
21775 }
21776
21777 state.disableUnusedAttributes();
21778
21779 _gl.drawArrays( _gl.TRIANGLES, 0, object.count );
21780
21781 object.count = 0;
21782
21783 };
21784
21785 this.renderBufferDirect = function ( camera, fog, geometry, material, object, group ) {
21786
21787 var frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 );
21788
21789 state.setMaterial( material, frontFaceCW );
21790
21791 var program = setProgram( camera, fog, material, object );
21792 var geometryProgram = geometry.id + '_' + program.id + '_' + ( material.wireframe === true );
21793
21794 var updateBuffers = false;
21795
21796 if ( geometryProgram !== _currentGeometryProgram ) {
21797
21798 _currentGeometryProgram = geometryProgram;
21799 updateBuffers = true;
21800
21801 }
21802
21803 if ( object.morphTargetInfluences ) {
21804
21805 morphtargets.update( object, geometry, material, program );
21806
21807 updateBuffers = true;
21808
21809 }
21810
21811 //
21812
21813 var index = geometry.index;
21814 var position = geometry.attributes.position;
21815 var rangeFactor = 1;
21816
21817 if ( material.wireframe === true ) {
21818
21819 index = geometries.getWireframeAttribute( geometry );
21820 rangeFactor = 2;
21821
21822 }
21823
21824 var attribute;
21825 var renderer = bufferRenderer;
21826
21827 if ( index !== null ) {
21828
21829 attribute = attributes.get( index );
21830
21831 renderer = indexedBufferRenderer;
21832 renderer.setIndex( attribute );
21833
21834 }
21835
21836 if ( updateBuffers ) {
21837
21838 setupVertexAttributes( material, program, geometry );
21839
21840 if ( index !== null ) {
21841
21842 _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, attribute.buffer );
21843
21844 }
21845
21846 }
21847
21848 //
21849
21850 var dataCount = Infinity;
21851
21852 if ( index !== null ) {
21853
21854 dataCount = index.count;
21855
21856 } else if ( position !== undefined ) {
21857
21858 dataCount = position.count;
21859
21860 }
21861
21862 var rangeStart = geometry.drawRange.start * rangeFactor;
21863 var rangeCount = geometry.drawRange.count * rangeFactor;
21864
21865 var groupStart = group !== null ? group.start * rangeFactor : 0;
21866 var groupCount = group !== null ? group.count * rangeFactor : Infinity;
21867
21868 var drawStart = Math.max( rangeStart, groupStart );
21869 var drawEnd = Math.min( dataCount, rangeStart + rangeCount, groupStart + groupCount ) - 1;
21870
21871 var drawCount = Math.max( 0, drawEnd - drawStart + 1 );
21872
21873 if ( drawCount === 0 ) return;
21874
21875 //
21876
21877 if ( object.isMesh ) {
21878
21879 if ( material.wireframe === true ) {
21880
21881 state.setLineWidth( material.wireframeLinewidth * getTargetPixelRatio() );
21882 renderer.setMode( _gl.LINES );
21883
21884 } else {
21885
21886 switch ( object.drawMode ) {
21887
21888 case TrianglesDrawMode:
21889 renderer.setMode( _gl.TRIANGLES );
21890 break;
21891
21892 case TriangleStripDrawMode:
21893 renderer.setMode( _gl.TRIANGLE_STRIP );
21894 break;
21895
21896 case TriangleFanDrawMode:
21897 renderer.setMode( _gl.TRIANGLE_FAN );
21898 break;
21899
21900 }
21901
21902 }
21903
21904
21905 } else if ( object.isLine ) {
21906
21907 var lineWidth = material.linewidth;
21908
21909 if ( lineWidth === undefined ) lineWidth = 1; // Not using Line*Material
21910
21911 state.setLineWidth( lineWidth * getTargetPixelRatio() );
21912
21913 if ( object.isLineSegments ) {
21914
21915 renderer.setMode( _gl.LINES );
21916
21917 } else if ( object.isLineLoop ) {
21918
21919 renderer.setMode( _gl.LINE_LOOP );
21920
21921 } else {
21922
21923 renderer.setMode( _gl.LINE_STRIP );
21924
21925 }
21926
21927 } else if ( object.isPoints ) {
21928
21929 renderer.setMode( _gl.POINTS );
21930
21931 }
21932
21933 if ( geometry && geometry.isInstancedBufferGeometry ) {
21934
21935 if ( geometry.maxInstancedCount > 0 ) {
21936
21937 renderer.renderInstances( geometry, drawStart, drawCount );
21938
21939 }
21940
21941 } else {
21942
21943 renderer.render( drawStart, drawCount );
21944
21945 }
21946
21947 };
21948
21949 function setupVertexAttributes( material, program, geometry ) {
21950
21951 if ( geometry && geometry.isInstancedBufferGeometry ) {
21952
21953 if ( extensions.get( 'ANGLE_instanced_arrays' ) === null ) {
21954
21955 console.error( 'THREE.WebGLRenderer.setupVertexAttributes: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
21956 return;
21957
21958 }
21959
21960 }
21961
21962 state.initAttributes();
21963
21964 var geometryAttributes = geometry.attributes;
21965
21966 var programAttributes = program.getAttributes();
21967
21968 var materialDefaultAttributeValues = material.defaultAttributeValues;
21969
21970 for ( var name in programAttributes ) {
21971
21972 var programAttribute = programAttributes[ name ];
21973
21974 if ( programAttribute >= 0 ) {
21975
21976 var geometryAttribute = geometryAttributes[ name ];
21977
21978 if ( geometryAttribute !== undefined ) {
21979
21980 var normalized = geometryAttribute.normalized;
21981 var size = geometryAttribute.itemSize;
21982
21983 var attribute = attributes.get( geometryAttribute );
21984
21985 // TODO Attribute may not be available on context restore
21986
21987 if ( attribute === undefined ) continue;
21988
21989 var buffer = attribute.buffer;
21990 var type = attribute.type;
21991 var bytesPerElement = attribute.bytesPerElement;
21992
21993 if ( geometryAttribute.isInterleavedBufferAttribute ) {
21994
21995 var data = geometryAttribute.data;
21996 var stride = data.stride;
21997 var offset = geometryAttribute.offset;
21998
21999 if ( data && data.isInstancedInterleavedBuffer ) {
22000
22001 state.enableAttributeAndDivisor( programAttribute, data.meshPerAttribute );
22002
22003 if ( geometry.maxInstancedCount === undefined ) {
22004
22005 geometry.maxInstancedCount = data.meshPerAttribute * data.count;
22006
22007 }
22008
22009 } else {
22010
22011 state.enableAttribute( programAttribute );
22012
22013 }
22014
22015 _gl.bindBuffer( _gl.ARRAY_BUFFER, buffer );
22016 _gl.vertexAttribPointer( programAttribute, size, type, normalized, stride * bytesPerElement, offset * bytesPerElement );
22017
22018 } else {
22019
22020 if ( geometryAttribute.isInstancedBufferAttribute ) {
22021
22022 state.enableAttributeAndDivisor( programAttribute, geometryAttribute.meshPerAttribute );
22023
22024 if ( geometry.maxInstancedCount === undefined ) {
22025
22026 geometry.maxInstancedCount = geometryAttribute.meshPerAttribute * geometryAttribute.count;
22027
22028 }
22029
22030 } else {
22031
22032 state.enableAttribute( programAttribute );
22033
22034 }
22035
22036 _gl.bindBuffer( _gl.ARRAY_BUFFER, buffer );
22037 _gl.vertexAttribPointer( programAttribute, size, type, normalized, 0, 0 );
22038
22039 }
22040
22041 } else if ( materialDefaultAttributeValues !== undefined ) {
22042
22043 var value = materialDefaultAttributeValues[ name ];
22044
22045 if ( value !== undefined ) {
22046
22047 switch ( value.length ) {
22048
22049 case 2:
22050 _gl.vertexAttrib2fv( programAttribute, value );
22051 break;
22052
22053 case 3:
22054 _gl.vertexAttrib3fv( programAttribute, value );
22055 break;
22056
22057 case 4:
22058 _gl.vertexAttrib4fv( programAttribute, value );
22059 break;
22060
22061 default:
22062 _gl.vertexAttrib1fv( programAttribute, value );
22063
22064 }
22065
22066 }
22067
22068 }
22069
22070 }
22071
22072 }
22073
22074 state.disableUnusedAttributes();
22075
22076 }
22077
22078 // Compile
22079
22080 this.compile = function ( scene, camera ) {
22081
22082 currentRenderState = renderStates.get( scene, camera );
22083 currentRenderState.init();
22084
22085 scene.traverse( function ( object ) {
22086
22087 if ( object.isLight ) {
22088
22089 currentRenderState.pushLight( object );
22090
22091 if ( object.castShadow ) {
22092
22093 currentRenderState.pushShadow( object );
22094
22095 }
22096
22097 }
22098
22099 } );
22100
22101 currentRenderState.setupLights( camera );
22102
22103 scene.traverse( function ( object ) {
22104
22105 if ( object.material ) {
22106
22107 if ( Array.isArray( object.material ) ) {
22108
22109 for ( var i = 0; i < object.material.length; i ++ ) {
22110
22111 initMaterial( object.material[ i ], scene.fog, object );
22112
22113 }
22114
22115 } else {
22116
22117 initMaterial( object.material, scene.fog, object );
22118
22119 }
22120
22121 }
22122
22123 } );
22124
22125 };
22126
22127 // Animation Loop
22128
22129 var isAnimating = false;
22130 var onAnimationFrame = null;
22131
22132 function startAnimation() {
22133
22134 if ( isAnimating ) return;
22135
22136 requestAnimationLoopFrame();
22137
22138 isAnimating = true;
22139
22140 }
22141
22142 function stopAnimation() {
22143
22144 isAnimating = false;
22145
22146 }
22147
22148 function requestAnimationLoopFrame() {
22149
22150 var device = vr.getDevice();
22151
22152 if ( device && device.isPresenting ) {
22153
22154 device.requestAnimationFrame( animationLoop );
22155
22156 } else {
22157
22158 window.requestAnimationFrame( animationLoop );
22159
22160 }
22161
22162 }
22163
22164 function animationLoop( time ) {
22165
22166 if ( isAnimating === false ) return;
22167
22168 onAnimationFrame( time );
22169
22170 requestAnimationLoopFrame();
22171
22172 }
22173
22174 this.animate = function ( callback ) {
22175
22176 onAnimationFrame = callback;
22177 onAnimationFrame !== null ? startAnimation() : stopAnimation();
22178
22179 };
22180
22181 // Rendering
22182
22183 this.render = function ( scene, camera, renderTarget, forceClear ) {
22184
22185 if ( ! ( camera && camera.isCamera ) ) {
22186
22187 console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' );
22188 return;
22189
22190 }
22191
22192 if ( _isContextLost ) return;
22193
22194 // reset caching for this frame
22195
22196 _currentGeometryProgram = '';
22197 _currentMaterialId = - 1;
22198 _currentCamera = null;
22199
22200 // update scene graph
22201
22202 if ( scene.autoUpdate === true ) scene.updateMatrixWorld();
22203
22204 // update camera matrices and frustum
22205
22206 if ( camera.parent === null ) camera.updateMatrixWorld();
22207
22208 if ( vr.enabled ) {
22209
22210 camera = vr.getCamera( camera );
22211
22212 }
22213
22214 //
22215
22216 currentRenderState = renderStates.get( scene, camera );
22217 currentRenderState.init();
22218
22219 scene.onBeforeRender( _this, scene, camera, renderTarget );
22220
22221 _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
22222 _frustum.setFromMatrix( _projScreenMatrix );
22223
22224 _localClippingEnabled = this.localClippingEnabled;
22225 _clippingEnabled = _clipping.init( this.clippingPlanes, _localClippingEnabled, camera );
22226
22227 currentRenderList = renderLists.get( scene, camera );
22228 currentRenderList.init();
22229
22230 projectObject( scene, camera, _this.sortObjects );
22231
22232 if ( _this.sortObjects === true ) {
22233
22234 currentRenderList.sort();
22235
22236 }
22237
22238 //
22239
22240 if ( _clippingEnabled ) _clipping.beginShadows();
22241
22242 var shadowsArray = currentRenderState.state.shadowsArray;
22243
22244 shadowMap.render( shadowsArray, scene, camera );
22245
22246 currentRenderState.setupLights( camera );
22247
22248 if ( _clippingEnabled ) _clipping.endShadows();
22249
22250 //
22251
22252 if ( this.info.autoReset ) this.info.reset();
22253
22254 if ( renderTarget === undefined ) {
22255
22256 renderTarget = null;
22257
22258 }
22259
22260 this.setRenderTarget( renderTarget );
22261
22262 //
22263
22264 background.render( currentRenderList, scene, camera, forceClear );
22265
22266 // render scene
22267
22268 var opaqueObjects = currentRenderList.opaque;
22269 var transparentObjects = currentRenderList.transparent;
22270
22271 if ( scene.overrideMaterial ) {
22272
22273 var overrideMaterial = scene.overrideMaterial;
22274
22275 if ( opaqueObjects.length ) renderObjects( opaqueObjects, scene, camera, overrideMaterial );
22276 if ( transparentObjects.length ) renderObjects( transparentObjects, scene, camera, overrideMaterial );
22277
22278 } else {
22279
22280 // opaque pass (front-to-back order)
22281
22282 if ( opaqueObjects.length ) renderObjects( opaqueObjects, scene, camera );
22283
22284 // transparent pass (back-to-front order)
22285
22286 if ( transparentObjects.length ) renderObjects( transparentObjects, scene, camera );
22287
22288 }
22289
22290 // custom renderers
22291
22292 var spritesArray = currentRenderState.state.spritesArray;
22293
22294 spriteRenderer.render( spritesArray, scene, camera );
22295
22296 // Generate mipmap if we're using any kind of mipmap filtering
22297
22298 if ( renderTarget ) {
22299
22300 textures.updateRenderTargetMipmap( renderTarget );
22301
22302 }
22303
22304 // Ensure depth buffer writing is enabled so it can be cleared on next render
22305
22306 state.buffers.depth.setTest( true );
22307 state.buffers.depth.setMask( true );
22308 state.buffers.color.setMask( true );
22309
22310 state.setPolygonOffset( false );
22311
22312 scene.onAfterRender( _this, scene, camera );
22313
22314 if ( vr.enabled ) {
22315
22316 vr.submitFrame();
22317
22318 }
22319
22320 // _gl.finish();
22321
22322 currentRenderList = null;
22323 currentRenderState = null;
22324
22325 };
22326
22327 /*
22328 // TODO Duplicated code (Frustum)
22329
22330 var _sphere = new Sphere();
22331
22332 function isObjectViewable( object ) {
22333
22334 var geometry = object.geometry;
22335
22336 if ( geometry.boundingSphere === null )
22337 geometry.computeBoundingSphere();
22338
22339 _sphere.copy( geometry.boundingSphere ).
22340 applyMatrix4( object.matrixWorld );
22341
22342 return isSphereViewable( _sphere );
22343
22344 }
22345
22346 function isSpriteViewable( sprite ) {
22347
22348 _sphere.center.set( 0, 0, 0 );
22349 _sphere.radius = 0.7071067811865476;
22350 _sphere.applyMatrix4( sprite.matrixWorld );
22351
22352 return isSphereViewable( _sphere );
22353
22354 }
22355
22356 function isSphereViewable( sphere ) {
22357
22358 if ( ! _frustum.intersectsSphere( sphere ) ) return false;
22359
22360 var numPlanes = _clipping.numPlanes;
22361
22362 if ( numPlanes === 0 ) return true;
22363
22364 var planes = _this.clippingPlanes,
22365
22366 center = sphere.center,
22367 negRad = - sphere.radius,
22368 i = 0;
22369
22370 do {
22371
22372 // out when deeper than radius in the negative halfspace
22373 if ( planes[ i ].distanceToPoint( center ) < negRad ) return false;
22374
22375 } while ( ++ i !== numPlanes );
22376
22377 return true;
22378
22379 }
22380 */
22381
22382 function projectObject( object, camera, sortObjects ) {
22383
22384 if ( object.visible === false ) return;
22385
22386 var visible = object.layers.test( camera.layers );
22387
22388 if ( visible ) {
22389
22390 if ( object.isLight ) {
22391
22392 currentRenderState.pushLight( object );
22393
22394 if ( object.castShadow ) {
22395
22396 currentRenderState.pushShadow( object );
22397
22398 }
22399
22400 } else if ( object.isSprite ) {
22401
22402 if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) {
22403
22404 currentRenderState.pushSprite( object );
22405
22406 }
22407
22408 } else if ( object.isImmediateRenderObject ) {
22409
22410 if ( sortObjects ) {
22411
22412 _vector3.setFromMatrixPosition( object.matrixWorld )
22413 .applyMatrix4( _projScreenMatrix );
22414
22415 }
22416
22417 currentRenderList.push( object, null, object.material, _vector3.z, null );
22418
22419 } else if ( object.isMesh || object.isLine || object.isPoints ) {
22420
22421 if ( object.isSkinnedMesh ) {
22422
22423 object.skeleton.update();
22424
22425 }
22426
22427 if ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) {
22428
22429 if ( sortObjects ) {
22430
22431 _vector3.setFromMatrixPosition( object.matrixWorld )
22432 .applyMatrix4( _projScreenMatrix );
22433
22434 }
22435
22436 var geometry = objects.update( object );
22437 var material = object.material;
22438
22439 if ( Array.isArray( material ) ) {
22440
22441 var groups = geometry.groups;
22442
22443 for ( var i = 0, l = groups.length; i < l; i ++ ) {
22444
22445 var group = groups[ i ];
22446 var groupMaterial = material[ group.materialIndex ];
22447
22448 if ( groupMaterial && groupMaterial.visible ) {
22449
22450 currentRenderList.push( object, geometry, groupMaterial, _vector3.z, group );
22451
22452 }
22453
22454 }
22455
22456 } else if ( material.visible ) {
22457
22458 currentRenderList.push( object, geometry, material, _vector3.z, null );
22459
22460 }
22461
22462 }
22463
22464 }
22465
22466 }
22467
22468 var children = object.children;
22469
22470 for ( var i = 0, l = children.length; i < l; i ++ ) {
22471
22472 projectObject( children[ i ], camera, sortObjects );
22473
22474 }
22475
22476 }
22477
22478 function renderObjects( renderList, scene, camera, overrideMaterial ) {
22479
22480 for ( var i = 0, l = renderList.length; i < l; i ++ ) {
22481
22482 var renderItem = renderList[ i ];
22483
22484 var object = renderItem.object;
22485 var geometry = renderItem.geometry;
22486 var material = overrideMaterial === undefined ? renderItem.material : overrideMaterial;
22487 var group = renderItem.group;
22488
22489 if ( camera.isArrayCamera ) {
22490
22491 _currentArrayCamera = camera;
22492
22493 var cameras = camera.cameras;
22494
22495 for ( var j = 0, jl = cameras.length; j < jl; j ++ ) {
22496
22497 var camera2 = cameras[ j ];
22498
22499 if ( object.layers.test( camera2.layers ) ) {
22500
22501 var bounds = camera2.bounds;
22502
22503 var x = bounds.x * _width;
22504 var y = bounds.y * _height;
22505 var width = bounds.z * _width;
22506 var height = bounds.w * _height;
22507
22508 state.viewport( _currentViewport.set( x, y, width, height ).multiplyScalar( _pixelRatio ) );
22509
22510 renderObject( object, scene, camera2, geometry, material, group );
22511
22512 }
22513
22514 }
22515
22516 } else {
22517
22518 _currentArrayCamera = null;
22519
22520 renderObject( object, scene, camera, geometry, material, group );
22521
22522 }
22523
22524 }
22525
22526 }
22527
22528 function renderObject( object, scene, camera, geometry, material, group ) {
22529
22530 object.onBeforeRender( _this, scene, camera, geometry, material, group );
22531 currentRenderState = renderStates.get( scene, _currentArrayCamera || camera );
22532
22533 object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
22534 object.normalMatrix.getNormalMatrix( object.modelViewMatrix );
22535
22536 if ( object.isImmediateRenderObject ) {
22537
22538 var frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 );
22539
22540 state.setMaterial( material, frontFaceCW );
22541
22542 var program = setProgram( camera, scene.fog, material, object );
22543
22544 _currentGeometryProgram = '';
22545
22546 renderObjectImmediate( object, program, material );
22547
22548 } else {
22549
22550 _this.renderBufferDirect( camera, scene.fog, geometry, material, object, group );
22551
22552 }
22553
22554 object.onAfterRender( _this, scene, camera, geometry, material, group );
22555 currentRenderState = renderStates.get( scene, _currentArrayCamera || camera );
22556
22557 }
22558
22559 function initMaterial( material, fog, object ) {
22560
22561 var materialProperties = properties.get( material );
22562
22563 var lights = currentRenderState.state.lights;
22564 var shadowsArray = currentRenderState.state.shadowsArray;
22565
22566 var parameters = programCache.getParameters(
22567 material, lights.state, shadowsArray, fog, _clipping.numPlanes, _clipping.numIntersection, object );
22568
22569 var code = programCache.getProgramCode( material, parameters );
22570
22571 var program = materialProperties.program;
22572 var programChange = true;
22573
22574 if ( program === undefined ) {
22575
22576 // new material
22577 material.addEventListener( 'dispose', onMaterialDispose );
22578
22579 } else if ( program.code !== code ) {
22580
22581 // changed glsl or parameters
22582 releaseMaterialProgramReference( material );
22583
22584 } else if ( materialProperties.lightsHash !== lights.state.hash ) {
22585
22586 properties.update( material, 'lightsHash', lights.state.hash );
22587 programChange = false;
22588
22589 } else if ( parameters.shaderID !== undefined ) {
22590
22591 // same glsl and uniform list
22592 return;
22593
22594 } else {
22595
22596 // only rebuild uniform list
22597 programChange = false;
22598
22599 }
22600
22601 if ( programChange ) {
22602
22603 if ( parameters.shaderID ) {
22604
22605 var shader = ShaderLib[ parameters.shaderID ];
22606
22607 materialProperties.shader = {
22608 name: material.type,
22609 uniforms: UniformsUtils.clone( shader.uniforms ),
22610 vertexShader: shader.vertexShader,
22611 fragmentShader: shader.fragmentShader
22612 };
22613
22614 } else {
22615
22616 materialProperties.shader = {
22617 name: material.type,
22618 uniforms: material.uniforms,
22619 vertexShader: material.vertexShader,
22620 fragmentShader: material.fragmentShader
22621 };
22622
22623 }
22624
22625 material.onBeforeCompile( materialProperties.shader, _this );
22626
22627 program = programCache.acquireProgram( material, materialProperties.shader, parameters, code );
22628
22629 materialProperties.program = program;
22630 material.program = program;
22631
22632 }
22633
22634 var programAttributes = program.getAttributes();
22635
22636 if ( material.morphTargets ) {
22637
22638 material.numSupportedMorphTargets = 0;
22639
22640 for ( var i = 0; i < _this.maxMorphTargets; i ++ ) {
22641
22642 if ( programAttributes[ 'morphTarget' + i ] >= 0 ) {
22643
22644 material.numSupportedMorphTargets ++;
22645
22646 }
22647
22648 }
22649
22650 }
22651
22652 if ( material.morphNormals ) {
22653
22654 material.numSupportedMorphNormals = 0;
22655
22656 for ( var i = 0; i < _this.maxMorphNormals; i ++ ) {
22657
22658 if ( programAttributes[ 'morphNormal' + i ] >= 0 ) {
22659
22660 material.numSupportedMorphNormals ++;
22661
22662 }
22663
22664 }
22665
22666 }
22667
22668 var uniforms = materialProperties.shader.uniforms;
22669
22670 if ( ! material.isShaderMaterial &&
22671 ! material.isRawShaderMaterial ||
22672 material.clipping === true ) {
22673
22674 materialProperties.numClippingPlanes = _clipping.numPlanes;
22675 materialProperties.numIntersection = _clipping.numIntersection;
22676 uniforms.clippingPlanes = _clipping.uniform;
22677
22678 }
22679
22680 materialProperties.fog = fog;
22681
22682 // store the light setup it was created for
22683
22684 materialProperties.lightsHash = lights.state.hash;
22685
22686 if ( material.lights ) {
22687
22688 // wire up the material to this renderer's lighting state
22689
22690 uniforms.ambientLightColor.value = lights.state.ambient;
22691 uniforms.directionalLights.value = lights.state.directional;
22692 uniforms.spotLights.value = lights.state.spot;
22693 uniforms.rectAreaLights.value = lights.state.rectArea;
22694 uniforms.pointLights.value = lights.state.point;
22695 uniforms.hemisphereLights.value = lights.state.hemi;
22696
22697 uniforms.directionalShadowMap.value = lights.state.directionalShadowMap;
22698 uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix;
22699 uniforms.spotShadowMap.value = lights.state.spotShadowMap;
22700 uniforms.spotShadowMatrix.value = lights.state.spotShadowMatrix;
22701 uniforms.pointShadowMap.value = lights.state.pointShadowMap;
22702 uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix;
22703 // TODO (abelnation): add area lights shadow info to uniforms
22704
22705 }
22706
22707 var progUniforms = materialProperties.program.getUniforms(),
22708 uniformsList =
22709 WebGLUniforms.seqWithValue( progUniforms.seq, uniforms );
22710
22711 materialProperties.uniformsList = uniformsList;
22712
22713 }
22714
22715 function setProgram( camera, fog, material, object ) {
22716
22717 _usedTextureUnits = 0;
22718
22719 var materialProperties = properties.get( material );
22720 var lights = currentRenderState.state.lights;
22721
22722 if ( _clippingEnabled ) {
22723
22724 if ( _localClippingEnabled || camera !== _currentCamera ) {
22725
22726 var useCache =
22727 camera === _currentCamera &&
22728 material.id === _currentMaterialId;
22729
22730 // we might want to call this function with some ClippingGroup
22731 // object instead of the material, once it becomes feasible
22732 // (#8465, #8379)
22733 _clipping.setState(
22734 material.clippingPlanes, material.clipIntersection, material.clipShadows,
22735 camera, materialProperties, useCache );
22736
22737 }
22738
22739 }
22740
22741 if ( material.needsUpdate === false ) {
22742
22743 if ( materialProperties.program === undefined ) {
22744
22745 material.needsUpdate = true;
22746
22747 } else if ( material.fog && materialProperties.fog !== fog ) {
22748
22749 material.needsUpdate = true;
22750
22751 } else if ( material.lights && materialProperties.lightsHash !== lights.state.hash ) {
22752
22753 material.needsUpdate = true;
22754
22755 } else if ( materialProperties.numClippingPlanes !== undefined &&
22756 ( materialProperties.numClippingPlanes !== _clipping.numPlanes ||
22757 materialProperties.numIntersection !== _clipping.numIntersection ) ) {
22758
22759 material.needsUpdate = true;
22760
22761 }
22762
22763 }
22764
22765 if ( material.needsUpdate ) {
22766
22767 initMaterial( material, fog, object );
22768 material.needsUpdate = false;
22769
22770 }
22771
22772 var refreshProgram = false;
22773 var refreshMaterial = false;
22774 var refreshLights = false;
22775
22776 var program = materialProperties.program,
22777 p_uniforms = program.getUniforms(),
22778 m_uniforms = materialProperties.shader.uniforms;
22779
22780 if ( state.useProgram( program.program ) ) {
22781
22782 refreshProgram = true;
22783 refreshMaterial = true;
22784 refreshLights = true;
22785
22786 }
22787
22788 if ( material.id !== _currentMaterialId ) {
22789
22790 _currentMaterialId = material.id;
22791
22792 refreshMaterial = true;
22793
22794 }
22795
22796 if ( refreshProgram || camera !== _currentCamera ) {
22797
22798 p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix );
22799
22800 if ( capabilities.logarithmicDepthBuffer ) {
22801
22802 p_uniforms.setValue( _gl, 'logDepthBufFC',
22803 2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) );
22804
22805 }
22806
22807 // Avoid unneeded uniform updates per ArrayCamera's sub-camera
22808
22809 if ( _currentCamera !== ( _currentArrayCamera || camera ) ) {
22810
22811 _currentCamera = ( _currentArrayCamera || camera );
22812
22813 // lighting uniforms depend on the camera so enforce an update
22814 // now, in case this material supports lights - or later, when
22815 // the next material that does gets activated:
22816
22817 refreshMaterial = true; // set to true on material change
22818 refreshLights = true; // remains set until update done
22819
22820 }
22821
22822 // load material specific uniforms
22823 // (shader material also gets them for the sake of genericity)
22824
22825 if ( material.isShaderMaterial ||
22826 material.isMeshPhongMaterial ||
22827 material.isMeshStandardMaterial ||
22828 material.envMap ) {
22829
22830 var uCamPos = p_uniforms.map.cameraPosition;
22831
22832 if ( uCamPos !== undefined ) {
22833
22834 uCamPos.setValue( _gl,
22835 _vector3.setFromMatrixPosition( camera.matrixWorld ) );
22836
22837 }
22838
22839 }
22840
22841 if ( material.isMeshPhongMaterial ||
22842 material.isMeshLambertMaterial ||
22843 material.isMeshBasicMaterial ||
22844 material.isMeshStandardMaterial ||
22845 material.isShaderMaterial ||
22846 material.skinning ) {
22847
22848 p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse );
22849
22850 }
22851
22852 }
22853
22854 // skinning uniforms must be set even if material didn't change
22855 // auto-setting of texture unit for bone texture must go before other textures
22856 // not sure why, but otherwise weird things happen
22857
22858 if ( material.skinning ) {
22859
22860 p_uniforms.setOptional( _gl, object, 'bindMatrix' );
22861 p_uniforms.setOptional( _gl, object, 'bindMatrixInverse' );
22862
22863 var skeleton = object.skeleton;
22864
22865 if ( skeleton ) {
22866
22867 var bones = skeleton.bones;
22868
22869 if ( capabilities.floatVertexTextures ) {
22870
22871 if ( skeleton.boneTexture === undefined ) {
22872
22873 // layout (1 matrix = 4 pixels)
22874 // RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)
22875 // with 8x8 pixel texture max 16 bones * 4 pixels = (8 * 8)
22876 // 16x16 pixel texture max 64 bones * 4 pixels = (16 * 16)
22877 // 32x32 pixel texture max 256 bones * 4 pixels = (32 * 32)
22878 // 64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64)
22879
22880
22881 var size = Math.sqrt( bones.length * 4 ); // 4 pixels needed for 1 matrix
22882 size = _Math.ceilPowerOfTwo( size );
22883 size = Math.max( size, 4 );
22884
22885 var boneMatrices = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel
22886 boneMatrices.set( skeleton.boneMatrices ); // copy current values
22887
22888 var boneTexture = new DataTexture( boneMatrices, size, size, RGBAFormat, FloatType );
22889 boneTexture.needsUpdate = true;
22890
22891 skeleton.boneMatrices = boneMatrices;
22892 skeleton.boneTexture = boneTexture;
22893 skeleton.boneTextureSize = size;
22894
22895 }
22896
22897 p_uniforms.setValue( _gl, 'boneTexture', skeleton.boneTexture );
22898 p_uniforms.setValue( _gl, 'boneTextureSize', skeleton.boneTextureSize );
22899
22900 } else {
22901
22902 p_uniforms.setOptional( _gl, skeleton, 'boneMatrices' );
22903
22904 }
22905
22906 }
22907
22908 }
22909
22910 if ( refreshMaterial ) {
22911
22912 p_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure );
22913 p_uniforms.setValue( _gl, 'toneMappingWhitePoint', _this.toneMappingWhitePoint );
22914
22915 if ( material.lights ) {
22916
22917 // the current material requires lighting info
22918
22919 // note: all lighting uniforms are always set correctly
22920 // they simply reference the renderer's state for their
22921 // values
22922 //
22923 // use the current material's .needsUpdate flags to set
22924 // the GL state when required
22925
22926 markUniformsLightsNeedsUpdate( m_uniforms, refreshLights );
22927
22928 }
22929
22930 // refresh uniforms common to several materials
22931
22932 if ( fog && material.fog ) {
22933
22934 refreshUniformsFog( m_uniforms, fog );
22935
22936 }
22937
22938 if ( material.isMeshBasicMaterial ) {
22939
22940 refreshUniformsCommon( m_uniforms, material );
22941
22942 } else if ( material.isMeshLambertMaterial ) {
22943
22944 refreshUniformsCommon( m_uniforms, material );
22945 refreshUniformsLambert( m_uniforms, material );
22946
22947 } else if ( material.isMeshPhongMaterial ) {
22948
22949 refreshUniformsCommon( m_uniforms, material );
22950
22951 if ( material.isMeshToonMaterial ) {
22952
22953 refreshUniformsToon( m_uniforms, material );
22954
22955 } else {
22956
22957 refreshUniformsPhong( m_uniforms, material );
22958
22959 }
22960
22961 } else if ( material.isMeshStandardMaterial ) {
22962
22963 refreshUniformsCommon( m_uniforms, material );
22964
22965 if ( material.isMeshPhysicalMaterial ) {
22966
22967 refreshUniformsPhysical( m_uniforms, material );
22968
22969 } else {
22970
22971 refreshUniformsStandard( m_uniforms, material );
22972
22973 }
22974
22975 } else if ( material.isMeshDepthMaterial ) {
22976
22977 refreshUniformsCommon( m_uniforms, material );
22978 refreshUniformsDepth( m_uniforms, material );
22979
22980 } else if ( material.isMeshDistanceMaterial ) {
22981
22982 refreshUniformsCommon( m_uniforms, material );
22983 refreshUniformsDistance( m_uniforms, material );
22984
22985 } else if ( material.isMeshNormalMaterial ) {
22986
22987 refreshUniformsCommon( m_uniforms, material );
22988 refreshUniformsNormal( m_uniforms, material );
22989
22990 } else if ( material.isLineBasicMaterial ) {
22991
22992 refreshUniformsLine( m_uniforms, material );
22993
22994 if ( material.isLineDashedMaterial ) {
22995
22996 refreshUniformsDash( m_uniforms, material );
22997
22998 }
22999
23000 } else if ( material.isPointsMaterial ) {
23001
23002 refreshUniformsPoints( m_uniforms, material );
23003
23004 } else if ( material.isShadowMaterial ) {
23005
23006 m_uniforms.color.value = material.color;
23007 m_uniforms.opacity.value = material.opacity;
23008
23009 }
23010
23011 // RectAreaLight Texture
23012 // TODO (mrdoob): Find a nicer implementation
23013
23014 if ( m_uniforms.ltc_1 !== undefined ) m_uniforms.ltc_1.value = UniformsLib.LTC_1;
23015 if ( m_uniforms.ltc_2 !== undefined ) m_uniforms.ltc_2.value = UniformsLib.LTC_2;
23016
23017 WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, _this );
23018
23019 }
23020
23021 if ( material.isShaderMaterial && material.uniformsNeedUpdate === true ) {
23022
23023 WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, _this );
23024 material.uniformsNeedUpdate = false;
23025
23026 }
23027
23028 // common matrices
23029
23030 p_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix );
23031 p_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix );
23032 p_uniforms.setValue( _gl, 'modelMatrix', object.matrixWorld );
23033
23034 return program;
23035
23036 }
23037
23038 // Uniforms (refresh uniforms objects)
23039
23040 function refreshUniformsCommon( uniforms, material ) {
23041
23042 uniforms.opacity.value = material.opacity;
23043
23044 if ( material.color ) {
23045
23046 uniforms.diffuse.value = material.color;
23047
23048 }
23049
23050 if ( material.emissive ) {
23051
23052 uniforms.emissive.value.copy( material.emissive ).multiplyScalar( material.emissiveIntensity );
23053
23054 }
23055
23056 if ( material.map ) {
23057
23058 uniforms.map.value = material.map;
23059
23060 }
23061
23062 if ( material.alphaMap ) {
23063
23064 uniforms.alphaMap.value = material.alphaMap;
23065
23066 }
23067
23068 if ( material.specularMap ) {
23069
23070 uniforms.specularMap.value = material.specularMap;
23071
23072 }
23073
23074 if ( material.envMap ) {
23075
23076 uniforms.envMap.value = material.envMap;
23077
23078 // don't flip CubeTexture envMaps, flip everything else:
23079 // WebGLRenderTargetCube will be flipped for backwards compatibility
23080 // WebGLRenderTargetCube.texture will be flipped because it's a Texture and NOT a CubeTexture
23081 // this check must be handled differently, or removed entirely, if WebGLRenderTargetCube uses a CubeTexture in the future
23082 uniforms.flipEnvMap.value = ( ! ( material.envMap && material.envMap.isCubeTexture ) ) ? 1 : - 1;
23083
23084 uniforms.reflectivity.value = material.reflectivity;
23085 uniforms.refractionRatio.value = material.refractionRatio;
23086
23087 uniforms.maxMipLevel.value = properties.get( material.envMap ).__maxMipLevel;
23088
23089 }
23090
23091 if ( material.lightMap ) {
23092
23093 uniforms.lightMap.value = material.lightMap;
23094 uniforms.lightMapIntensity.value = material.lightMapIntensity;
23095
23096 }
23097
23098 if ( material.aoMap ) {
23099
23100 uniforms.aoMap.value = material.aoMap;
23101 uniforms.aoMapIntensity.value = material.aoMapIntensity;
23102
23103 }
23104
23105 // uv repeat and offset setting priorities
23106 // 1. color map
23107 // 2. specular map
23108 // 3. normal map
23109 // 4. bump map
23110 // 5. alpha map
23111 // 6. emissive map
23112
23113 var uvScaleMap;
23114
23115 if ( material.map ) {
23116
23117 uvScaleMap = material.map;
23118
23119 } else if ( material.specularMap ) {
23120
23121 uvScaleMap = material.specularMap;
23122
23123 } else if ( material.displacementMap ) {
23124
23125 uvScaleMap = material.displacementMap;
23126
23127 } else if ( material.normalMap ) {
23128
23129 uvScaleMap = material.normalMap;
23130
23131 } else if ( material.bumpMap ) {
23132
23133 uvScaleMap = material.bumpMap;
23134
23135 } else if ( material.roughnessMap ) {
23136
23137 uvScaleMap = material.roughnessMap;
23138
23139 } else if ( material.metalnessMap ) {
23140
23141 uvScaleMap = material.metalnessMap;
23142
23143 } else if ( material.alphaMap ) {
23144
23145 uvScaleMap = material.alphaMap;
23146
23147 } else if ( material.emissiveMap ) {
23148
23149 uvScaleMap = material.emissiveMap;
23150
23151 }
23152
23153 if ( uvScaleMap !== undefined ) {
23154
23155 // backwards compatibility
23156 if ( uvScaleMap.isWebGLRenderTarget ) {
23157
23158 uvScaleMap = uvScaleMap.texture;
23159
23160 }
23161
23162 if ( uvScaleMap.matrixAutoUpdate === true ) {
23163
23164 uvScaleMap.updateMatrix();
23165
23166 }
23167
23168 uniforms.uvTransform.value.copy( uvScaleMap.matrix );
23169
23170 }
23171
23172 }
23173
23174 function refreshUniformsLine( uniforms, material ) {
23175
23176 uniforms.diffuse.value = material.color;
23177 uniforms.opacity.value = material.opacity;
23178
23179 }
23180
23181 function refreshUniformsDash( uniforms, material ) {
23182
23183 uniforms.dashSize.value = material.dashSize;
23184 uniforms.totalSize.value = material.dashSize + material.gapSize;
23185 uniforms.scale.value = material.scale;
23186
23187 }
23188
23189 function refreshUniformsPoints( uniforms, material ) {
23190
23191 uniforms.diffuse.value = material.color;
23192 uniforms.opacity.value = material.opacity;
23193 uniforms.size.value = material.size * _pixelRatio;
23194 uniforms.scale.value = _height * 0.5;
23195
23196 uniforms.map.value = material.map;
23197
23198 if ( material.map !== null ) {
23199
23200 if ( material.map.matrixAutoUpdate === true ) {
23201
23202 material.map.updateMatrix();
23203
23204 }
23205
23206 uniforms.uvTransform.value.copy( material.map.matrix );
23207
23208 }
23209
23210 }
23211
23212 function refreshUniformsFog( uniforms, fog ) {
23213
23214 uniforms.fogColor.value = fog.color;
23215
23216 if ( fog.isFog ) {
23217
23218 uniforms.fogNear.value = fog.near;
23219 uniforms.fogFar.value = fog.far;
23220
23221 } else if ( fog.isFogExp2 ) {
23222
23223 uniforms.fogDensity.value = fog.density;
23224
23225 }
23226
23227 }
23228
23229 function refreshUniformsLambert( uniforms, material ) {
23230
23231 if ( material.emissiveMap ) {
23232
23233 uniforms.emissiveMap.value = material.emissiveMap;
23234
23235 }
23236
23237 }
23238
23239 function refreshUniformsPhong( uniforms, material ) {
23240
23241 uniforms.specular.value = material.specular;
23242 uniforms.shininess.value = Math.max( material.shininess, 1e-4 ); // to prevent pow( 0.0, 0.0 )
23243
23244 if ( material.emissiveMap ) {
23245
23246 uniforms.emissiveMap.value = material.emissiveMap;
23247
23248 }
23249
23250 if ( material.bumpMap ) {
23251
23252 uniforms.bumpMap.value = material.bumpMap;
23253 uniforms.bumpScale.value = material.bumpScale;
23254
23255 }
23256
23257 if ( material.normalMap ) {
23258
23259 uniforms.normalMap.value = material.normalMap;
23260 uniforms.normalScale.value.copy( material.normalScale );
23261
23262 }
23263
23264 if ( material.displacementMap ) {
23265
23266 uniforms.displacementMap.value = material.displacementMap;
23267 uniforms.displacementScale.value = material.displacementScale;
23268 uniforms.displacementBias.value = material.displacementBias;
23269
23270 }
23271
23272 }
23273
23274 function refreshUniformsToon( uniforms, material ) {
23275
23276 refreshUniformsPhong( uniforms, material );
23277
23278 if ( material.gradientMap ) {
23279
23280 uniforms.gradientMap.value = material.gradientMap;
23281
23282 }
23283
23284 }
23285
23286 function refreshUniformsStandard( uniforms, material ) {
23287
23288 uniforms.roughness.value = material.roughness;
23289 uniforms.metalness.value = material.metalness;
23290
23291 if ( material.roughnessMap ) {
23292
23293 uniforms.roughnessMap.value = material.roughnessMap;
23294
23295 }
23296
23297 if ( material.metalnessMap ) {
23298
23299 uniforms.metalnessMap.value = material.metalnessMap;
23300
23301 }
23302
23303 if ( material.emissiveMap ) {
23304
23305 uniforms.emissiveMap.value = material.emissiveMap;
23306
23307 }
23308
23309 if ( material.bumpMap ) {
23310
23311 uniforms.bumpMap.value = material.bumpMap;
23312 uniforms.bumpScale.value = material.bumpScale;
23313
23314 }
23315
23316 if ( material.normalMap ) {
23317
23318 uniforms.normalMap.value = material.normalMap;
23319 uniforms.normalScale.value.copy( material.normalScale );
23320
23321 }
23322
23323 if ( material.displacementMap ) {
23324
23325 uniforms.displacementMap.value = material.displacementMap;
23326 uniforms.displacementScale.value = material.displacementScale;
23327 uniforms.displacementBias.value = material.displacementBias;
23328
23329 }
23330
23331 if ( material.envMap ) {
23332
23333 //uniforms.envMap.value = material.envMap; // part of uniforms common
23334 uniforms.envMapIntensity.value = material.envMapIntensity;
23335
23336 }
23337
23338 }
23339
23340 function refreshUniformsPhysical( uniforms, material ) {
23341
23342 uniforms.clearCoat.value = material.clearCoat;
23343 uniforms.clearCoatRoughness.value = material.clearCoatRoughness;
23344
23345 refreshUniformsStandard( uniforms, material );
23346
23347 }
23348
23349 function refreshUniformsDepth( uniforms, material ) {
23350
23351 if ( material.displacementMap ) {
23352
23353 uniforms.displacementMap.value = material.displacementMap;
23354 uniforms.displacementScale.value = material.displacementScale;
23355 uniforms.displacementBias.value = material.displacementBias;
23356
23357 }
23358
23359 }
23360
23361 function refreshUniformsDistance( uniforms, material ) {
23362
23363 if ( material.displacementMap ) {
23364
23365 uniforms.displacementMap.value = material.displacementMap;
23366 uniforms.displacementScale.value = material.displacementScale;
23367 uniforms.displacementBias.value = material.displacementBias;
23368
23369 }
23370
23371 uniforms.referencePosition.value.copy( material.referencePosition );
23372 uniforms.nearDistance.value = material.nearDistance;
23373 uniforms.farDistance.value = material.farDistance;
23374
23375 }
23376
23377 function refreshUniformsNormal( uniforms, material ) {
23378
23379 if ( material.bumpMap ) {
23380
23381 uniforms.bumpMap.value = material.bumpMap;
23382 uniforms.bumpScale.value = material.bumpScale;
23383
23384 }
23385
23386 if ( material.normalMap ) {
23387
23388 uniforms.normalMap.value = material.normalMap;
23389 uniforms.normalScale.value.copy( material.normalScale );
23390
23391 }
23392
23393 if ( material.displacementMap ) {
23394
23395 uniforms.displacementMap.value = material.displacementMap;
23396 uniforms.displacementScale.value = material.displacementScale;
23397 uniforms.displacementBias.value = material.displacementBias;
23398
23399 }
23400
23401 }
23402
23403 // If uniforms are marked as clean, they don't need to be loaded to the GPU.
23404
23405 function markUniformsLightsNeedsUpdate( uniforms, value ) {
23406
23407 uniforms.ambientLightColor.needsUpdate = value;
23408
23409 uniforms.directionalLights.needsUpdate = value;
23410 uniforms.pointLights.needsUpdate = value;
23411 uniforms.spotLights.needsUpdate = value;
23412 uniforms.rectAreaLights.needsUpdate = value;
23413 uniforms.hemisphereLights.needsUpdate = value;
23414
23415 }
23416
23417 // Textures
23418
23419 function allocTextureUnit() {
23420
23421 var textureUnit = _usedTextureUnits;
23422
23423 if ( textureUnit >= capabilities.maxTextures ) {
23424
23425 console.warn( 'THREE.WebGLRenderer: Trying to use ' + textureUnit + ' texture units while this GPU supports only ' + capabilities.maxTextures );
23426
23427 }
23428
23429 _usedTextureUnits += 1;
23430
23431 return textureUnit;
23432
23433 }
23434
23435 this.allocTextureUnit = allocTextureUnit;
23436
23437 // this.setTexture2D = setTexture2D;
23438 this.setTexture2D = ( function () {
23439
23440 var warned = false;
23441
23442 // backwards compatibility: peel texture.texture
23443 return function setTexture2D( texture, slot ) {
23444
23445 if ( texture && texture.isWebGLRenderTarget ) {
23446
23447 if ( ! warned ) {
23448
23449 console.warn( "THREE.WebGLRenderer.setTexture2D: don't use render targets as textures. Use their .texture property instead." );
23450 warned = true;
23451
23452 }
23453
23454 texture = texture.texture;
23455
23456 }
23457
23458 textures.setTexture2D( texture, slot );
23459
23460 };
23461
23462 }() );
23463
23464 this.setTexture = ( function () {
23465
23466 var warned = false;
23467
23468 return function setTexture( texture, slot ) {
23469
23470 if ( ! warned ) {
23471
23472 console.warn( "THREE.WebGLRenderer: .setTexture is deprecated, use setTexture2D instead." );
23473 warned = true;
23474
23475 }
23476
23477 textures.setTexture2D( texture, slot );
23478
23479 };
23480
23481 }() );
23482
23483 this.setTextureCube = ( function () {
23484
23485 var warned = false;
23486
23487 return function setTextureCube( texture, slot ) {
23488
23489 // backwards compatibility: peel texture.texture
23490 if ( texture && texture.isWebGLRenderTargetCube ) {
23491
23492 if ( ! warned ) {
23493
23494 console.warn( "THREE.WebGLRenderer.setTextureCube: don't use cube render targets as textures. Use their .texture property instead." );
23495 warned = true;
23496
23497 }
23498
23499 texture = texture.texture;
23500
23501 }
23502
23503 // currently relying on the fact that WebGLRenderTargetCube.texture is a Texture and NOT a CubeTexture
23504 // TODO: unify these code paths
23505 if ( ( texture && texture.isCubeTexture ) ||
23506 ( Array.isArray( texture.image ) && texture.image.length === 6 ) ) {
23507
23508 // CompressedTexture can have Array in image :/
23509
23510 // this function alone should take care of cube textures
23511 textures.setTextureCube( texture, slot );
23512
23513 } else {
23514
23515 // assumed: texture property of THREE.WebGLRenderTargetCube
23516
23517 textures.setTextureCubeDynamic( texture, slot );
23518
23519 }
23520
23521 };
23522
23523 }() );
23524
23525 this.getRenderTarget = function () {
23526
23527 return _currentRenderTarget;
23528
23529 };
23530
23531 this.setRenderTarget = function ( renderTarget ) {
23532
23533 _currentRenderTarget = renderTarget;
23534
23535 if ( renderTarget && properties.get( renderTarget ).__webglFramebuffer === undefined ) {
23536
23537 textures.setupRenderTarget( renderTarget );
23538
23539 }
23540
23541 var framebuffer = null;
23542 var isCube = false;
23543
23544 if ( renderTarget ) {
23545
23546 var __webglFramebuffer = properties.get( renderTarget ).__webglFramebuffer;
23547
23548 if ( renderTarget.isWebGLRenderTargetCube ) {
23549
23550 framebuffer = __webglFramebuffer[ renderTarget.activeCubeFace ];
23551 isCube = true;
23552
23553 } else {
23554
23555 framebuffer = __webglFramebuffer;
23556
23557 }
23558
23559 _currentViewport.copy( renderTarget.viewport );
23560 _currentScissor.copy( renderTarget.scissor );
23561 _currentScissorTest = renderTarget.scissorTest;
23562
23563 } else {
23564
23565 _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio );
23566 _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio );
23567 _currentScissorTest = _scissorTest;
23568
23569 }
23570
23571 if ( _currentFramebuffer !== framebuffer ) {
23572
23573 _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
23574 _currentFramebuffer = framebuffer;
23575
23576 }
23577
23578 state.viewport( _currentViewport );
23579 state.scissor( _currentScissor );
23580 state.setScissorTest( _currentScissorTest );
23581
23582 if ( isCube ) {
23583
23584 var textureProperties = properties.get( renderTarget.texture );
23585 _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + renderTarget.activeCubeFace, textureProperties.__webglTexture, renderTarget.activeMipMapLevel );
23586
23587 }
23588
23589 };
23590
23591 this.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer ) {
23592
23593 if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) {
23594
23595 console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' );
23596 return;
23597
23598 }
23599
23600 var framebuffer = properties.get( renderTarget ).__webglFramebuffer;
23601
23602 if ( framebuffer ) {
23603
23604 var restore = false;
23605
23606 if ( framebuffer !== _currentFramebuffer ) {
23607
23608 _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
23609
23610 restore = true;
23611
23612 }
23613
23614 try {
23615
23616 var texture = renderTarget.texture;
23617 var textureFormat = texture.format;
23618 var textureType = texture.type;
23619
23620 if ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_FORMAT ) ) {
23621
23622 console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' );
23623 return;
23624
23625 }
23626
23627 if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_TYPE ) && // IE11, Edge and Chrome Mac < 52 (#9513)
23628 ! ( textureType === FloatType && ( extensions.get( 'OES_texture_float' ) || extensions.get( 'WEBGL_color_buffer_float' ) ) ) && // Chrome Mac >= 52 and Firefox
23629 ! ( textureType === HalfFloatType && extensions.get( 'EXT_color_buffer_half_float' ) ) ) {
23630
23631 console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' );
23632 return;
23633
23634 }
23635
23636 if ( _gl.checkFramebufferStatus( _gl.FRAMEBUFFER ) === _gl.FRAMEBUFFER_COMPLETE ) {
23637
23638 // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604)
23639
23640 if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) {
23641
23642 _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer );
23643
23644 }
23645
23646 } else {
23647
23648 console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.' );
23649
23650 }
23651
23652 } finally {
23653
23654 if ( restore ) {
23655
23656 _gl.bindFramebuffer( _gl.FRAMEBUFFER, _currentFramebuffer );
23657
23658 }
23659
23660 }
23661
23662 }
23663
23664 };
23665
23666 this.copyFramebufferToTexture = function ( position, texture, level ) {
23667
23668 var width = texture.image.width;
23669 var height = texture.image.height;
23670 var glFormat = utils.convert( texture.format );
23671
23672 this.setTexture2D( texture, 0 );
23673
23674 _gl.copyTexImage2D( _gl.TEXTURE_2D, level || 0, glFormat, position.x, position.y, width, height, 0 );
23675
23676 };
23677
23678 this.copyTextureToTexture = function ( position, srcTexture, dstTexture, level ) {
23679
23680 var width = srcTexture.image.width;
23681 var height = srcTexture.image.height;
23682 var glFormat = utils.convert( dstTexture.format );
23683 var glType = utils.convert( dstTexture.type );
23684 var pixels = srcTexture.isDataTexture ? srcTexture.image.data : srcTexture.image;
23685
23686 this.setTexture2D( dstTexture, 0 );
23687
23688 _gl.texSubImage2D( _gl.TEXTURE_2D, level || 0, position.x, position.y, width, height, glFormat, glType, pixels );
23689
23690 };
23691
23692}
23693
23694/**
23695 * @author mrdoob / http://mrdoob.com/
23696 * @author alteredq / http://alteredqualia.com/
23697 */
23698
23699function FogExp2( color, density ) {
23700
23701 this.name = '';
23702
23703 this.color = new Color( color );
23704 this.density = ( density !== undefined ) ? density : 0.00025;
23705
23706}
23707
23708FogExp2.prototype.isFogExp2 = true;
23709
23710FogExp2.prototype.clone = function () {
23711
23712 return new FogExp2( this.color.getHex(), this.density );
23713
23714};
23715
23716FogExp2.prototype.toJSON = function ( /* meta */ ) {
23717
23718 return {
23719 type: 'FogExp2',
23720 color: this.color.getHex(),
23721 density: this.density
23722 };
23723
23724};
23725
23726/**
23727 * @author mrdoob / http://mrdoob.com/
23728 * @author alteredq / http://alteredqualia.com/
23729 */
23730
23731function Fog( color, near, far ) {
23732
23733 this.name = '';
23734
23735 this.color = new Color( color );
23736
23737 this.near = ( near !== undefined ) ? near : 1;
23738 this.far = ( far !== undefined ) ? far : 1000;
23739
23740}
23741
23742Fog.prototype.isFog = true;
23743
23744Fog.prototype.clone = function () {
23745
23746 return new Fog( this.color.getHex(), this.near, this.far );
23747
23748};
23749
23750Fog.prototype.toJSON = function ( /* meta */ ) {
23751
23752 return {
23753 type: 'Fog',
23754 color: this.color.getHex(),
23755 near: this.near,
23756 far: this.far
23757 };
23758
23759};
23760
23761/**
23762 * @author mrdoob / http://mrdoob.com/
23763 */
23764
23765function Scene() {
23766
23767 Object3D.call( this );
23768
23769 this.type = 'Scene';
23770
23771 this.background = null;
23772 this.fog = null;
23773 this.overrideMaterial = null;
23774
23775 this.autoUpdate = true; // checked by the renderer
23776
23777}
23778
23779Scene.prototype = Object.assign( Object.create( Object3D.prototype ), {
23780
23781 constructor: Scene,
23782
23783 copy: function ( source, recursive ) {
23784
23785 Object3D.prototype.copy.call( this, source, recursive );
23786
23787 if ( source.background !== null ) this.background = source.background.clone();
23788 if ( source.fog !== null ) this.fog = source.fog.clone();
23789 if ( source.overrideMaterial !== null ) this.overrideMaterial = source.overrideMaterial.clone();
23790
23791 this.autoUpdate = source.autoUpdate;
23792 this.matrixAutoUpdate = source.matrixAutoUpdate;
23793
23794 return this;
23795
23796 },
23797
23798 toJSON: function ( meta ) {
23799
23800 var data = Object3D.prototype.toJSON.call( this, meta );
23801
23802 if ( this.background !== null ) data.object.background = this.background.toJSON( meta );
23803 if ( this.fog !== null ) data.object.fog = this.fog.toJSON();
23804
23805 return data;
23806
23807 }
23808
23809} );
23810
23811/**
23812 * @author alteredq / http://alteredqualia.com/
23813 *
23814 * parameters = {
23815 * color: <hex>,
23816 * opacity: <float>,
23817 * map: new THREE.Texture( <Image> ),
23818 *
23819 * uvOffset: new THREE.Vector2(),
23820 * uvScale: new THREE.Vector2()
23821 * }
23822 */
23823
23824function SpriteMaterial( parameters ) {
23825
23826 Material.call( this );
23827
23828 this.type = 'SpriteMaterial';
23829
23830 this.color = new Color( 0xffffff );
23831 this.map = null;
23832
23833 this.rotation = 0;
23834
23835 this.fog = false;
23836 this.lights = false;
23837
23838 this.setValues( parameters );
23839
23840}
23841
23842SpriteMaterial.prototype = Object.create( Material.prototype );
23843SpriteMaterial.prototype.constructor = SpriteMaterial;
23844SpriteMaterial.prototype.isSpriteMaterial = true;
23845
23846SpriteMaterial.prototype.copy = function ( source ) {
23847
23848 Material.prototype.copy.call( this, source );
23849
23850 this.color.copy( source.color );
23851 this.map = source.map;
23852
23853 this.rotation = source.rotation;
23854
23855 return this;
23856
23857};
23858
23859/**
23860 * @author mikael emtinger / http://gomo.se/
23861 * @author alteredq / http://alteredqualia.com/
23862 */
23863
23864function Sprite( material ) {
23865
23866 Object3D.call( this );
23867
23868 this.type = 'Sprite';
23869
23870 this.material = ( material !== undefined ) ? material : new SpriteMaterial();
23871
23872 this.center = new Vector2( 0.5, 0.5 );
23873
23874}
23875
23876Sprite.prototype = Object.assign( Object.create( Object3D.prototype ), {
23877
23878 constructor: Sprite,
23879
23880 isSprite: true,
23881
23882 raycast: ( function () {
23883
23884 var intersectPoint = new Vector3();
23885 var worldPosition = new Vector3();
23886 var worldScale = new Vector3();
23887
23888 return function raycast( raycaster, intersects ) {
23889
23890 worldPosition.setFromMatrixPosition( this.matrixWorld );
23891 raycaster.ray.closestPointToPoint( worldPosition, intersectPoint );
23892
23893 worldScale.setFromMatrixScale( this.matrixWorld );
23894 var guessSizeSq = worldScale.x * worldScale.y / 4;
23895
23896 if ( worldPosition.distanceToSquared( intersectPoint ) > guessSizeSq ) return;
23897
23898 var distance = raycaster.ray.origin.distanceTo( intersectPoint );
23899
23900 if ( distance < raycaster.near || distance > raycaster.far ) return;
23901
23902 intersects.push( {
23903
23904 distance: distance,
23905 point: intersectPoint.clone(),
23906 face: null,
23907 object: this
23908
23909 } );
23910
23911 };
23912
23913 }() ),
23914
23915 clone: function () {
23916
23917 return new this.constructor( this.material ).copy( this );
23918
23919 },
23920
23921 copy: function ( source ) {
23922
23923 Object3D.prototype.copy.call( this, source );
23924
23925 if ( source.center !== undefined ) this.center.copy( source.center );
23926
23927 return this;
23928
23929 }
23930
23931
23932} );
23933
23934/**
23935 * @author mikael emtinger / http://gomo.se/
23936 * @author alteredq / http://alteredqualia.com/
23937 * @author mrdoob / http://mrdoob.com/
23938 */
23939
23940function LOD() {
23941
23942 Object3D.call( this );
23943
23944 this.type = 'LOD';
23945
23946 Object.defineProperties( this, {
23947 levels: {
23948 enumerable: true,
23949 value: []
23950 }
23951 } );
23952
23953}
23954
23955LOD.prototype = Object.assign( Object.create( Object3D.prototype ), {
23956
23957 constructor: LOD,
23958
23959 copy: function ( source ) {
23960
23961 Object3D.prototype.copy.call( this, source, false );
23962
23963 var levels = source.levels;
23964
23965 for ( var i = 0, l = levels.length; i < l; i ++ ) {
23966
23967 var level = levels[ i ];
23968
23969 this.addLevel( level.object.clone(), level.distance );
23970
23971 }
23972
23973 return this;
23974
23975 },
23976
23977 addLevel: function ( object, distance ) {
23978
23979 if ( distance === undefined ) distance = 0;
23980
23981 distance = Math.abs( distance );
23982
23983 var levels = this.levels;
23984
23985 for ( var l = 0; l < levels.length; l ++ ) {
23986
23987 if ( distance < levels[ l ].distance ) {
23988
23989 break;
23990
23991 }
23992
23993 }
23994
23995 levels.splice( l, 0, { distance: distance, object: object } );
23996
23997 this.add( object );
23998
23999 },
24000
24001 getObjectForDistance: function ( distance ) {
24002
24003 var levels = this.levels;
24004
24005 for ( var i = 1, l = levels.length; i < l; i ++ ) {
24006
24007 if ( distance < levels[ i ].distance ) {
24008
24009 break;
24010
24011 }
24012
24013 }
24014
24015 return levels[ i - 1 ].object;
24016
24017 },
24018
24019 raycast: ( function () {
24020
24021 var matrixPosition = new Vector3();
24022
24023 return function raycast( raycaster, intersects ) {
24024
24025 matrixPosition.setFromMatrixPosition( this.matrixWorld );
24026
24027 var distance = raycaster.ray.origin.distanceTo( matrixPosition );
24028
24029 this.getObjectForDistance( distance ).raycast( raycaster, intersects );
24030
24031 };
24032
24033 }() ),
24034
24035 update: function () {
24036
24037 var v1 = new Vector3();
24038 var v2 = new Vector3();
24039
24040 return function update( camera ) {
24041
24042 var levels = this.levels;
24043
24044 if ( levels.length > 1 ) {
24045
24046 v1.setFromMatrixPosition( camera.matrixWorld );
24047 v2.setFromMatrixPosition( this.matrixWorld );
24048
24049 var distance = v1.distanceTo( v2 );
24050
24051 levels[ 0 ].object.visible = true;
24052
24053 for ( var i = 1, l = levels.length; i < l; i ++ ) {
24054
24055 if ( distance >= levels[ i ].distance ) {
24056
24057 levels[ i - 1 ].object.visible = false;
24058 levels[ i ].object.visible = true;
24059
24060 } else {
24061
24062 break;
24063
24064 }
24065
24066 }
24067
24068 for ( ; i < l; i ++ ) {
24069
24070 levels[ i ].object.visible = false;
24071
24072 }
24073
24074 }
24075
24076 };
24077
24078 }(),
24079
24080 toJSON: function ( meta ) {
24081
24082 var data = Object3D.prototype.toJSON.call( this, meta );
24083
24084 data.object.levels = [];
24085
24086 var levels = this.levels;
24087
24088 for ( var i = 0, l = levels.length; i < l; i ++ ) {
24089
24090 var level = levels[ i ];
24091
24092 data.object.levels.push( {
24093 object: level.object.uuid,
24094 distance: level.distance
24095 } );
24096
24097 }
24098
24099 return data;
24100
24101 }
24102
24103} );
24104
24105/**
24106 * @author mikael emtinger / http://gomo.se/
24107 * @author alteredq / http://alteredqualia.com/
24108 * @author michael guerrero / http://realitymeltdown.com
24109 * @author ikerr / http://verold.com
24110 */
24111
24112function Skeleton( bones, boneInverses ) {
24113
24114 // copy the bone array
24115
24116 bones = bones || [];
24117
24118 this.bones = bones.slice( 0 );
24119 this.boneMatrices = new Float32Array( this.bones.length * 16 );
24120
24121 // use the supplied bone inverses or calculate the inverses
24122
24123 if ( boneInverses === undefined ) {
24124
24125 this.calculateInverses();
24126
24127 } else {
24128
24129 if ( this.bones.length === boneInverses.length ) {
24130
24131 this.boneInverses = boneInverses.slice( 0 );
24132
24133 } else {
24134
24135 console.warn( 'THREE.Skeleton boneInverses is the wrong length.' );
24136
24137 this.boneInverses = [];
24138
24139 for ( var i = 0, il = this.bones.length; i < il; i ++ ) {
24140
24141 this.boneInverses.push( new Matrix4() );
24142
24143 }
24144
24145 }
24146
24147 }
24148
24149}
24150
24151Object.assign( Skeleton.prototype, {
24152
24153 calculateInverses: function () {
24154
24155 this.boneInverses = [];
24156
24157 for ( var i = 0, il = this.bones.length; i < il; i ++ ) {
24158
24159 var inverse = new Matrix4();
24160
24161 if ( this.bones[ i ] ) {
24162
24163 inverse.getInverse( this.bones[ i ].matrixWorld );
24164
24165 }
24166
24167 this.boneInverses.push( inverse );
24168
24169 }
24170
24171 },
24172
24173 pose: function () {
24174
24175 var bone, i, il;
24176
24177 // recover the bind-time world matrices
24178
24179 for ( i = 0, il = this.bones.length; i < il; i ++ ) {
24180
24181 bone = this.bones[ i ];
24182
24183 if ( bone ) {
24184
24185 bone.matrixWorld.getInverse( this.boneInverses[ i ] );
24186
24187 }
24188
24189 }
24190
24191 // compute the local matrices, positions, rotations and scales
24192
24193 for ( i = 0, il = this.bones.length; i < il; i ++ ) {
24194
24195 bone = this.bones[ i ];
24196
24197 if ( bone ) {
24198
24199 if ( bone.parent && bone.parent.isBone ) {
24200
24201 bone.matrix.getInverse( bone.parent.matrixWorld );
24202 bone.matrix.multiply( bone.matrixWorld );
24203
24204 } else {
24205
24206 bone.matrix.copy( bone.matrixWorld );
24207
24208 }
24209
24210 bone.matrix.decompose( bone.position, bone.quaternion, bone.scale );
24211
24212 }
24213
24214 }
24215
24216 },
24217
24218 update: ( function () {
24219
24220 var offsetMatrix = new Matrix4();
24221 var identityMatrix = new Matrix4();
24222
24223 return function update() {
24224
24225 var bones = this.bones;
24226 var boneInverses = this.boneInverses;
24227 var boneMatrices = this.boneMatrices;
24228 var boneTexture = this.boneTexture;
24229
24230 // flatten bone matrices to array
24231
24232 for ( var i = 0, il = bones.length; i < il; i ++ ) {
24233
24234 // compute the offset between the current and the original transform
24235
24236 var matrix = bones[ i ] ? bones[ i ].matrixWorld : identityMatrix;
24237
24238 offsetMatrix.multiplyMatrices( matrix, boneInverses[ i ] );
24239 offsetMatrix.toArray( boneMatrices, i * 16 );
24240
24241 }
24242
24243 if ( boneTexture !== undefined ) {
24244
24245 boneTexture.needsUpdate = true;
24246
24247 }
24248
24249 };
24250
24251 } )(),
24252
24253 clone: function () {
24254
24255 return new Skeleton( this.bones, this.boneInverses );
24256
24257 },
24258
24259 getBoneByName: function ( name ) {
24260
24261 for ( var i = 0, il = this.bones.length; i < il; i ++ ) {
24262
24263 var bone = this.bones[ i ];
24264
24265 if ( bone.name === name ) {
24266
24267 return bone;
24268
24269 }
24270
24271 }
24272
24273 return undefined;
24274
24275 }
24276
24277} );
24278
24279/**
24280 * @author mikael emtinger / http://gomo.se/
24281 * @author alteredq / http://alteredqualia.com/
24282 * @author ikerr / http://verold.com
24283 */
24284
24285function Bone() {
24286
24287 Object3D.call( this );
24288
24289 this.type = 'Bone';
24290
24291}
24292
24293Bone.prototype = Object.assign( Object.create( Object3D.prototype ), {
24294
24295 constructor: Bone,
24296
24297 isBone: true
24298
24299} );
24300
24301/**
24302 * @author mikael emtinger / http://gomo.se/
24303 * @author alteredq / http://alteredqualia.com/
24304 * @author ikerr / http://verold.com
24305 */
24306
24307function SkinnedMesh( geometry, material ) {
24308
24309 Mesh.call( this, geometry, material );
24310
24311 this.type = 'SkinnedMesh';
24312
24313 this.bindMode = 'attached';
24314 this.bindMatrix = new Matrix4();
24315 this.bindMatrixInverse = new Matrix4();
24316
24317 var bones = this.initBones();
24318 var skeleton = new Skeleton( bones );
24319
24320 this.bind( skeleton, this.matrixWorld );
24321
24322 this.normalizeSkinWeights();
24323
24324}
24325
24326SkinnedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), {
24327
24328 constructor: SkinnedMesh,
24329
24330 isSkinnedMesh: true,
24331
24332 initBones: function () {
24333
24334 var bones = [], bone, gbone;
24335 var i, il;
24336
24337 if ( this.geometry && this.geometry.bones !== undefined ) {
24338
24339 // first, create array of 'Bone' objects from geometry data
24340
24341 for ( i = 0, il = this.geometry.bones.length; i < il; i ++ ) {
24342
24343 gbone = this.geometry.bones[ i ];
24344
24345 // create new 'Bone' object
24346
24347 bone = new Bone();
24348 bones.push( bone );
24349
24350 // apply values
24351
24352 bone.name = gbone.name;
24353 bone.position.fromArray( gbone.pos );
24354 bone.quaternion.fromArray( gbone.rotq );
24355 if ( gbone.scl !== undefined ) bone.scale.fromArray( gbone.scl );
24356
24357 }
24358
24359 // second, create bone hierarchy
24360
24361 for ( i = 0, il = this.geometry.bones.length; i < il; i ++ ) {
24362
24363 gbone = this.geometry.bones[ i ];
24364
24365 if ( ( gbone.parent !== - 1 ) && ( gbone.parent !== null ) && ( bones[ gbone.parent ] !== undefined ) ) {
24366
24367 // subsequent bones in the hierarchy
24368
24369 bones[ gbone.parent ].add( bones[ i ] );
24370
24371 } else {
24372
24373 // topmost bone, immediate child of the skinned mesh
24374
24375 this.add( bones[ i ] );
24376
24377 }
24378
24379 }
24380
24381 }
24382
24383 // now the bones are part of the scene graph and children of the skinned mesh.
24384 // let's update the corresponding matrices
24385
24386 this.updateMatrixWorld( true );
24387
24388 return bones;
24389
24390 },
24391
24392 bind: function ( skeleton, bindMatrix ) {
24393
24394 this.skeleton = skeleton;
24395
24396 if ( bindMatrix === undefined ) {
24397
24398 this.updateMatrixWorld( true );
24399
24400 this.skeleton.calculateInverses();
24401
24402 bindMatrix = this.matrixWorld;
24403
24404 }
24405
24406 this.bindMatrix.copy( bindMatrix );
24407 this.bindMatrixInverse.getInverse( bindMatrix );
24408
24409 },
24410
24411 pose: function () {
24412
24413 this.skeleton.pose();
24414
24415 },
24416
24417 normalizeSkinWeights: function () {
24418
24419 var scale, i;
24420
24421 if ( this.geometry && this.geometry.isGeometry ) {
24422
24423 for ( i = 0; i < this.geometry.skinWeights.length; i ++ ) {
24424
24425 var sw = this.geometry.skinWeights[ i ];
24426
24427 scale = 1.0 / sw.manhattanLength();
24428
24429 if ( scale !== Infinity ) {
24430
24431 sw.multiplyScalar( scale );
24432
24433 } else {
24434
24435 sw.set( 1, 0, 0, 0 ); // do something reasonable
24436
24437 }
24438
24439 }
24440
24441 } else if ( this.geometry && this.geometry.isBufferGeometry ) {
24442
24443 var vec = new Vector4();
24444
24445 var skinWeight = this.geometry.attributes.skinWeight;
24446
24447 for ( i = 0; i < skinWeight.count; i ++ ) {
24448
24449 vec.x = skinWeight.getX( i );
24450 vec.y = skinWeight.getY( i );
24451 vec.z = skinWeight.getZ( i );
24452 vec.w = skinWeight.getW( i );
24453
24454 scale = 1.0 / vec.manhattanLength();
24455
24456 if ( scale !== Infinity ) {
24457
24458 vec.multiplyScalar( scale );
24459
24460 } else {
24461
24462 vec.set( 1, 0, 0, 0 ); // do something reasonable
24463
24464 }
24465
24466 skinWeight.setXYZW( i, vec.x, vec.y, vec.z, vec.w );
24467
24468 }
24469
24470 }
24471
24472 },
24473
24474 updateMatrixWorld: function ( force ) {
24475
24476 Mesh.prototype.updateMatrixWorld.call( this, force );
24477
24478 if ( this.bindMode === 'attached' ) {
24479
24480 this.bindMatrixInverse.getInverse( this.matrixWorld );
24481
24482 } else if ( this.bindMode === 'detached' ) {
24483
24484 this.bindMatrixInverse.getInverse( this.bindMatrix );
24485
24486 } else {
24487
24488 console.warn( 'THREE.SkinnedMesh: Unrecognized bindMode: ' + this.bindMode );
24489
24490 }
24491
24492 },
24493
24494 clone: function () {
24495
24496 return new this.constructor( this.geometry, this.material ).copy( this );
24497
24498 }
24499
24500} );
24501
24502/**
24503 * @author mrdoob / http://mrdoob.com/
24504 * @author alteredq / http://alteredqualia.com/
24505 *
24506 * parameters = {
24507 * color: <hex>,
24508 * opacity: <float>,
24509 *
24510 * linewidth: <float>,
24511 * linecap: "round",
24512 * linejoin: "round"
24513 * }
24514 */
24515
24516function LineBasicMaterial( parameters ) {
24517
24518 Material.call( this );
24519
24520 this.type = 'LineBasicMaterial';
24521
24522 this.color = new Color( 0xffffff );
24523
24524 this.linewidth = 1;
24525 this.linecap = 'round';
24526 this.linejoin = 'round';
24527
24528 this.lights = false;
24529
24530 this.setValues( parameters );
24531
24532}
24533
24534LineBasicMaterial.prototype = Object.create( Material.prototype );
24535LineBasicMaterial.prototype.constructor = LineBasicMaterial;
24536
24537LineBasicMaterial.prototype.isLineBasicMaterial = true;
24538
24539LineBasicMaterial.prototype.copy = function ( source ) {
24540
24541 Material.prototype.copy.call( this, source );
24542
24543 this.color.copy( source.color );
24544
24545 this.linewidth = source.linewidth;
24546 this.linecap = source.linecap;
24547 this.linejoin = source.linejoin;
24548
24549 return this;
24550
24551};
24552
24553/**
24554 * @author mrdoob / http://mrdoob.com/
24555 */
24556
24557function Line( geometry, material, mode ) {
24558
24559 if ( mode === 1 ) {
24560
24561 console.warn( 'THREE.Line: parameter THREE.LinePieces no longer supported. Created THREE.LineSegments instead.' );
24562 return new LineSegments( geometry, material );
24563
24564 }
24565
24566 Object3D.call( this );
24567
24568 this.type = 'Line';
24569
24570 this.geometry = geometry !== undefined ? geometry : new BufferGeometry();
24571 this.material = material !== undefined ? material : new LineBasicMaterial( { color: Math.random() * 0xffffff } );
24572
24573}
24574
24575Line.prototype = Object.assign( Object.create( Object3D.prototype ), {
24576
24577 constructor: Line,
24578
24579 isLine: true,
24580
24581 computeLineDistances: ( function () {
24582
24583 var start = new Vector3();
24584 var end = new Vector3();
24585
24586 return function computeLineDistances() {
24587
24588 var geometry = this.geometry;
24589
24590 if ( geometry.isBufferGeometry ) {
24591
24592 // we assume non-indexed geometry
24593
24594 if ( geometry.index === null ) {
24595
24596 var positionAttribute = geometry.attributes.position;
24597 var lineDistances = [ 0 ];
24598
24599 for ( var i = 1, l = positionAttribute.count; i < l; i ++ ) {
24600
24601 start.fromBufferAttribute( positionAttribute, i - 1 );
24602 end.fromBufferAttribute( positionAttribute, i );
24603
24604 lineDistances[ i ] = lineDistances[ i - 1 ];
24605 lineDistances[ i ] += start.distanceTo( end );
24606
24607 }
24608
24609 geometry.addAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );
24610
24611 } else {
24612
24613 console.warn( 'THREE.Line.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );
24614
24615 }
24616
24617 } else if ( geometry.isGeometry ) {
24618
24619 var vertices = geometry.vertices;
24620 var lineDistances = geometry.lineDistances;
24621
24622 lineDistances[ 0 ] = 0;
24623
24624 for ( var i = 1, l = vertices.length; i < l; i ++ ) {
24625
24626 lineDistances[ i ] = lineDistances[ i - 1 ];
24627 lineDistances[ i ] += vertices[ i - 1 ].distanceTo( vertices[ i ] );
24628
24629 }
24630
24631 }
24632
24633 return this;
24634
24635 };
24636
24637 }() ),
24638
24639 raycast: ( function () {
24640
24641 var inverseMatrix = new Matrix4();
24642 var ray = new Ray();
24643 var sphere = new Sphere();
24644
24645 return function raycast( raycaster, intersects ) {
24646
24647 var precision = raycaster.linePrecision;
24648 var precisionSq = precision * precision;
24649
24650 var geometry = this.geometry;
24651 var matrixWorld = this.matrixWorld;
24652
24653 // Checking boundingSphere distance to ray
24654
24655 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
24656
24657 sphere.copy( geometry.boundingSphere );
24658 sphere.applyMatrix4( matrixWorld );
24659
24660 if ( raycaster.ray.intersectsSphere( sphere ) === false ) return;
24661
24662 //
24663
24664 inverseMatrix.getInverse( matrixWorld );
24665 ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix );
24666
24667 var vStart = new Vector3();
24668 var vEnd = new Vector3();
24669 var interSegment = new Vector3();
24670 var interRay = new Vector3();
24671 var step = ( this && this.isLineSegments ) ? 2 : 1;
24672
24673 if ( geometry.isBufferGeometry ) {
24674
24675 var index = geometry.index;
24676 var attributes = geometry.attributes;
24677 var positions = attributes.position.array;
24678
24679 if ( index !== null ) {
24680
24681 var indices = index.array;
24682
24683 for ( var i = 0, l = indices.length - 1; i < l; i += step ) {
24684
24685 var a = indices[ i ];
24686 var b = indices[ i + 1 ];
24687
24688 vStart.fromArray( positions, a * 3 );
24689 vEnd.fromArray( positions, b * 3 );
24690
24691 var distSq = ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
24692
24693 if ( distSq > precisionSq ) continue;
24694
24695 interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
24696
24697 var distance = raycaster.ray.origin.distanceTo( interRay );
24698
24699 if ( distance < raycaster.near || distance > raycaster.far ) continue;
24700
24701 intersects.push( {
24702
24703 distance: distance,
24704 // What do we want? intersection point on the ray or on the segment??
24705 // point: raycaster.ray.at( distance ),
24706 point: interSegment.clone().applyMatrix4( this.matrixWorld ),
24707 index: i,
24708 face: null,
24709 faceIndex: null,
24710 object: this
24711
24712 } );
24713
24714 }
24715
24716 } else {
24717
24718 for ( var i = 0, l = positions.length / 3 - 1; i < l; i += step ) {
24719
24720 vStart.fromArray( positions, 3 * i );
24721 vEnd.fromArray( positions, 3 * i + 3 );
24722
24723 var distSq = ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
24724
24725 if ( distSq > precisionSq ) continue;
24726
24727 interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
24728
24729 var distance = raycaster.ray.origin.distanceTo( interRay );
24730
24731 if ( distance < raycaster.near || distance > raycaster.far ) continue;
24732
24733 intersects.push( {
24734
24735 distance: distance,
24736 // What do we want? intersection point on the ray or on the segment??
24737 // point: raycaster.ray.at( distance ),
24738 point: interSegment.clone().applyMatrix4( this.matrixWorld ),
24739 index: i,
24740 face: null,
24741 faceIndex: null,
24742 object: this
24743
24744 } );
24745
24746 }
24747
24748 }
24749
24750 } else if ( geometry.isGeometry ) {
24751
24752 var vertices = geometry.vertices;
24753 var nbVertices = vertices.length;
24754
24755 for ( var i = 0; i < nbVertices - 1; i += step ) {
24756
24757 var distSq = ray.distanceSqToSegment( vertices[ i ], vertices[ i + 1 ], interRay, interSegment );
24758
24759 if ( distSq > precisionSq ) continue;
24760
24761 interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
24762
24763 var distance = raycaster.ray.origin.distanceTo( interRay );
24764
24765 if ( distance < raycaster.near || distance > raycaster.far ) continue;
24766
24767 intersects.push( {
24768
24769 distance: distance,
24770 // What do we want? intersection point on the ray or on the segment??
24771 // point: raycaster.ray.at( distance ),
24772 point: interSegment.clone().applyMatrix4( this.matrixWorld ),
24773 index: i,
24774 face: null,
24775 faceIndex: null,
24776 object: this
24777
24778 } );
24779
24780 }
24781
24782 }
24783
24784 };
24785
24786 }() ),
24787
24788 clone: function () {
24789
24790 return new this.constructor( this.geometry, this.material ).copy( this );
24791
24792 }
24793
24794} );
24795
24796/**
24797 * @author mrdoob / http://mrdoob.com/
24798 */
24799
24800function LineSegments( geometry, material ) {
24801
24802 Line.call( this, geometry, material );
24803
24804 this.type = 'LineSegments';
24805
24806}
24807
24808LineSegments.prototype = Object.assign( Object.create( Line.prototype ), {
24809
24810 constructor: LineSegments,
24811
24812 isLineSegments: true,
24813
24814 computeLineDistances: ( function () {
24815
24816 var start = new Vector3();
24817 var end = new Vector3();
24818
24819 return function computeLineDistances() {
24820
24821 var geometry = this.geometry;
24822
24823 if ( geometry.isBufferGeometry ) {
24824
24825 // we assume non-indexed geometry
24826
24827 if ( geometry.index === null ) {
24828
24829 var positionAttribute = geometry.attributes.position;
24830 var lineDistances = [];
24831
24832 for ( var i = 0, l = positionAttribute.count; i < l; i += 2 ) {
24833
24834 start.fromBufferAttribute( positionAttribute, i );
24835 end.fromBufferAttribute( positionAttribute, i + 1 );
24836
24837 lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ];
24838 lineDistances[ i + 1 ] = lineDistances[ i ] + start.distanceTo( end );
24839
24840 }
24841
24842 geometry.addAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );
24843
24844 } else {
24845
24846 console.warn( 'THREE.LineSegments.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );
24847
24848 }
24849
24850 } else if ( geometry.isGeometry ) {
24851
24852 var vertices = geometry.vertices;
24853 var lineDistances = geometry.lineDistances;
24854
24855 for ( var i = 0, l = vertices.length; i < l; i += 2 ) {
24856
24857 start.copy( vertices[ i ] );
24858 end.copy( vertices[ i + 1 ] );
24859
24860 lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ];
24861 lineDistances[ i + 1 ] = lineDistances[ i ] + start.distanceTo( end );
24862
24863 }
24864
24865 }
24866
24867 return this;
24868
24869 };
24870
24871 }() )
24872
24873} );
24874
24875/**
24876 * @author mgreter / http://github.com/mgreter
24877 */
24878
24879function LineLoop( geometry, material ) {
24880
24881 Line.call( this, geometry, material );
24882
24883 this.type = 'LineLoop';
24884
24885}
24886
24887LineLoop.prototype = Object.assign( Object.create( Line.prototype ), {
24888
24889 constructor: LineLoop,
24890
24891 isLineLoop: true,
24892
24893} );
24894
24895/**
24896 * @author mrdoob / http://mrdoob.com/
24897 * @author alteredq / http://alteredqualia.com/
24898 *
24899 * parameters = {
24900 * color: <hex>,
24901 * opacity: <float>,
24902 * map: new THREE.Texture( <Image> ),
24903 *
24904 * size: <float>,
24905 * sizeAttenuation: <bool>
24906 * }
24907 */
24908
24909function PointsMaterial( parameters ) {
24910
24911 Material.call( this );
24912
24913 this.type = 'PointsMaterial';
24914
24915 this.color = new Color( 0xffffff );
24916
24917 this.map = null;
24918
24919 this.size = 1;
24920 this.sizeAttenuation = true;
24921
24922 this.lights = false;
24923
24924 this.setValues( parameters );
24925
24926}
24927
24928PointsMaterial.prototype = Object.create( Material.prototype );
24929PointsMaterial.prototype.constructor = PointsMaterial;
24930
24931PointsMaterial.prototype.isPointsMaterial = true;
24932
24933PointsMaterial.prototype.copy = function ( source ) {
24934
24935 Material.prototype.copy.call( this, source );
24936
24937 this.color.copy( source.color );
24938
24939 this.map = source.map;
24940
24941 this.size = source.size;
24942 this.sizeAttenuation = source.sizeAttenuation;
24943
24944 return this;
24945
24946};
24947
24948/**
24949 * @author alteredq / http://alteredqualia.com/
24950 */
24951
24952function Points( geometry, material ) {
24953
24954 Object3D.call( this );
24955
24956 this.type = 'Points';
24957
24958 this.geometry = geometry !== undefined ? geometry : new BufferGeometry();
24959 this.material = material !== undefined ? material : new PointsMaterial( { color: Math.random() * 0xffffff } );
24960
24961}
24962
24963Points.prototype = Object.assign( Object.create( Object3D.prototype ), {
24964
24965 constructor: Points,
24966
24967 isPoints: true,
24968
24969 raycast: ( function () {
24970
24971 var inverseMatrix = new Matrix4();
24972 var ray = new Ray();
24973 var sphere = new Sphere();
24974
24975 return function raycast( raycaster, intersects ) {
24976
24977 var object = this;
24978 var geometry = this.geometry;
24979 var matrixWorld = this.matrixWorld;
24980 var threshold = raycaster.params.Points.threshold;
24981
24982 // Checking boundingSphere distance to ray
24983
24984 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
24985
24986 sphere.copy( geometry.boundingSphere );
24987 sphere.applyMatrix4( matrixWorld );
24988 sphere.radius += threshold;
24989
24990 if ( raycaster.ray.intersectsSphere( sphere ) === false ) return;
24991
24992 //
24993
24994 inverseMatrix.getInverse( matrixWorld );
24995 ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix );
24996
24997 var localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
24998 var localThresholdSq = localThreshold * localThreshold;
24999 var position = new Vector3();
25000 var intersectPoint = new Vector3();
25001
25002 function testPoint( point, index ) {
25003
25004 var rayPointDistanceSq = ray.distanceSqToPoint( point );
25005
25006 if ( rayPointDistanceSq < localThresholdSq ) {
25007
25008 ray.closestPointToPoint( point, intersectPoint );
25009 intersectPoint.applyMatrix4( matrixWorld );
25010
25011 var distance = raycaster.ray.origin.distanceTo( intersectPoint );
25012
25013 if ( distance < raycaster.near || distance > raycaster.far ) return;
25014
25015 intersects.push( {
25016
25017 distance: distance,
25018 distanceToRay: Math.sqrt( rayPointDistanceSq ),
25019 point: intersectPoint.clone(),
25020 index: index,
25021 face: null,
25022 object: object
25023
25024 } );
25025
25026 }
25027
25028 }
25029
25030 if ( geometry.isBufferGeometry ) {
25031
25032 var index = geometry.index;
25033 var attributes = geometry.attributes;
25034 var positions = attributes.position.array;
25035
25036 if ( index !== null ) {
25037
25038 var indices = index.array;
25039
25040 for ( var i = 0, il = indices.length; i < il; i ++ ) {
25041
25042 var a = indices[ i ];
25043
25044 position.fromArray( positions, a * 3 );
25045
25046 testPoint( position, a );
25047
25048 }
25049
25050 } else {
25051
25052 for ( var i = 0, l = positions.length / 3; i < l; i ++ ) {
25053
25054 position.fromArray( positions, i * 3 );
25055
25056 testPoint( position, i );
25057
25058 }
25059
25060 }
25061
25062 } else {
25063
25064 var vertices = geometry.vertices;
25065
25066 for ( var i = 0, l = vertices.length; i < l; i ++ ) {
25067
25068 testPoint( vertices[ i ], i );
25069
25070 }
25071
25072 }
25073
25074 };
25075
25076 }() ),
25077
25078 clone: function () {
25079
25080 return new this.constructor( this.geometry, this.material ).copy( this );
25081
25082 }
25083
25084} );
25085
25086/**
25087 * @author mrdoob / http://mrdoob.com/
25088 */
25089
25090function Group() {
25091
25092 Object3D.call( this );
25093
25094 this.type = 'Group';
25095
25096}
25097
25098Group.prototype = Object.assign( Object.create( Object3D.prototype ), {
25099
25100 constructor: Group,
25101
25102 isGroup: true
25103
25104} );
25105
25106/**
25107 * @author mrdoob / http://mrdoob.com/
25108 */
25109
25110function VideoTexture( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
25111
25112 Texture.call( this, video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
25113
25114 this.generateMipmaps = false;
25115
25116}
25117
25118VideoTexture.prototype = Object.assign( Object.create( Texture.prototype ), {
25119
25120 constructor: VideoTexture,
25121
25122 isVideoTexture: true,
25123
25124 update: function () {
25125
25126 var video = this.image;
25127
25128 if ( video.readyState >= video.HAVE_CURRENT_DATA ) {
25129
25130 this.needsUpdate = true;
25131
25132 }
25133
25134 }
25135
25136} );
25137
25138/**
25139 * @author alteredq / http://alteredqualia.com/
25140 */
25141
25142function CompressedTexture( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) {
25143
25144 Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
25145
25146 this.image = { width: width, height: height };
25147 this.mipmaps = mipmaps;
25148
25149 // no flipping for cube textures
25150 // (also flipping doesn't work for compressed textures )
25151
25152 this.flipY = false;
25153
25154 // can't generate mipmaps for compressed textures
25155 // mips must be embedded in DDS files
25156
25157 this.generateMipmaps = false;
25158
25159}
25160
25161CompressedTexture.prototype = Object.create( Texture.prototype );
25162CompressedTexture.prototype.constructor = CompressedTexture;
25163
25164CompressedTexture.prototype.isCompressedTexture = true;
25165
25166/**
25167 * @author Matt DesLauriers / @mattdesl
25168 * @author atix / arthursilber.de
25169 */
25170
25171function DepthTexture( width, height, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format ) {
25172
25173 format = format !== undefined ? format : DepthFormat;
25174
25175 if ( format !== DepthFormat && format !== DepthStencilFormat ) {
25176
25177 throw new Error( 'DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat' );
25178
25179 }
25180
25181 if ( type === undefined && format === DepthFormat ) type = UnsignedShortType;
25182 if ( type === undefined && format === DepthStencilFormat ) type = UnsignedInt248Type;
25183
25184 Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
25185
25186 this.image = { width: width, height: height };
25187
25188 this.magFilter = magFilter !== undefined ? magFilter : NearestFilter;
25189 this.minFilter = minFilter !== undefined ? minFilter : NearestFilter;
25190
25191 this.flipY = false;
25192 this.generateMipmaps = false;
25193
25194}
25195
25196DepthTexture.prototype = Object.create( Texture.prototype );
25197DepthTexture.prototype.constructor = DepthTexture;
25198DepthTexture.prototype.isDepthTexture = true;
25199
25200/**
25201 * @author mrdoob / http://mrdoob.com/
25202 * @author Mugen87 / https://github.com/Mugen87
25203 */
25204
25205function WireframeGeometry( geometry ) {
25206
25207 BufferGeometry.call( this );
25208
25209 this.type = 'WireframeGeometry';
25210
25211 // buffer
25212
25213 var vertices = [];
25214
25215 // helper variables
25216
25217 var i, j, l, o, ol;
25218 var edge = [ 0, 0 ], edges = {}, e, edge1, edge2;
25219 var key, keys = [ 'a', 'b', 'c' ];
25220 var vertex;
25221
25222 // different logic for Geometry and BufferGeometry
25223
25224 if ( geometry && geometry.isGeometry ) {
25225
25226 // create a data structure that contains all edges without duplicates
25227
25228 var faces = geometry.faces;
25229
25230 for ( i = 0, l = faces.length; i < l; i ++ ) {
25231
25232 var face = faces[ i ];
25233
25234 for ( j = 0; j < 3; j ++ ) {
25235
25236 edge1 = face[ keys[ j ] ];
25237 edge2 = face[ keys[ ( j + 1 ) % 3 ] ];
25238 edge[ 0 ] = Math.min( edge1, edge2 ); // sorting prevents duplicates
25239 edge[ 1 ] = Math.max( edge1, edge2 );
25240
25241 key = edge[ 0 ] + ',' + edge[ 1 ];
25242
25243 if ( edges[ key ] === undefined ) {
25244
25245 edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ] };
25246
25247 }
25248
25249 }
25250
25251 }
25252
25253 // generate vertices
25254
25255 for ( key in edges ) {
25256
25257 e = edges[ key ];
25258
25259 vertex = geometry.vertices[ e.index1 ];
25260 vertices.push( vertex.x, vertex.y, vertex.z );
25261
25262 vertex = geometry.vertices[ e.index2 ];
25263 vertices.push( vertex.x, vertex.y, vertex.z );
25264
25265 }
25266
25267 } else if ( geometry && geometry.isBufferGeometry ) {
25268
25269 var position, indices, groups;
25270 var group, start, count;
25271 var index1, index2;
25272
25273 vertex = new Vector3();
25274
25275 if ( geometry.index !== null ) {
25276
25277 // indexed BufferGeometry
25278
25279 position = geometry.attributes.position;
25280 indices = geometry.index;
25281 groups = geometry.groups;
25282
25283 if ( groups.length === 0 ) {
25284
25285 groups = [ { start: 0, count: indices.count, materialIndex: 0 } ];
25286
25287 }
25288
25289 // create a data structure that contains all eges without duplicates
25290
25291 for ( o = 0, ol = groups.length; o < ol; ++ o ) {
25292
25293 group = groups[ o ];
25294
25295 start = group.start;
25296 count = group.count;
25297
25298 for ( i = start, l = ( start + count ); i < l; i += 3 ) {
25299
25300 for ( j = 0; j < 3; j ++ ) {
25301
25302 edge1 = indices.getX( i + j );
25303 edge2 = indices.getX( i + ( j + 1 ) % 3 );
25304 edge[ 0 ] = Math.min( edge1, edge2 ); // sorting prevents duplicates
25305 edge[ 1 ] = Math.max( edge1, edge2 );
25306
25307 key = edge[ 0 ] + ',' + edge[ 1 ];
25308
25309 if ( edges[ key ] === undefined ) {
25310
25311 edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ] };
25312
25313 }
25314
25315 }
25316
25317 }
25318
25319 }
25320
25321 // generate vertices
25322
25323 for ( key in edges ) {
25324
25325 e = edges[ key ];
25326
25327 vertex.fromBufferAttribute( position, e.index1 );
25328 vertices.push( vertex.x, vertex.y, vertex.z );
25329
25330 vertex.fromBufferAttribute( position, e.index2 );
25331 vertices.push( vertex.x, vertex.y, vertex.z );
25332
25333 }
25334
25335 } else {
25336
25337 // non-indexed BufferGeometry
25338
25339 position = geometry.attributes.position;
25340
25341 for ( i = 0, l = ( position.count / 3 ); i < l; i ++ ) {
25342
25343 for ( j = 0; j < 3; j ++ ) {
25344
25345 // three edges per triangle, an edge is represented as (index1, index2)
25346 // e.g. the first triangle has the following edges: (0,1),(1,2),(2,0)
25347
25348 index1 = 3 * i + j;
25349 vertex.fromBufferAttribute( position, index1 );
25350 vertices.push( vertex.x, vertex.y, vertex.z );
25351
25352 index2 = 3 * i + ( ( j + 1 ) % 3 );
25353 vertex.fromBufferAttribute( position, index2 );
25354 vertices.push( vertex.x, vertex.y, vertex.z );
25355
25356 }
25357
25358 }
25359
25360 }
25361
25362 }
25363
25364 // build geometry
25365
25366 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
25367
25368}
25369
25370WireframeGeometry.prototype = Object.create( BufferGeometry.prototype );
25371WireframeGeometry.prototype.constructor = WireframeGeometry;
25372
25373/**
25374 * @author zz85 / https://github.com/zz85
25375 * @author Mugen87 / https://github.com/Mugen87
25376 *
25377 * Parametric Surfaces Geometry
25378 * based on the brilliant article by @prideout http://prideout.net/blog/?p=44
25379 */
25380
25381// ParametricGeometry
25382
25383function ParametricGeometry( func, slices, stacks ) {
25384
25385 Geometry.call( this );
25386
25387 this.type = 'ParametricGeometry';
25388
25389 this.parameters = {
25390 func: func,
25391 slices: slices,
25392 stacks: stacks
25393 };
25394
25395 this.fromBufferGeometry( new ParametricBufferGeometry( func, slices, stacks ) );
25396 this.mergeVertices();
25397
25398}
25399
25400ParametricGeometry.prototype = Object.create( Geometry.prototype );
25401ParametricGeometry.prototype.constructor = ParametricGeometry;
25402
25403// ParametricBufferGeometry
25404
25405function ParametricBufferGeometry( func, slices, stacks ) {
25406
25407 BufferGeometry.call( this );
25408
25409 this.type = 'ParametricBufferGeometry';
25410
25411 this.parameters = {
25412 func: func,
25413 slices: slices,
25414 stacks: stacks
25415 };
25416
25417 // buffers
25418
25419 var indices = [];
25420 var vertices = [];
25421 var normals = [];
25422 var uvs = [];
25423
25424 var EPS = 0.00001;
25425
25426 var normal = new Vector3();
25427
25428 var p0 = new Vector3(), p1 = new Vector3();
25429 var pu = new Vector3(), pv = new Vector3();
25430
25431 var i, j;
25432
25433 // generate vertices, normals and uvs
25434
25435 var sliceCount = slices + 1;
25436
25437 for ( i = 0; i <= stacks; i ++ ) {
25438
25439 var v = i / stacks;
25440
25441 for ( j = 0; j <= slices; j ++ ) {
25442
25443 var u = j / slices;
25444
25445 // vertex
25446
25447 func( u, v, p0 );
25448 vertices.push( p0.x, p0.y, p0.z );
25449
25450 // normal
25451
25452 // approximate tangent vectors via finite differences
25453
25454 if ( u - EPS >= 0 ) {
25455
25456 func( u - EPS, v, p1 );
25457 pu.subVectors( p0, p1 );
25458
25459 } else {
25460
25461 func( u + EPS, v, p1 );
25462 pu.subVectors( p1, p0 );
25463
25464 }
25465
25466 if ( v - EPS >= 0 ) {
25467
25468 func( u, v - EPS, p1 );
25469 pv.subVectors( p0, p1 );
25470
25471 } else {
25472
25473 func( u, v + EPS, p1 );
25474 pv.subVectors( p1, p0 );
25475
25476 }
25477
25478 // cross product of tangent vectors returns surface normal
25479
25480 normal.crossVectors( pu, pv ).normalize();
25481 normals.push( normal.x, normal.y, normal.z );
25482
25483 // uv
25484
25485 uvs.push( u, v );
25486
25487 }
25488
25489 }
25490
25491 // generate indices
25492
25493 for ( i = 0; i < stacks; i ++ ) {
25494
25495 for ( j = 0; j < slices; j ++ ) {
25496
25497 var a = i * sliceCount + j;
25498 var b = i * sliceCount + j + 1;
25499 var c = ( i + 1 ) * sliceCount + j + 1;
25500 var d = ( i + 1 ) * sliceCount + j;
25501
25502 // faces one and two
25503
25504 indices.push( a, b, d );
25505 indices.push( b, c, d );
25506
25507 }
25508
25509 }
25510
25511 // build geometry
25512
25513 this.setIndex( indices );
25514 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
25515 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
25516 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
25517
25518}
25519
25520ParametricBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
25521ParametricBufferGeometry.prototype.constructor = ParametricBufferGeometry;
25522
25523/**
25524 * @author clockworkgeek / https://github.com/clockworkgeek
25525 * @author timothypratley / https://github.com/timothypratley
25526 * @author WestLangley / http://github.com/WestLangley
25527 * @author Mugen87 / https://github.com/Mugen87
25528 */
25529
25530// PolyhedronGeometry
25531
25532function PolyhedronGeometry( vertices, indices, radius, detail ) {
25533
25534 Geometry.call( this );
25535
25536 this.type = 'PolyhedronGeometry';
25537
25538 this.parameters = {
25539 vertices: vertices,
25540 indices: indices,
25541 radius: radius,
25542 detail: detail
25543 };
25544
25545 this.fromBufferGeometry( new PolyhedronBufferGeometry( vertices, indices, radius, detail ) );
25546 this.mergeVertices();
25547
25548}
25549
25550PolyhedronGeometry.prototype = Object.create( Geometry.prototype );
25551PolyhedronGeometry.prototype.constructor = PolyhedronGeometry;
25552
25553// PolyhedronBufferGeometry
25554
25555function PolyhedronBufferGeometry( vertices, indices, radius, detail ) {
25556
25557 BufferGeometry.call( this );
25558
25559 this.type = 'PolyhedronBufferGeometry';
25560
25561 this.parameters = {
25562 vertices: vertices,
25563 indices: indices,
25564 radius: radius,
25565 detail: detail
25566 };
25567
25568 radius = radius || 1;
25569 detail = detail || 0;
25570
25571 // default buffer data
25572
25573 var vertexBuffer = [];
25574 var uvBuffer = [];
25575
25576 // the subdivision creates the vertex buffer data
25577
25578 subdivide( detail );
25579
25580 // all vertices should lie on a conceptual sphere with a given radius
25581
25582 appplyRadius( radius );
25583
25584 // finally, create the uv data
25585
25586 generateUVs();
25587
25588 // build non-indexed geometry
25589
25590 this.addAttribute( 'position', new Float32BufferAttribute( vertexBuffer, 3 ) );
25591 this.addAttribute( 'normal', new Float32BufferAttribute( vertexBuffer.slice(), 3 ) );
25592 this.addAttribute( 'uv', new Float32BufferAttribute( uvBuffer, 2 ) );
25593
25594 if ( detail === 0 ) {
25595
25596 this.computeVertexNormals(); // flat normals
25597
25598 } else {
25599
25600 this.normalizeNormals(); // smooth normals
25601
25602 }
25603
25604 // helper functions
25605
25606 function subdivide( detail ) {
25607
25608 var a = new Vector3();
25609 var b = new Vector3();
25610 var c = new Vector3();
25611
25612 // iterate over all faces and apply a subdivison with the given detail value
25613
25614 for ( var i = 0; i < indices.length; i += 3 ) {
25615
25616 // get the vertices of the face
25617
25618 getVertexByIndex( indices[ i + 0 ], a );
25619 getVertexByIndex( indices[ i + 1 ], b );
25620 getVertexByIndex( indices[ i + 2 ], c );
25621
25622 // perform subdivision
25623
25624 subdivideFace( a, b, c, detail );
25625
25626 }
25627
25628 }
25629
25630 function subdivideFace( a, b, c, detail ) {
25631
25632 var cols = Math.pow( 2, detail );
25633
25634 // we use this multidimensional array as a data structure for creating the subdivision
25635
25636 var v = [];
25637
25638 var i, j;
25639
25640 // construct all of the vertices for this subdivision
25641
25642 for ( i = 0; i <= cols; i ++ ) {
25643
25644 v[ i ] = [];
25645
25646 var aj = a.clone().lerp( c, i / cols );
25647 var bj = b.clone().lerp( c, i / cols );
25648
25649 var rows = cols - i;
25650
25651 for ( j = 0; j <= rows; j ++ ) {
25652
25653 if ( j === 0 && i === cols ) {
25654
25655 v[ i ][ j ] = aj;
25656
25657 } else {
25658
25659 v[ i ][ j ] = aj.clone().lerp( bj, j / rows );
25660
25661 }
25662
25663 }
25664
25665 }
25666
25667 // construct all of the faces
25668
25669 for ( i = 0; i < cols; i ++ ) {
25670
25671 for ( j = 0; j < 2 * ( cols - i ) - 1; j ++ ) {
25672
25673 var k = Math.floor( j / 2 );
25674
25675 if ( j % 2 === 0 ) {
25676
25677 pushVertex( v[ i ][ k + 1 ] );
25678 pushVertex( v[ i + 1 ][ k ] );
25679 pushVertex( v[ i ][ k ] );
25680
25681 } else {
25682
25683 pushVertex( v[ i ][ k + 1 ] );
25684 pushVertex( v[ i + 1 ][ k + 1 ] );
25685 pushVertex( v[ i + 1 ][ k ] );
25686
25687 }
25688
25689 }
25690
25691 }
25692
25693 }
25694
25695 function appplyRadius( radius ) {
25696
25697 var vertex = new Vector3();
25698
25699 // iterate over the entire buffer and apply the radius to each vertex
25700
25701 for ( var i = 0; i < vertexBuffer.length; i += 3 ) {
25702
25703 vertex.x = vertexBuffer[ i + 0 ];
25704 vertex.y = vertexBuffer[ i + 1 ];
25705 vertex.z = vertexBuffer[ i + 2 ];
25706
25707 vertex.normalize().multiplyScalar( radius );
25708
25709 vertexBuffer[ i + 0 ] = vertex.x;
25710 vertexBuffer[ i + 1 ] = vertex.y;
25711 vertexBuffer[ i + 2 ] = vertex.z;
25712
25713 }
25714
25715 }
25716
25717 function generateUVs() {
25718
25719 var vertex = new Vector3();
25720
25721 for ( var i = 0; i < vertexBuffer.length; i += 3 ) {
25722
25723 vertex.x = vertexBuffer[ i + 0 ];
25724 vertex.y = vertexBuffer[ i + 1 ];
25725 vertex.z = vertexBuffer[ i + 2 ];
25726
25727 var u = azimuth( vertex ) / 2 / Math.PI + 0.5;
25728 var v = inclination( vertex ) / Math.PI + 0.5;
25729 uvBuffer.push( u, 1 - v );
25730
25731 }
25732
25733 correctUVs();
25734
25735 correctSeam();
25736
25737 }
25738
25739 function correctSeam() {
25740
25741 // handle case when face straddles the seam, see #3269
25742
25743 for ( var i = 0; i < uvBuffer.length; i += 6 ) {
25744
25745 // uv data of a single face
25746
25747 var x0 = uvBuffer[ i + 0 ];
25748 var x1 = uvBuffer[ i + 2 ];
25749 var x2 = uvBuffer[ i + 4 ];
25750
25751 var max = Math.max( x0, x1, x2 );
25752 var min = Math.min( x0, x1, x2 );
25753
25754 // 0.9 is somewhat arbitrary
25755
25756 if ( max > 0.9 && min < 0.1 ) {
25757
25758 if ( x0 < 0.2 ) uvBuffer[ i + 0 ] += 1;
25759 if ( x1 < 0.2 ) uvBuffer[ i + 2 ] += 1;
25760 if ( x2 < 0.2 ) uvBuffer[ i + 4 ] += 1;
25761
25762 }
25763
25764 }
25765
25766 }
25767
25768 function pushVertex( vertex ) {
25769
25770 vertexBuffer.push( vertex.x, vertex.y, vertex.z );
25771
25772 }
25773
25774 function getVertexByIndex( index, vertex ) {
25775
25776 var stride = index * 3;
25777
25778 vertex.x = vertices[ stride + 0 ];
25779 vertex.y = vertices[ stride + 1 ];
25780 vertex.z = vertices[ stride + 2 ];
25781
25782 }
25783
25784 function correctUVs() {
25785
25786 var a = new Vector3();
25787 var b = new Vector3();
25788 var c = new Vector3();
25789
25790 var centroid = new Vector3();
25791
25792 var uvA = new Vector2();
25793 var uvB = new Vector2();
25794 var uvC = new Vector2();
25795
25796 for ( var i = 0, j = 0; i < vertexBuffer.length; i += 9, j += 6 ) {
25797
25798 a.set( vertexBuffer[ i + 0 ], vertexBuffer[ i + 1 ], vertexBuffer[ i + 2 ] );
25799 b.set( vertexBuffer[ i + 3 ], vertexBuffer[ i + 4 ], vertexBuffer[ i + 5 ] );
25800 c.set( vertexBuffer[ i + 6 ], vertexBuffer[ i + 7 ], vertexBuffer[ i + 8 ] );
25801
25802 uvA.set( uvBuffer[ j + 0 ], uvBuffer[ j + 1 ] );
25803 uvB.set( uvBuffer[ j + 2 ], uvBuffer[ j + 3 ] );
25804 uvC.set( uvBuffer[ j + 4 ], uvBuffer[ j + 5 ] );
25805
25806 centroid.copy( a ).add( b ).add( c ).divideScalar( 3 );
25807
25808 var azi = azimuth( centroid );
25809
25810 correctUV( uvA, j + 0, a, azi );
25811 correctUV( uvB, j + 2, b, azi );
25812 correctUV( uvC, j + 4, c, azi );
25813
25814 }
25815
25816 }
25817
25818 function correctUV( uv, stride, vector, azimuth ) {
25819
25820 if ( ( azimuth < 0 ) && ( uv.x === 1 ) ) {
25821
25822 uvBuffer[ stride ] = uv.x - 1;
25823
25824 }
25825
25826 if ( ( vector.x === 0 ) && ( vector.z === 0 ) ) {
25827
25828 uvBuffer[ stride ] = azimuth / 2 / Math.PI + 0.5;
25829
25830 }
25831
25832 }
25833
25834 // Angle around the Y axis, counter-clockwise when looking from above.
25835
25836 function azimuth( vector ) {
25837
25838 return Math.atan2( vector.z, - vector.x );
25839
25840 }
25841
25842
25843 // Angle above the XZ plane.
25844
25845 function inclination( vector ) {
25846
25847 return Math.atan2( - vector.y, Math.sqrt( ( vector.x * vector.x ) + ( vector.z * vector.z ) ) );
25848
25849 }
25850
25851}
25852
25853PolyhedronBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
25854PolyhedronBufferGeometry.prototype.constructor = PolyhedronBufferGeometry;
25855
25856/**
25857 * @author timothypratley / https://github.com/timothypratley
25858 * @author Mugen87 / https://github.com/Mugen87
25859 */
25860
25861// TetrahedronGeometry
25862
25863function TetrahedronGeometry( radius, detail ) {
25864
25865 Geometry.call( this );
25866
25867 this.type = 'TetrahedronGeometry';
25868
25869 this.parameters = {
25870 radius: radius,
25871 detail: detail
25872 };
25873
25874 this.fromBufferGeometry( new TetrahedronBufferGeometry( radius, detail ) );
25875 this.mergeVertices();
25876
25877}
25878
25879TetrahedronGeometry.prototype = Object.create( Geometry.prototype );
25880TetrahedronGeometry.prototype.constructor = TetrahedronGeometry;
25881
25882// TetrahedronBufferGeometry
25883
25884function TetrahedronBufferGeometry( radius, detail ) {
25885
25886 var vertices = [
25887 1, 1, 1, - 1, - 1, 1, - 1, 1, - 1, 1, - 1, - 1
25888 ];
25889
25890 var indices = [
25891 2, 1, 0, 0, 3, 2, 1, 3, 0, 2, 3, 1
25892 ];
25893
25894 PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail );
25895
25896 this.type = 'TetrahedronBufferGeometry';
25897
25898 this.parameters = {
25899 radius: radius,
25900 detail: detail
25901 };
25902
25903}
25904
25905TetrahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype );
25906TetrahedronBufferGeometry.prototype.constructor = TetrahedronBufferGeometry;
25907
25908/**
25909 * @author timothypratley / https://github.com/timothypratley
25910 * @author Mugen87 / https://github.com/Mugen87
25911 */
25912
25913// OctahedronGeometry
25914
25915function OctahedronGeometry( radius, detail ) {
25916
25917 Geometry.call( this );
25918
25919 this.type = 'OctahedronGeometry';
25920
25921 this.parameters = {
25922 radius: radius,
25923 detail: detail
25924 };
25925
25926 this.fromBufferGeometry( new OctahedronBufferGeometry( radius, detail ) );
25927 this.mergeVertices();
25928
25929}
25930
25931OctahedronGeometry.prototype = Object.create( Geometry.prototype );
25932OctahedronGeometry.prototype.constructor = OctahedronGeometry;
25933
25934// OctahedronBufferGeometry
25935
25936function OctahedronBufferGeometry( radius, detail ) {
25937
25938 var vertices = [
25939 1, 0, 0, - 1, 0, 0, 0, 1, 0,
25940 0, - 1, 0, 0, 0, 1, 0, 0, - 1
25941 ];
25942
25943 var indices = [
25944 0, 2, 4, 0, 4, 3, 0, 3, 5,
25945 0, 5, 2, 1, 2, 5, 1, 5, 3,
25946 1, 3, 4, 1, 4, 2
25947 ];
25948
25949 PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail );
25950
25951 this.type = 'OctahedronBufferGeometry';
25952
25953 this.parameters = {
25954 radius: radius,
25955 detail: detail
25956 };
25957
25958}
25959
25960OctahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype );
25961OctahedronBufferGeometry.prototype.constructor = OctahedronBufferGeometry;
25962
25963/**
25964 * @author timothypratley / https://github.com/timothypratley
25965 * @author Mugen87 / https://github.com/Mugen87
25966 */
25967
25968// IcosahedronGeometry
25969
25970function IcosahedronGeometry( radius, detail ) {
25971
25972 Geometry.call( this );
25973
25974 this.type = 'IcosahedronGeometry';
25975
25976 this.parameters = {
25977 radius: radius,
25978 detail: detail
25979 };
25980
25981 this.fromBufferGeometry( new IcosahedronBufferGeometry( radius, detail ) );
25982 this.mergeVertices();
25983
25984}
25985
25986IcosahedronGeometry.prototype = Object.create( Geometry.prototype );
25987IcosahedronGeometry.prototype.constructor = IcosahedronGeometry;
25988
25989// IcosahedronBufferGeometry
25990
25991function IcosahedronBufferGeometry( radius, detail ) {
25992
25993 var t = ( 1 + Math.sqrt( 5 ) ) / 2;
25994
25995 var vertices = [
25996 - 1, t, 0, 1, t, 0, - 1, - t, 0, 1, - t, 0,
25997 0, - 1, t, 0, 1, t, 0, - 1, - t, 0, 1, - t,
25998 t, 0, - 1, t, 0, 1, - t, 0, - 1, - t, 0, 1
25999 ];
26000
26001 var indices = [
26002 0, 11, 5, 0, 5, 1, 0, 1, 7, 0, 7, 10, 0, 10, 11,
26003 1, 5, 9, 5, 11, 4, 11, 10, 2, 10, 7, 6, 7, 1, 8,
26004 3, 9, 4, 3, 4, 2, 3, 2, 6, 3, 6, 8, 3, 8, 9,
26005 4, 9, 5, 2, 4, 11, 6, 2, 10, 8, 6, 7, 9, 8, 1
26006 ];
26007
26008 PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail );
26009
26010 this.type = 'IcosahedronBufferGeometry';
26011
26012 this.parameters = {
26013 radius: radius,
26014 detail: detail
26015 };
26016
26017}
26018
26019IcosahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype );
26020IcosahedronBufferGeometry.prototype.constructor = IcosahedronBufferGeometry;
26021
26022/**
26023 * @author Abe Pazos / https://hamoid.com
26024 * @author Mugen87 / https://github.com/Mugen87
26025 */
26026
26027// DodecahedronGeometry
26028
26029function DodecahedronGeometry( radius, detail ) {
26030
26031 Geometry.call( this );
26032
26033 this.type = 'DodecahedronGeometry';
26034
26035 this.parameters = {
26036 radius: radius,
26037 detail: detail
26038 };
26039
26040 this.fromBufferGeometry( new DodecahedronBufferGeometry( radius, detail ) );
26041 this.mergeVertices();
26042
26043}
26044
26045DodecahedronGeometry.prototype = Object.create( Geometry.prototype );
26046DodecahedronGeometry.prototype.constructor = DodecahedronGeometry;
26047
26048// DodecahedronBufferGeometry
26049
26050function DodecahedronBufferGeometry( radius, detail ) {
26051
26052 var t = ( 1 + Math.sqrt( 5 ) ) / 2;
26053 var r = 1 / t;
26054
26055 var vertices = [
26056
26057 // (±1, ±1, ±1)
26058 - 1, - 1, - 1, - 1, - 1, 1,
26059 - 1, 1, - 1, - 1, 1, 1,
26060 1, - 1, - 1, 1, - 1, 1,
26061 1, 1, - 1, 1, 1, 1,
26062
26063 // (0, ±1/φ, ±φ)
26064 0, - r, - t, 0, - r, t,
26065 0, r, - t, 0, r, t,
26066
26067 // (±1/φ, ±φ, 0)
26068 - r, - t, 0, - r, t, 0,
26069 r, - t, 0, r, t, 0,
26070
26071 // (±φ, 0, ±1/φ)
26072 - t, 0, - r, t, 0, - r,
26073 - t, 0, r, t, 0, r
26074 ];
26075
26076 var indices = [
26077 3, 11, 7, 3, 7, 15, 3, 15, 13,
26078 7, 19, 17, 7, 17, 6, 7, 6, 15,
26079 17, 4, 8, 17, 8, 10, 17, 10, 6,
26080 8, 0, 16, 8, 16, 2, 8, 2, 10,
26081 0, 12, 1, 0, 1, 18, 0, 18, 16,
26082 6, 10, 2, 6, 2, 13, 6, 13, 15,
26083 2, 16, 18, 2, 18, 3, 2, 3, 13,
26084 18, 1, 9, 18, 9, 11, 18, 11, 3,
26085 4, 14, 12, 4, 12, 0, 4, 0, 8,
26086 11, 9, 5, 11, 5, 19, 11, 19, 7,
26087 19, 5, 14, 19, 14, 4, 19, 4, 17,
26088 1, 12, 14, 1, 14, 5, 1, 5, 9
26089 ];
26090
26091 PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail );
26092
26093 this.type = 'DodecahedronBufferGeometry';
26094
26095 this.parameters = {
26096 radius: radius,
26097 detail: detail
26098 };
26099
26100}
26101
26102DodecahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype );
26103DodecahedronBufferGeometry.prototype.constructor = DodecahedronBufferGeometry;
26104
26105/**
26106 * @author oosmoxiecode / https://github.com/oosmoxiecode
26107 * @author WestLangley / https://github.com/WestLangley
26108 * @author zz85 / https://github.com/zz85
26109 * @author miningold / https://github.com/miningold
26110 * @author jonobr1 / https://github.com/jonobr1
26111 * @author Mugen87 / https://github.com/Mugen87
26112 *
26113 */
26114
26115// TubeGeometry
26116
26117function TubeGeometry( path, tubularSegments, radius, radialSegments, closed, taper ) {
26118
26119 Geometry.call( this );
26120
26121 this.type = 'TubeGeometry';
26122
26123 this.parameters = {
26124 path: path,
26125 tubularSegments: tubularSegments,
26126 radius: radius,
26127 radialSegments: radialSegments,
26128 closed: closed
26129 };
26130
26131 if ( taper !== undefined ) console.warn( 'THREE.TubeGeometry: taper has been removed.' );
26132
26133 var bufferGeometry = new TubeBufferGeometry( path, tubularSegments, radius, radialSegments, closed );
26134
26135 // expose internals
26136
26137 this.tangents = bufferGeometry.tangents;
26138 this.normals = bufferGeometry.normals;
26139 this.binormals = bufferGeometry.binormals;
26140
26141 // create geometry
26142
26143 this.fromBufferGeometry( bufferGeometry );
26144 this.mergeVertices();
26145
26146}
26147
26148TubeGeometry.prototype = Object.create( Geometry.prototype );
26149TubeGeometry.prototype.constructor = TubeGeometry;
26150
26151// TubeBufferGeometry
26152
26153function TubeBufferGeometry( path, tubularSegments, radius, radialSegments, closed ) {
26154
26155 BufferGeometry.call( this );
26156
26157 this.type = 'TubeBufferGeometry';
26158
26159 this.parameters = {
26160 path: path,
26161 tubularSegments: tubularSegments,
26162 radius: radius,
26163 radialSegments: radialSegments,
26164 closed: closed
26165 };
26166
26167 tubularSegments = tubularSegments || 64;
26168 radius = radius || 1;
26169 radialSegments = radialSegments || 8;
26170 closed = closed || false;
26171
26172 var frames = path.computeFrenetFrames( tubularSegments, closed );
26173
26174 // expose internals
26175
26176 this.tangents = frames.tangents;
26177 this.normals = frames.normals;
26178 this.binormals = frames.binormals;
26179
26180 // helper variables
26181
26182 var vertex = new Vector3();
26183 var normal = new Vector3();
26184 var uv = new Vector2();
26185 var P = new Vector3();
26186
26187 var i, j;
26188
26189 // buffer
26190
26191 var vertices = [];
26192 var normals = [];
26193 var uvs = [];
26194 var indices = [];
26195
26196 // create buffer data
26197
26198 generateBufferData();
26199
26200 // build geometry
26201
26202 this.setIndex( indices );
26203 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
26204 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
26205 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
26206
26207 // functions
26208
26209 function generateBufferData() {
26210
26211 for ( i = 0; i < tubularSegments; i ++ ) {
26212
26213 generateSegment( i );
26214
26215 }
26216
26217 // if the geometry is not closed, generate the last row of vertices and normals
26218 // at the regular position on the given path
26219 //
26220 // if the geometry is closed, duplicate the first row of vertices and normals (uvs will differ)
26221
26222 generateSegment( ( closed === false ) ? tubularSegments : 0 );
26223
26224 // uvs are generated in a separate function.
26225 // this makes it easy compute correct values for closed geometries
26226
26227 generateUVs();
26228
26229 // finally create faces
26230
26231 generateIndices();
26232
26233 }
26234
26235 function generateSegment( i ) {
26236
26237 // we use getPointAt to sample evenly distributed points from the given path
26238
26239 P = path.getPointAt( i / tubularSegments, P );
26240
26241 // retrieve corresponding normal and binormal
26242
26243 var N = frames.normals[ i ];
26244 var B = frames.binormals[ i ];
26245
26246 // generate normals and vertices for the current segment
26247
26248 for ( j = 0; j <= radialSegments; j ++ ) {
26249
26250 var v = j / radialSegments * Math.PI * 2;
26251
26252 var sin = Math.sin( v );
26253 var cos = - Math.cos( v );
26254
26255 // normal
26256
26257 normal.x = ( cos * N.x + sin * B.x );
26258 normal.y = ( cos * N.y + sin * B.y );
26259 normal.z = ( cos * N.z + sin * B.z );
26260 normal.normalize();
26261
26262 normals.push( normal.x, normal.y, normal.z );
26263
26264 // vertex
26265
26266 vertex.x = P.x + radius * normal.x;
26267 vertex.y = P.y + radius * normal.y;
26268 vertex.z = P.z + radius * normal.z;
26269
26270 vertices.push( vertex.x, vertex.y, vertex.z );
26271
26272 }
26273
26274 }
26275
26276 function generateIndices() {
26277
26278 for ( j = 1; j <= tubularSegments; j ++ ) {
26279
26280 for ( i = 1; i <= radialSegments; i ++ ) {
26281
26282 var a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 );
26283 var b = ( radialSegments + 1 ) * j + ( i - 1 );
26284 var c = ( radialSegments + 1 ) * j + i;
26285 var d = ( radialSegments + 1 ) * ( j - 1 ) + i;
26286
26287 // faces
26288
26289 indices.push( a, b, d );
26290 indices.push( b, c, d );
26291
26292 }
26293
26294 }
26295
26296 }
26297
26298 function generateUVs() {
26299
26300 for ( i = 0; i <= tubularSegments; i ++ ) {
26301
26302 for ( j = 0; j <= radialSegments; j ++ ) {
26303
26304 uv.x = i / tubularSegments;
26305 uv.y = j / radialSegments;
26306
26307 uvs.push( uv.x, uv.y );
26308
26309 }
26310
26311 }
26312
26313 }
26314
26315}
26316
26317TubeBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
26318TubeBufferGeometry.prototype.constructor = TubeBufferGeometry;
26319
26320/**
26321 * @author oosmoxiecode
26322 * @author Mugen87 / https://github.com/Mugen87
26323 *
26324 * based on http://www.blackpawn.com/texts/pqtorus/
26325 */
26326
26327// TorusKnotGeometry
26328
26329function TorusKnotGeometry( radius, tube, tubularSegments, radialSegments, p, q, heightScale ) {
26330
26331 Geometry.call( this );
26332
26333 this.type = 'TorusKnotGeometry';
26334
26335 this.parameters = {
26336 radius: radius,
26337 tube: tube,
26338 tubularSegments: tubularSegments,
26339 radialSegments: radialSegments,
26340 p: p,
26341 q: q
26342 };
26343
26344 if ( heightScale !== undefined ) console.warn( 'THREE.TorusKnotGeometry: heightScale has been deprecated. Use .scale( x, y, z ) instead.' );
26345
26346 this.fromBufferGeometry( new TorusKnotBufferGeometry( radius, tube, tubularSegments, radialSegments, p, q ) );
26347 this.mergeVertices();
26348
26349}
26350
26351TorusKnotGeometry.prototype = Object.create( Geometry.prototype );
26352TorusKnotGeometry.prototype.constructor = TorusKnotGeometry;
26353
26354// TorusKnotBufferGeometry
26355
26356function TorusKnotBufferGeometry( radius, tube, tubularSegments, radialSegments, p, q ) {
26357
26358 BufferGeometry.call( this );
26359
26360 this.type = 'TorusKnotBufferGeometry';
26361
26362 this.parameters = {
26363 radius: radius,
26364 tube: tube,
26365 tubularSegments: tubularSegments,
26366 radialSegments: radialSegments,
26367 p: p,
26368 q: q
26369 };
26370
26371 radius = radius || 1;
26372 tube = tube || 0.4;
26373 tubularSegments = Math.floor( tubularSegments ) || 64;
26374 radialSegments = Math.floor( radialSegments ) || 8;
26375 p = p || 2;
26376 q = q || 3;
26377
26378 // buffers
26379
26380 var indices = [];
26381 var vertices = [];
26382 var normals = [];
26383 var uvs = [];
26384
26385 // helper variables
26386
26387 var i, j;
26388
26389 var vertex = new Vector3();
26390 var normal = new Vector3();
26391
26392 var P1 = new Vector3();
26393 var P2 = new Vector3();
26394
26395 var B = new Vector3();
26396 var T = new Vector3();
26397 var N = new Vector3();
26398
26399 // generate vertices, normals and uvs
26400
26401 for ( i = 0; i <= tubularSegments; ++ i ) {
26402
26403 // the radian "u" is used to calculate the position on the torus curve of the current tubular segement
26404
26405 var u = i / tubularSegments * p * Math.PI * 2;
26406
26407 // now we calculate two points. P1 is our current position on the curve, P2 is a little farther ahead.
26408 // these points are used to create a special "coordinate space", which is necessary to calculate the correct vertex positions
26409
26410 calculatePositionOnCurve( u, p, q, radius, P1 );
26411 calculatePositionOnCurve( u + 0.01, p, q, radius, P2 );
26412
26413 // calculate orthonormal basis
26414
26415 T.subVectors( P2, P1 );
26416 N.addVectors( P2, P1 );
26417 B.crossVectors( T, N );
26418 N.crossVectors( B, T );
26419
26420 // normalize B, N. T can be ignored, we don't use it
26421
26422 B.normalize();
26423 N.normalize();
26424
26425 for ( j = 0; j <= radialSegments; ++ j ) {
26426
26427 // now calculate the vertices. they are nothing more than an extrusion of the torus curve.
26428 // because we extrude a shape in the xy-plane, there is no need to calculate a z-value.
26429
26430 var v = j / radialSegments * Math.PI * 2;
26431 var cx = - tube * Math.cos( v );
26432 var cy = tube * Math.sin( v );
26433
26434 // now calculate the final vertex position.
26435 // first we orient the extrusion with our basis vectos, then we add it to the current position on the curve
26436
26437 vertex.x = P1.x + ( cx * N.x + cy * B.x );
26438 vertex.y = P1.y + ( cx * N.y + cy * B.y );
26439 vertex.z = P1.z + ( cx * N.z + cy * B.z );
26440
26441 vertices.push( vertex.x, vertex.y, vertex.z );
26442
26443 // normal (P1 is always the center/origin of the extrusion, thus we can use it to calculate the normal)
26444
26445 normal.subVectors( vertex, P1 ).normalize();
26446
26447 normals.push( normal.x, normal.y, normal.z );
26448
26449 // uv
26450
26451 uvs.push( i / tubularSegments );
26452 uvs.push( j / radialSegments );
26453
26454 }
26455
26456 }
26457
26458 // generate indices
26459
26460 for ( j = 1; j <= tubularSegments; j ++ ) {
26461
26462 for ( i = 1; i <= radialSegments; i ++ ) {
26463
26464 // indices
26465
26466 var a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 );
26467 var b = ( radialSegments + 1 ) * j + ( i - 1 );
26468 var c = ( radialSegments + 1 ) * j + i;
26469 var d = ( radialSegments + 1 ) * ( j - 1 ) + i;
26470
26471 // faces
26472
26473 indices.push( a, b, d );
26474 indices.push( b, c, d );
26475
26476 }
26477
26478 }
26479
26480 // build geometry
26481
26482 this.setIndex( indices );
26483 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
26484 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
26485 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
26486
26487 // this function calculates the current position on the torus curve
26488
26489 function calculatePositionOnCurve( u, p, q, radius, position ) {
26490
26491 var cu = Math.cos( u );
26492 var su = Math.sin( u );
26493 var quOverP = q / p * u;
26494 var cs = Math.cos( quOverP );
26495
26496 position.x = radius * ( 2 + cs ) * 0.5 * cu;
26497 position.y = radius * ( 2 + cs ) * su * 0.5;
26498 position.z = radius * Math.sin( quOverP ) * 0.5;
26499
26500 }
26501
26502}
26503
26504TorusKnotBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
26505TorusKnotBufferGeometry.prototype.constructor = TorusKnotBufferGeometry;
26506
26507/**
26508 * @author oosmoxiecode
26509 * @author mrdoob / http://mrdoob.com/
26510 * @author Mugen87 / https://github.com/Mugen87
26511 */
26512
26513// TorusGeometry
26514
26515function TorusGeometry( radius, tube, radialSegments, tubularSegments, arc ) {
26516
26517 Geometry.call( this );
26518
26519 this.type = 'TorusGeometry';
26520
26521 this.parameters = {
26522 radius: radius,
26523 tube: tube,
26524 radialSegments: radialSegments,
26525 tubularSegments: tubularSegments,
26526 arc: arc
26527 };
26528
26529 this.fromBufferGeometry( new TorusBufferGeometry( radius, tube, radialSegments, tubularSegments, arc ) );
26530 this.mergeVertices();
26531
26532}
26533
26534TorusGeometry.prototype = Object.create( Geometry.prototype );
26535TorusGeometry.prototype.constructor = TorusGeometry;
26536
26537// TorusBufferGeometry
26538
26539function TorusBufferGeometry( radius, tube, radialSegments, tubularSegments, arc ) {
26540
26541 BufferGeometry.call( this );
26542
26543 this.type = 'TorusBufferGeometry';
26544
26545 this.parameters = {
26546 radius: radius,
26547 tube: tube,
26548 radialSegments: radialSegments,
26549 tubularSegments: tubularSegments,
26550 arc: arc
26551 };
26552
26553 radius = radius || 1;
26554 tube = tube || 0.4;
26555 radialSegments = Math.floor( radialSegments ) || 8;
26556 tubularSegments = Math.floor( tubularSegments ) || 6;
26557 arc = arc || Math.PI * 2;
26558
26559 // buffers
26560
26561 var indices = [];
26562 var vertices = [];
26563 var normals = [];
26564 var uvs = [];
26565
26566 // helper variables
26567
26568 var center = new Vector3();
26569 var vertex = new Vector3();
26570 var normal = new Vector3();
26571
26572 var j, i;
26573
26574 // generate vertices, normals and uvs
26575
26576 for ( j = 0; j <= radialSegments; j ++ ) {
26577
26578 for ( i = 0; i <= tubularSegments; i ++ ) {
26579
26580 var u = i / tubularSegments * arc;
26581 var v = j / radialSegments * Math.PI * 2;
26582
26583 // vertex
26584
26585 vertex.x = ( radius + tube * Math.cos( v ) ) * Math.cos( u );
26586 vertex.y = ( radius + tube * Math.cos( v ) ) * Math.sin( u );
26587 vertex.z = tube * Math.sin( v );
26588
26589 vertices.push( vertex.x, vertex.y, vertex.z );
26590
26591 // normal
26592
26593 center.x = radius * Math.cos( u );
26594 center.y = radius * Math.sin( u );
26595 normal.subVectors( vertex, center ).normalize();
26596
26597 normals.push( normal.x, normal.y, normal.z );
26598
26599 // uv
26600
26601 uvs.push( i / tubularSegments );
26602 uvs.push( j / radialSegments );
26603
26604 }
26605
26606 }
26607
26608 // generate indices
26609
26610 for ( j = 1; j <= radialSegments; j ++ ) {
26611
26612 for ( i = 1; i <= tubularSegments; i ++ ) {
26613
26614 // indices
26615
26616 var a = ( tubularSegments + 1 ) * j + i - 1;
26617 var b = ( tubularSegments + 1 ) * ( j - 1 ) + i - 1;
26618 var c = ( tubularSegments + 1 ) * ( j - 1 ) + i;
26619 var d = ( tubularSegments + 1 ) * j + i;
26620
26621 // faces
26622
26623 indices.push( a, b, d );
26624 indices.push( b, c, d );
26625
26626 }
26627
26628 }
26629
26630 // build geometry
26631
26632 this.setIndex( indices );
26633 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
26634 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
26635 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
26636
26637}
26638
26639TorusBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
26640TorusBufferGeometry.prototype.constructor = TorusBufferGeometry;
26641
26642/**
26643 * @author Mugen87 / https://github.com/Mugen87
26644 * Port from https://github.com/mapbox/earcut (v2.1.2)
26645 */
26646
26647var Earcut = {
26648
26649 triangulate: function ( data, holeIndices, dim ) {
26650
26651 dim = dim || 2;
26652
26653 var hasHoles = holeIndices && holeIndices.length,
26654 outerLen = hasHoles ? holeIndices[ 0 ] * dim : data.length,
26655 outerNode = linkedList( data, 0, outerLen, dim, true ),
26656 triangles = [];
26657
26658 if ( ! outerNode ) return triangles;
26659
26660 var minX, minY, maxX, maxY, x, y, invSize;
26661
26662 if ( hasHoles ) outerNode = eliminateHoles( data, holeIndices, outerNode, dim );
26663
26664 // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox
26665
26666 if ( data.length > 80 * dim ) {
26667
26668 minX = maxX = data[ 0 ];
26669 minY = maxY = data[ 1 ];
26670
26671 for ( var i = dim; i < outerLen; i += dim ) {
26672
26673 x = data[ i ];
26674 y = data[ i + 1 ];
26675 if ( x < minX ) minX = x;
26676 if ( y < minY ) minY = y;
26677 if ( x > maxX ) maxX = x;
26678 if ( y > maxY ) maxY = y;
26679
26680 }
26681
26682 // minX, minY and invSize are later used to transform coords into integers for z-order calculation
26683
26684 invSize = Math.max( maxX - minX, maxY - minY );
26685 invSize = invSize !== 0 ? 1 / invSize : 0;
26686
26687 }
26688
26689 earcutLinked( outerNode, triangles, dim, minX, minY, invSize );
26690
26691 return triangles;
26692
26693 }
26694
26695};
26696
26697// create a circular doubly linked list from polygon points in the specified winding order
26698
26699function linkedList( data, start, end, dim, clockwise ) {
26700
26701 var i, last;
26702
26703 if ( clockwise === ( signedArea( data, start, end, dim ) > 0 ) ) {
26704
26705 for ( i = start; i < end; i += dim ) last = insertNode( i, data[ i ], data[ i + 1 ], last );
26706
26707 } else {
26708
26709 for ( i = end - dim; i >= start; i -= dim ) last = insertNode( i, data[ i ], data[ i + 1 ], last );
26710
26711 }
26712
26713 if ( last && equals( last, last.next ) ) {
26714
26715 removeNode( last );
26716 last = last.next;
26717
26718 }
26719
26720 return last;
26721
26722}
26723
26724// eliminate colinear or duplicate points
26725
26726function filterPoints( start, end ) {
26727
26728 if ( ! start ) return start;
26729 if ( ! end ) end = start;
26730
26731 var p = start, again;
26732
26733 do {
26734
26735 again = false;
26736
26737 if ( ! p.steiner && ( equals( p, p.next ) || area( p.prev, p, p.next ) === 0 ) ) {
26738
26739 removeNode( p );
26740 p = end = p.prev;
26741 if ( p === p.next ) break;
26742 again = true;
26743
26744 } else {
26745
26746 p = p.next;
26747
26748 }
26749
26750 } while ( again || p !== end );
26751
26752 return end;
26753
26754}
26755
26756// main ear slicing loop which triangulates a polygon (given as a linked list)
26757
26758function earcutLinked( ear, triangles, dim, minX, minY, invSize, pass ) {
26759
26760 if ( ! ear ) return;
26761
26762 // interlink polygon nodes in z-order
26763
26764 if ( ! pass && invSize ) indexCurve( ear, minX, minY, invSize );
26765
26766 var stop = ear, prev, next;
26767
26768 // iterate through ears, slicing them one by one
26769
26770 while ( ear.prev !== ear.next ) {
26771
26772 prev = ear.prev;
26773 next = ear.next;
26774
26775 if ( invSize ? isEarHashed( ear, minX, minY, invSize ) : isEar( ear ) ) {
26776
26777 // cut off the triangle
26778 triangles.push( prev.i / dim );
26779 triangles.push( ear.i / dim );
26780 triangles.push( next.i / dim );
26781
26782 removeNode( ear );
26783
26784 // skipping the next vertice leads to less sliver triangles
26785 ear = next.next;
26786 stop = next.next;
26787
26788 continue;
26789
26790 }
26791
26792 ear = next;
26793
26794 // if we looped through the whole remaining polygon and can't find any more ears
26795
26796 if ( ear === stop ) {
26797
26798 // try filtering points and slicing again
26799
26800 if ( ! pass ) {
26801
26802 earcutLinked( filterPoints( ear ), triangles, dim, minX, minY, invSize, 1 );
26803
26804 // if this didn't work, try curing all small self-intersections locally
26805
26806 } else if ( pass === 1 ) {
26807
26808 ear = cureLocalIntersections( ear, triangles, dim );
26809 earcutLinked( ear, triangles, dim, minX, minY, invSize, 2 );
26810
26811 // as a last resort, try splitting the remaining polygon into two
26812
26813 } else if ( pass === 2 ) {
26814
26815 splitEarcut( ear, triangles, dim, minX, minY, invSize );
26816
26817 }
26818
26819 break;
26820
26821 }
26822
26823 }
26824
26825}
26826
26827// check whether a polygon node forms a valid ear with adjacent nodes
26828
26829function isEar( ear ) {
26830
26831 var a = ear.prev,
26832 b = ear,
26833 c = ear.next;
26834
26835 if ( area( a, b, c ) >= 0 ) return false; // reflex, can't be an ear
26836
26837 // now make sure we don't have other points inside the potential ear
26838 var p = ear.next.next;
26839
26840 while ( p !== ear.prev ) {
26841
26842 if ( pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) && area( p.prev, p, p.next ) >= 0 ) {
26843
26844 return false;
26845
26846 }
26847
26848 p = p.next;
26849
26850 }
26851
26852 return true;
26853
26854}
26855
26856function isEarHashed( ear, minX, minY, invSize ) {
26857
26858 var a = ear.prev,
26859 b = ear,
26860 c = ear.next;
26861
26862 if ( area( a, b, c ) >= 0 ) return false; // reflex, can't be an ear
26863
26864 // triangle bbox; min & max are calculated like this for speed
26865
26866 var minTX = a.x < b.x ? ( a.x < c.x ? a.x : c.x ) : ( b.x < c.x ? b.x : c.x ),
26867 minTY = a.y < b.y ? ( a.y < c.y ? a.y : c.y ) : ( b.y < c.y ? b.y : c.y ),
26868 maxTX = a.x > b.x ? ( a.x > c.x ? a.x : c.x ) : ( b.x > c.x ? b.x : c.x ),
26869 maxTY = a.y > b.y ? ( a.y > c.y ? a.y : c.y ) : ( b.y > c.y ? b.y : c.y );
26870
26871 // z-order range for the current triangle bbox;
26872
26873 var minZ = zOrder( minTX, minTY, minX, minY, invSize ),
26874 maxZ = zOrder( maxTX, maxTY, minX, minY, invSize );
26875
26876 // first look for points inside the triangle in increasing z-order
26877
26878 var p = ear.nextZ;
26879
26880 while ( p && p.z <= maxZ ) {
26881
26882 if ( p !== ear.prev && p !== ear.next &&
26883 pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) &&
26884 area( p.prev, p, p.next ) >= 0 ) return false;
26885 p = p.nextZ;
26886
26887 }
26888
26889 // then look for points in decreasing z-order
26890
26891 p = ear.prevZ;
26892
26893 while ( p && p.z >= minZ ) {
26894
26895 if ( p !== ear.prev && p !== ear.next &&
26896 pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) &&
26897 area( p.prev, p, p.next ) >= 0 ) return false;
26898
26899 p = p.prevZ;
26900
26901 }
26902
26903 return true;
26904
26905}
26906
26907// go through all polygon nodes and cure small local self-intersections
26908
26909function cureLocalIntersections( start, triangles, dim ) {
26910
26911 var p = start;
26912
26913 do {
26914
26915 var a = p.prev, b = p.next.next;
26916
26917 if ( ! equals( a, b ) && intersects( a, p, p.next, b ) && locallyInside( a, b ) && locallyInside( b, a ) ) {
26918
26919 triangles.push( a.i / dim );
26920 triangles.push( p.i / dim );
26921 triangles.push( b.i / dim );
26922
26923 // remove two nodes involved
26924
26925 removeNode( p );
26926 removeNode( p.next );
26927
26928 p = start = b;
26929
26930 }
26931
26932 p = p.next;
26933
26934 } while ( p !== start );
26935
26936 return p;
26937
26938}
26939
26940// try splitting polygon into two and triangulate them independently
26941
26942function splitEarcut( start, triangles, dim, minX, minY, invSize ) {
26943
26944 // look for a valid diagonal that divides the polygon into two
26945
26946 var a = start;
26947
26948 do {
26949
26950 var b = a.next.next;
26951
26952 while ( b !== a.prev ) {
26953
26954 if ( a.i !== b.i && isValidDiagonal( a, b ) ) {
26955
26956 // split the polygon in two by the diagonal
26957
26958 var c = splitPolygon( a, b );
26959
26960 // filter colinear points around the cuts
26961
26962 a = filterPoints( a, a.next );
26963 c = filterPoints( c, c.next );
26964
26965 // run earcut on each half
26966
26967 earcutLinked( a, triangles, dim, minX, minY, invSize );
26968 earcutLinked( c, triangles, dim, minX, minY, invSize );
26969 return;
26970
26971 }
26972
26973 b = b.next;
26974
26975 }
26976
26977 a = a.next;
26978
26979 } while ( a !== start );
26980
26981}
26982
26983// link every hole into the outer loop, producing a single-ring polygon without holes
26984
26985function eliminateHoles( data, holeIndices, outerNode, dim ) {
26986
26987 var queue = [], i, len, start, end, list;
26988
26989 for ( i = 0, len = holeIndices.length; i < len; i ++ ) {
26990
26991 start = holeIndices[ i ] * dim;
26992 end = i < len - 1 ? holeIndices[ i + 1 ] * dim : data.length;
26993 list = linkedList( data, start, end, dim, false );
26994 if ( list === list.next ) list.steiner = true;
26995 queue.push( getLeftmost( list ) );
26996
26997 }
26998
26999 queue.sort( compareX );
27000
27001 // process holes from left to right
27002
27003 for ( i = 0; i < queue.length; i ++ ) {
27004
27005 eliminateHole( queue[ i ], outerNode );
27006 outerNode = filterPoints( outerNode, outerNode.next );
27007
27008 }
27009
27010 return outerNode;
27011
27012}
27013
27014function compareX( a, b ) {
27015
27016 return a.x - b.x;
27017
27018}
27019
27020// find a bridge between vertices that connects hole with an outer ring and and link it
27021
27022function eliminateHole( hole, outerNode ) {
27023
27024 outerNode = findHoleBridge( hole, outerNode );
27025
27026 if ( outerNode ) {
27027
27028 var b = splitPolygon( outerNode, hole );
27029
27030 filterPoints( b, b.next );
27031
27032 }
27033
27034}
27035
27036// David Eberly's algorithm for finding a bridge between hole and outer polygon
27037
27038function findHoleBridge( hole, outerNode ) {
27039
27040 var p = outerNode,
27041 hx = hole.x,
27042 hy = hole.y,
27043 qx = - Infinity,
27044 m;
27045
27046 // find a segment intersected by a ray from the hole's leftmost point to the left;
27047 // segment's endpoint with lesser x will be potential connection point
27048
27049 do {
27050
27051 if ( hy <= p.y && hy >= p.next.y && p.next.y !== p.y ) {
27052
27053 var x = p.x + ( hy - p.y ) * ( p.next.x - p.x ) / ( p.next.y - p.y );
27054
27055 if ( x <= hx && x > qx ) {
27056
27057 qx = x;
27058
27059 if ( x === hx ) {
27060
27061 if ( hy === p.y ) return p;
27062 if ( hy === p.next.y ) return p.next;
27063
27064 }
27065
27066 m = p.x < p.next.x ? p : p.next;
27067
27068 }
27069
27070 }
27071
27072 p = p.next;
27073
27074 } while ( p !== outerNode );
27075
27076 if ( ! m ) return null;
27077
27078 if ( hx === qx ) return m.prev; // hole touches outer segment; pick lower endpoint
27079
27080 // look for points inside the triangle of hole point, segment intersection and endpoint;
27081 // if there are no points found, we have a valid connection;
27082 // otherwise choose the point of the minimum angle with the ray as connection point
27083
27084 var stop = m,
27085 mx = m.x,
27086 my = m.y,
27087 tanMin = Infinity,
27088 tan;
27089
27090 p = m.next;
27091
27092 while ( p !== stop ) {
27093
27094 if ( hx >= p.x && p.x >= mx && hx !== p.x &&
27095 pointInTriangle( hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y ) ) {
27096
27097 tan = Math.abs( hy - p.y ) / ( hx - p.x ); // tangential
27098
27099 if ( ( tan < tanMin || ( tan === tanMin && p.x > m.x ) ) && locallyInside( p, hole ) ) {
27100
27101 m = p;
27102 tanMin = tan;
27103
27104 }
27105
27106 }
27107
27108 p = p.next;
27109
27110 }
27111
27112 return m;
27113
27114}
27115
27116// interlink polygon nodes in z-order
27117
27118function indexCurve( start, minX, minY, invSize ) {
27119
27120 var p = start;
27121
27122 do {
27123
27124 if ( p.z === null ) p.z = zOrder( p.x, p.y, minX, minY, invSize );
27125 p.prevZ = p.prev;
27126 p.nextZ = p.next;
27127 p = p.next;
27128
27129 } while ( p !== start );
27130
27131 p.prevZ.nextZ = null;
27132 p.prevZ = null;
27133
27134 sortLinked( p );
27135
27136}
27137
27138// Simon Tatham's linked list merge sort algorithm
27139// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
27140
27141function sortLinked( list ) {
27142
27143 var i, p, q, e, tail, numMerges, pSize, qSize, inSize = 1;
27144
27145 do {
27146
27147 p = list;
27148 list = null;
27149 tail = null;
27150 numMerges = 0;
27151
27152 while ( p ) {
27153
27154 numMerges ++;
27155 q = p;
27156 pSize = 0;
27157
27158 for ( i = 0; i < inSize; i ++ ) {
27159
27160 pSize ++;
27161 q = q.nextZ;
27162 if ( ! q ) break;
27163
27164 }
27165
27166 qSize = inSize;
27167
27168 while ( pSize > 0 || ( qSize > 0 && q ) ) {
27169
27170 if ( pSize !== 0 && ( qSize === 0 || ! q || p.z <= q.z ) ) {
27171
27172 e = p;
27173 p = p.nextZ;
27174 pSize --;
27175
27176 } else {
27177
27178 e = q;
27179 q = q.nextZ;
27180 qSize --;
27181
27182 }
27183
27184 if ( tail ) tail.nextZ = e;
27185 else list = e;
27186
27187 e.prevZ = tail;
27188 tail = e;
27189
27190 }
27191
27192 p = q;
27193
27194 }
27195
27196 tail.nextZ = null;
27197 inSize *= 2;
27198
27199 } while ( numMerges > 1 );
27200
27201 return list;
27202
27203}
27204
27205// z-order of a point given coords and inverse of the longer side of data bbox
27206
27207function zOrder( x, y, minX, minY, invSize ) {
27208
27209 // coords are transformed into non-negative 15-bit integer range
27210
27211 x = 32767 * ( x - minX ) * invSize;
27212 y = 32767 * ( y - minY ) * invSize;
27213
27214 x = ( x | ( x << 8 ) ) & 0x00FF00FF;
27215 x = ( x | ( x << 4 ) ) & 0x0F0F0F0F;
27216 x = ( x | ( x << 2 ) ) & 0x33333333;
27217 x = ( x | ( x << 1 ) ) & 0x55555555;
27218
27219 y = ( y | ( y << 8 ) ) & 0x00FF00FF;
27220 y = ( y | ( y << 4 ) ) & 0x0F0F0F0F;
27221 y = ( y | ( y << 2 ) ) & 0x33333333;
27222 y = ( y | ( y << 1 ) ) & 0x55555555;
27223
27224 return x | ( y << 1 );
27225
27226}
27227
27228// find the leftmost node of a polygon ring
27229
27230function getLeftmost( start ) {
27231
27232 var p = start, leftmost = start;
27233
27234 do {
27235
27236 if ( p.x < leftmost.x ) leftmost = p;
27237 p = p.next;
27238
27239 } while ( p !== start );
27240
27241 return leftmost;
27242
27243}
27244
27245// check if a point lies within a convex triangle
27246
27247function pointInTriangle( ax, ay, bx, by, cx, cy, px, py ) {
27248
27249 return ( cx - px ) * ( ay - py ) - ( ax - px ) * ( cy - py ) >= 0 &&
27250 ( ax - px ) * ( by - py ) - ( bx - px ) * ( ay - py ) >= 0 &&
27251 ( bx - px ) * ( cy - py ) - ( cx - px ) * ( by - py ) >= 0;
27252
27253}
27254
27255// check if a diagonal between two polygon nodes is valid (lies in polygon interior)
27256
27257function isValidDiagonal( a, b ) {
27258
27259 return a.next.i !== b.i && a.prev.i !== b.i && ! intersectsPolygon( a, b ) &&
27260 locallyInside( a, b ) && locallyInside( b, a ) && middleInside( a, b );
27261
27262}
27263
27264// signed area of a triangle
27265
27266function area( p, q, r ) {
27267
27268 return ( q.y - p.y ) * ( r.x - q.x ) - ( q.x - p.x ) * ( r.y - q.y );
27269
27270}
27271
27272// check if two points are equal
27273
27274function equals( p1, p2 ) {
27275
27276 return p1.x === p2.x && p1.y === p2.y;
27277
27278}
27279
27280// check if two segments intersect
27281
27282function intersects( p1, q1, p2, q2 ) {
27283
27284 if ( ( equals( p1, q1 ) && equals( p2, q2 ) ) ||
27285 ( equals( p1, q2 ) && equals( p2, q1 ) ) ) return true;
27286
27287 return area( p1, q1, p2 ) > 0 !== area( p1, q1, q2 ) > 0 &&
27288 area( p2, q2, p1 ) > 0 !== area( p2, q2, q1 ) > 0;
27289
27290}
27291
27292// check if a polygon diagonal intersects any polygon segments
27293
27294function intersectsPolygon( a, b ) {
27295
27296 var p = a;
27297
27298 do {
27299
27300 if ( p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i &&
27301 intersects( p, p.next, a, b ) ) {
27302
27303 return true;
27304
27305 }
27306
27307 p = p.next;
27308
27309 } while ( p !== a );
27310
27311 return false;
27312
27313}
27314
27315// check if a polygon diagonal is locally inside the polygon
27316
27317function locallyInside( a, b ) {
27318
27319 return area( a.prev, a, a.next ) < 0 ?
27320 area( a, b, a.next ) >= 0 && area( a, a.prev, b ) >= 0 :
27321 area( a, b, a.prev ) < 0 || area( a, a.next, b ) < 0;
27322
27323}
27324
27325// check if the middle point of a polygon diagonal is inside the polygon
27326
27327function middleInside( a, b ) {
27328
27329 var p = a,
27330 inside = false,
27331 px = ( a.x + b.x ) / 2,
27332 py = ( a.y + b.y ) / 2;
27333
27334 do {
27335
27336 if ( ( ( p.y > py ) !== ( p.next.y > py ) ) && p.next.y !== p.y &&
27337 ( px < ( p.next.x - p.x ) * ( py - p.y ) / ( p.next.y - p.y ) + p.x ) ) {
27338
27339 inside = ! inside;
27340
27341 }
27342
27343 p = p.next;
27344
27345 } while ( p !== a );
27346
27347 return inside;
27348
27349}
27350
27351// link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two;
27352// if one belongs to the outer ring and another to a hole, it merges it into a single ring
27353
27354function splitPolygon( a, b ) {
27355
27356 var a2 = new Node( a.i, a.x, a.y ),
27357 b2 = new Node( b.i, b.x, b.y ),
27358 an = a.next,
27359 bp = b.prev;
27360
27361 a.next = b;
27362 b.prev = a;
27363
27364 a2.next = an;
27365 an.prev = a2;
27366
27367 b2.next = a2;
27368 a2.prev = b2;
27369
27370 bp.next = b2;
27371 b2.prev = bp;
27372
27373 return b2;
27374
27375}
27376
27377// create a node and optionally link it with previous one (in a circular doubly linked list)
27378
27379function insertNode( i, x, y, last ) {
27380
27381 var p = new Node( i, x, y );
27382
27383 if ( ! last ) {
27384
27385 p.prev = p;
27386 p.next = p;
27387
27388 } else {
27389
27390 p.next = last.next;
27391 p.prev = last;
27392 last.next.prev = p;
27393 last.next = p;
27394
27395 }
27396
27397 return p;
27398
27399}
27400
27401function removeNode( p ) {
27402
27403 p.next.prev = p.prev;
27404 p.prev.next = p.next;
27405
27406 if ( p.prevZ ) p.prevZ.nextZ = p.nextZ;
27407 if ( p.nextZ ) p.nextZ.prevZ = p.prevZ;
27408
27409}
27410
27411function Node( i, x, y ) {
27412
27413 // vertice index in coordinates array
27414 this.i = i;
27415
27416 // vertex coordinates
27417 this.x = x;
27418 this.y = y;
27419
27420 // previous and next vertice nodes in a polygon ring
27421 this.prev = null;
27422 this.next = null;
27423
27424 // z-order curve value
27425 this.z = null;
27426
27427 // previous and next nodes in z-order
27428 this.prevZ = null;
27429 this.nextZ = null;
27430
27431 // indicates whether this is a steiner point
27432 this.steiner = false;
27433
27434}
27435
27436function signedArea( data, start, end, dim ) {
27437
27438 var sum = 0;
27439
27440 for ( var i = start, j = end - dim; i < end; i += dim ) {
27441
27442 sum += ( data[ j ] - data[ i ] ) * ( data[ i + 1 ] + data[ j + 1 ] );
27443 j = i;
27444
27445 }
27446
27447 return sum;
27448
27449}
27450
27451/**
27452 * @author zz85 / http://www.lab4games.net/zz85/blog
27453 */
27454
27455var ShapeUtils = {
27456
27457 // calculate area of the contour polygon
27458
27459 area: function ( contour ) {
27460
27461 var n = contour.length;
27462 var a = 0.0;
27463
27464 for ( var p = n - 1, q = 0; q < n; p = q ++ ) {
27465
27466 a += contour[ p ].x * contour[ q ].y - contour[ q ].x * contour[ p ].y;
27467
27468 }
27469
27470 return a * 0.5;
27471
27472 },
27473
27474 isClockWise: function ( pts ) {
27475
27476 return ShapeUtils.area( pts ) < 0;
27477
27478 },
27479
27480 triangulateShape: function ( contour, holes ) {
27481
27482 var vertices = []; // flat array of vertices like [ x0,y0, x1,y1, x2,y2, ... ]
27483 var holeIndices = []; // array of hole indices
27484 var faces = []; // final array of vertex indices like [ [ a,b,d ], [ b,c,d ] ]
27485
27486 removeDupEndPts( contour );
27487 addContour( vertices, contour );
27488
27489 //
27490
27491 var holeIndex = contour.length;
27492
27493 holes.forEach( removeDupEndPts );
27494
27495 for ( var i = 0; i < holes.length; i ++ ) {
27496
27497 holeIndices.push( holeIndex );
27498 holeIndex += holes[ i ].length;
27499 addContour( vertices, holes[ i ] );
27500
27501 }
27502
27503 //
27504
27505 var triangles = Earcut.triangulate( vertices, holeIndices );
27506
27507 //
27508
27509 for ( var i = 0; i < triangles.length; i += 3 ) {
27510
27511 faces.push( triangles.slice( i, i + 3 ) );
27512
27513 }
27514
27515 return faces;
27516
27517 }
27518
27519};
27520
27521function removeDupEndPts( points ) {
27522
27523 var l = points.length;
27524
27525 if ( l > 2 && points[ l - 1 ].equals( points[ 0 ] ) ) {
27526
27527 points.pop();
27528
27529 }
27530
27531}
27532
27533function addContour( vertices, contour ) {
27534
27535 for ( var i = 0; i < contour.length; i ++ ) {
27536
27537 vertices.push( contour[ i ].x );
27538 vertices.push( contour[ i ].y );
27539
27540 }
27541
27542}
27543
27544/**
27545 * @author zz85 / http://www.lab4games.net/zz85/blog
27546 *
27547 * Creates extruded geometry from a path shape.
27548 *
27549 * parameters = {
27550 *
27551 * curveSegments: <int>, // number of points on the curves
27552 * steps: <int>, // number of points for z-side extrusions / used for subdividing segments of extrude spline too
27553 * amount: <int>, // Depth to extrude the shape
27554 *
27555 * bevelEnabled: <bool>, // turn on bevel
27556 * bevelThickness: <float>, // how deep into the original shape bevel goes
27557 * bevelSize: <float>, // how far from shape outline is bevel
27558 * bevelSegments: <int>, // number of bevel layers
27559 *
27560 * extrudePath: <THREE.Curve> // curve to extrude shape along
27561 *
27562 * UVGenerator: <Object> // object that provides UV generator functions
27563 *
27564 * }
27565 */
27566
27567// ExtrudeGeometry
27568
27569function ExtrudeGeometry( shapes, options ) {
27570
27571 Geometry.call( this );
27572
27573 this.type = 'ExtrudeGeometry';
27574
27575 this.parameters = {
27576 shapes: shapes,
27577 options: options
27578 };
27579
27580 this.fromBufferGeometry( new ExtrudeBufferGeometry( shapes, options ) );
27581 this.mergeVertices();
27582
27583}
27584
27585ExtrudeGeometry.prototype = Object.create( Geometry.prototype );
27586ExtrudeGeometry.prototype.constructor = ExtrudeGeometry;
27587
27588// ExtrudeBufferGeometry
27589
27590function ExtrudeBufferGeometry( shapes, options ) {
27591
27592 BufferGeometry.call( this );
27593
27594 this.type = 'ExtrudeBufferGeometry';
27595
27596 this.parameters = {
27597 shapes: shapes,
27598 options: options
27599 };
27600
27601 shapes = Array.isArray( shapes ) ? shapes : [ shapes ];
27602
27603 var scope = this;
27604
27605 var verticesArray = [];
27606 var uvArray = [];
27607
27608 for ( var i = 0, l = shapes.length; i < l; i ++ ) {
27609
27610 var shape = shapes[ i ];
27611 addShape( shape, options );
27612
27613 }
27614
27615 // build geometry
27616
27617 this.addAttribute( 'position', new Float32BufferAttribute( verticesArray, 3 ) );
27618 this.addAttribute( 'uv', new Float32BufferAttribute( uvArray, 2 ) );
27619
27620 this.computeVertexNormals();
27621
27622 // functions
27623
27624 function addShape( shape ) {
27625
27626 var placeholder = [];
27627
27628 // options
27629
27630 var curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12;
27631 var steps = options.steps !== undefined ? options.steps : 1;
27632 var amount = options.amount !== undefined ? options.amount : 100;
27633
27634 var bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true;
27635 var bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 6;
27636 var bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 2;
27637 var bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3;
27638
27639 var extrudePath = options.extrudePath;
27640
27641 var uvgen = options.UVGenerator !== undefined ? options.UVGenerator : WorldUVGenerator;
27642
27643 //
27644
27645 var extrudePts, extrudeByPath = false;
27646 var splineTube, binormal, normal, position2;
27647
27648 if ( extrudePath ) {
27649
27650 extrudePts = extrudePath.getSpacedPoints( steps );
27651
27652 extrudeByPath = true;
27653 bevelEnabled = false; // bevels not supported for path extrusion
27654
27655 // SETUP TNB variables
27656
27657 // TODO1 - have a .isClosed in spline?
27658
27659 splineTube = extrudePath.computeFrenetFrames( steps, false );
27660
27661 // console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length);
27662
27663 binormal = new Vector3();
27664 normal = new Vector3();
27665 position2 = new Vector3();
27666
27667 }
27668
27669 // Safeguards if bevels are not enabled
27670
27671 if ( ! bevelEnabled ) {
27672
27673 bevelSegments = 0;
27674 bevelThickness = 0;
27675 bevelSize = 0;
27676
27677 }
27678
27679 // Variables initialization
27680
27681 var ahole, h, hl; // looping of holes
27682
27683 var shapePoints = shape.extractPoints( curveSegments );
27684
27685 var vertices = shapePoints.shape;
27686 var holes = shapePoints.holes;
27687
27688 var reverse = ! ShapeUtils.isClockWise( vertices );
27689
27690 if ( reverse ) {
27691
27692 vertices = vertices.reverse();
27693
27694 // Maybe we should also check if holes are in the opposite direction, just to be safe ...
27695
27696 for ( h = 0, hl = holes.length; h < hl; h ++ ) {
27697
27698 ahole = holes[ h ];
27699
27700 if ( ShapeUtils.isClockWise( ahole ) ) {
27701
27702 holes[ h ] = ahole.reverse();
27703
27704 }
27705
27706 }
27707
27708 }
27709
27710
27711 var faces = ShapeUtils.triangulateShape( vertices, holes );
27712
27713 /* Vertices */
27714
27715 var contour = vertices; // vertices has all points but contour has only points of circumference
27716
27717 for ( h = 0, hl = holes.length; h < hl; h ++ ) {
27718
27719 ahole = holes[ h ];
27720
27721 vertices = vertices.concat( ahole );
27722
27723 }
27724
27725
27726 function scalePt2( pt, vec, size ) {
27727
27728 if ( ! vec ) console.error( "THREE.ExtrudeGeometry: vec does not exist" );
27729
27730 return vec.clone().multiplyScalar( size ).add( pt );
27731
27732 }
27733
27734 var b, bs, t, z,
27735 vert, vlen = vertices.length,
27736 face, flen = faces.length;
27737
27738
27739 // Find directions for point movement
27740
27741
27742 function getBevelVec( inPt, inPrev, inNext ) {
27743
27744 // computes for inPt the corresponding point inPt' on a new contour
27745 // shifted by 1 unit (length of normalized vector) to the left
27746 // if we walk along contour clockwise, this new contour is outside the old one
27747 //
27748 // inPt' is the intersection of the two lines parallel to the two
27749 // adjacent edges of inPt at a distance of 1 unit on the left side.
27750
27751 var v_trans_x, v_trans_y, shrink_by; // resulting translation vector for inPt
27752
27753 // good reading for geometry algorithms (here: line-line intersection)
27754 // http://geomalgorithms.com/a05-_intersect-1.html
27755
27756 var v_prev_x = inPt.x - inPrev.x,
27757 v_prev_y = inPt.y - inPrev.y;
27758 var v_next_x = inNext.x - inPt.x,
27759 v_next_y = inNext.y - inPt.y;
27760
27761 var v_prev_lensq = ( v_prev_x * v_prev_x + v_prev_y * v_prev_y );
27762
27763 // check for collinear edges
27764 var collinear0 = ( v_prev_x * v_next_y - v_prev_y * v_next_x );
27765
27766 if ( Math.abs( collinear0 ) > Number.EPSILON ) {
27767
27768 // not collinear
27769
27770 // length of vectors for normalizing
27771
27772 var v_prev_len = Math.sqrt( v_prev_lensq );
27773 var v_next_len = Math.sqrt( v_next_x * v_next_x + v_next_y * v_next_y );
27774
27775 // shift adjacent points by unit vectors to the left
27776
27777 var ptPrevShift_x = ( inPrev.x - v_prev_y / v_prev_len );
27778 var ptPrevShift_y = ( inPrev.y + v_prev_x / v_prev_len );
27779
27780 var ptNextShift_x = ( inNext.x - v_next_y / v_next_len );
27781 var ptNextShift_y = ( inNext.y + v_next_x / v_next_len );
27782
27783 // scaling factor for v_prev to intersection point
27784
27785 var sf = ( ( ptNextShift_x - ptPrevShift_x ) * v_next_y -
27786 ( ptNextShift_y - ptPrevShift_y ) * v_next_x ) /
27787 ( v_prev_x * v_next_y - v_prev_y * v_next_x );
27788
27789 // vector from inPt to intersection point
27790
27791 v_trans_x = ( ptPrevShift_x + v_prev_x * sf - inPt.x );
27792 v_trans_y = ( ptPrevShift_y + v_prev_y * sf - inPt.y );
27793
27794 // Don't normalize!, otherwise sharp corners become ugly
27795 // but prevent crazy spikes
27796 var v_trans_lensq = ( v_trans_x * v_trans_x + v_trans_y * v_trans_y );
27797 if ( v_trans_lensq <= 2 ) {
27798
27799 return new Vector2( v_trans_x, v_trans_y );
27800
27801 } else {
27802
27803 shrink_by = Math.sqrt( v_trans_lensq / 2 );
27804
27805 }
27806
27807 } else {
27808
27809 // handle special case of collinear edges
27810
27811 var direction_eq = false; // assumes: opposite
27812 if ( v_prev_x > Number.EPSILON ) {
27813
27814 if ( v_next_x > Number.EPSILON ) {
27815
27816 direction_eq = true;
27817
27818 }
27819
27820 } else {
27821
27822 if ( v_prev_x < - Number.EPSILON ) {
27823
27824 if ( v_next_x < - Number.EPSILON ) {
27825
27826 direction_eq = true;
27827
27828 }
27829
27830 } else {
27831
27832 if ( Math.sign( v_prev_y ) === Math.sign( v_next_y ) ) {
27833
27834 direction_eq = true;
27835
27836 }
27837
27838 }
27839
27840 }
27841
27842 if ( direction_eq ) {
27843
27844 // console.log("Warning: lines are a straight sequence");
27845 v_trans_x = - v_prev_y;
27846 v_trans_y = v_prev_x;
27847 shrink_by = Math.sqrt( v_prev_lensq );
27848
27849 } else {
27850
27851 // console.log("Warning: lines are a straight spike");
27852 v_trans_x = v_prev_x;
27853 v_trans_y = v_prev_y;
27854 shrink_by = Math.sqrt( v_prev_lensq / 2 );
27855
27856 }
27857
27858 }
27859
27860 return new Vector2( v_trans_x / shrink_by, v_trans_y / shrink_by );
27861
27862 }
27863
27864
27865 var contourMovements = [];
27866
27867 for ( var i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
27868
27869 if ( j === il ) j = 0;
27870 if ( k === il ) k = 0;
27871
27872 // (j)---(i)---(k)
27873 // console.log('i,j,k', i, j , k)
27874
27875 contourMovements[ i ] = getBevelVec( contour[ i ], contour[ j ], contour[ k ] );
27876
27877 }
27878
27879 var holesMovements = [],
27880 oneHoleMovements, verticesMovements = contourMovements.concat();
27881
27882 for ( h = 0, hl = holes.length; h < hl; h ++ ) {
27883
27884 ahole = holes[ h ];
27885
27886 oneHoleMovements = [];
27887
27888 for ( i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
27889
27890 if ( j === il ) j = 0;
27891 if ( k === il ) k = 0;
27892
27893 // (j)---(i)---(k)
27894 oneHoleMovements[ i ] = getBevelVec( ahole[ i ], ahole[ j ], ahole[ k ] );
27895
27896 }
27897
27898 holesMovements.push( oneHoleMovements );
27899 verticesMovements = verticesMovements.concat( oneHoleMovements );
27900
27901 }
27902
27903
27904 // Loop bevelSegments, 1 for the front, 1 for the back
27905
27906 for ( b = 0; b < bevelSegments; b ++ ) {
27907
27908 //for ( b = bevelSegments; b > 0; b -- ) {
27909
27910 t = b / bevelSegments;
27911 z = bevelThickness * Math.cos( t * Math.PI / 2 );
27912 bs = bevelSize * Math.sin( t * Math.PI / 2 );
27913
27914 // contract shape
27915
27916 for ( i = 0, il = contour.length; i < il; i ++ ) {
27917
27918 vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
27919
27920 v( vert.x, vert.y, - z );
27921
27922 }
27923
27924 // expand holes
27925
27926 for ( h = 0, hl = holes.length; h < hl; h ++ ) {
27927
27928 ahole = holes[ h ];
27929 oneHoleMovements = holesMovements[ h ];
27930
27931 for ( i = 0, il = ahole.length; i < il; i ++ ) {
27932
27933 vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
27934
27935 v( vert.x, vert.y, - z );
27936
27937 }
27938
27939 }
27940
27941 }
27942
27943 bs = bevelSize;
27944
27945 // Back facing vertices
27946
27947 for ( i = 0; i < vlen; i ++ ) {
27948
27949 vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
27950
27951 if ( ! extrudeByPath ) {
27952
27953 v( vert.x, vert.y, 0 );
27954
27955 } else {
27956
27957 // v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x );
27958
27959 normal.copy( splineTube.normals[ 0 ] ).multiplyScalar( vert.x );
27960 binormal.copy( splineTube.binormals[ 0 ] ).multiplyScalar( vert.y );
27961
27962 position2.copy( extrudePts[ 0 ] ).add( normal ).add( binormal );
27963
27964 v( position2.x, position2.y, position2.z );
27965
27966 }
27967
27968 }
27969
27970 // Add stepped vertices...
27971 // Including front facing vertices
27972
27973 var s;
27974
27975 for ( s = 1; s <= steps; s ++ ) {
27976
27977 for ( i = 0; i < vlen; i ++ ) {
27978
27979 vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
27980
27981 if ( ! extrudeByPath ) {
27982
27983 v( vert.x, vert.y, amount / steps * s );
27984
27985 } else {
27986
27987 // v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x );
27988
27989 normal.copy( splineTube.normals[ s ] ).multiplyScalar( vert.x );
27990 binormal.copy( splineTube.binormals[ s ] ).multiplyScalar( vert.y );
27991
27992 position2.copy( extrudePts[ s ] ).add( normal ).add( binormal );
27993
27994 v( position2.x, position2.y, position2.z );
27995
27996 }
27997
27998 }
27999
28000 }
28001
28002
28003 // Add bevel segments planes
28004
28005 //for ( b = 1; b <= bevelSegments; b ++ ) {
28006 for ( b = bevelSegments - 1; b >= 0; b -- ) {
28007
28008 t = b / bevelSegments;
28009 z = bevelThickness * Math.cos( t * Math.PI / 2 );
28010 bs = bevelSize * Math.sin( t * Math.PI / 2 );
28011
28012 // contract shape
28013
28014 for ( i = 0, il = contour.length; i < il; i ++ ) {
28015
28016 vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
28017 v( vert.x, vert.y, amount + z );
28018
28019 }
28020
28021 // expand holes
28022
28023 for ( h = 0, hl = holes.length; h < hl; h ++ ) {
28024
28025 ahole = holes[ h ];
28026 oneHoleMovements = holesMovements[ h ];
28027
28028 for ( i = 0, il = ahole.length; i < il; i ++ ) {
28029
28030 vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
28031
28032 if ( ! extrudeByPath ) {
28033
28034 v( vert.x, vert.y, amount + z );
28035
28036 } else {
28037
28038 v( vert.x, vert.y + extrudePts[ steps - 1 ].y, extrudePts[ steps - 1 ].x + z );
28039
28040 }
28041
28042 }
28043
28044 }
28045
28046 }
28047
28048 /* Faces */
28049
28050 // Top and bottom faces
28051
28052 buildLidFaces();
28053
28054 // Sides faces
28055
28056 buildSideFaces();
28057
28058
28059 ///// Internal functions
28060
28061 function buildLidFaces() {
28062
28063 var start = verticesArray.length / 3;
28064
28065 if ( bevelEnabled ) {
28066
28067 var layer = 0; // steps + 1
28068 var offset = vlen * layer;
28069
28070 // Bottom faces
28071
28072 for ( i = 0; i < flen; i ++ ) {
28073
28074 face = faces[ i ];
28075 f3( face[ 2 ] + offset, face[ 1 ] + offset, face[ 0 ] + offset );
28076
28077 }
28078
28079 layer = steps + bevelSegments * 2;
28080 offset = vlen * layer;
28081
28082 // Top faces
28083
28084 for ( i = 0; i < flen; i ++ ) {
28085
28086 face = faces[ i ];
28087 f3( face[ 0 ] + offset, face[ 1 ] + offset, face[ 2 ] + offset );
28088
28089 }
28090
28091 } else {
28092
28093 // Bottom faces
28094
28095 for ( i = 0; i < flen; i ++ ) {
28096
28097 face = faces[ i ];
28098 f3( face[ 2 ], face[ 1 ], face[ 0 ] );
28099
28100 }
28101
28102 // Top faces
28103
28104 for ( i = 0; i < flen; i ++ ) {
28105
28106 face = faces[ i ];
28107 f3( face[ 0 ] + vlen * steps, face[ 1 ] + vlen * steps, face[ 2 ] + vlen * steps );
28108
28109 }
28110
28111 }
28112
28113 scope.addGroup( start, verticesArray.length / 3 - start, 0 );
28114
28115 }
28116
28117 // Create faces for the z-sides of the shape
28118
28119 function buildSideFaces() {
28120
28121 var start = verticesArray.length / 3;
28122 var layeroffset = 0;
28123 sidewalls( contour, layeroffset );
28124 layeroffset += contour.length;
28125
28126 for ( h = 0, hl = holes.length; h < hl; h ++ ) {
28127
28128 ahole = holes[ h ];
28129 sidewalls( ahole, layeroffset );
28130
28131 //, true
28132 layeroffset += ahole.length;
28133
28134 }
28135
28136
28137 scope.addGroup( start, verticesArray.length / 3 - start, 1 );
28138
28139
28140 }
28141
28142 function sidewalls( contour, layeroffset ) {
28143
28144 var j, k;
28145 i = contour.length;
28146
28147 while ( -- i >= 0 ) {
28148
28149 j = i;
28150 k = i - 1;
28151 if ( k < 0 ) k = contour.length - 1;
28152
28153 //console.log('b', i,j, i-1, k,vertices.length);
28154
28155 var s = 0,
28156 sl = steps + bevelSegments * 2;
28157
28158 for ( s = 0; s < sl; s ++ ) {
28159
28160 var slen1 = vlen * s;
28161 var slen2 = vlen * ( s + 1 );
28162
28163 var a = layeroffset + j + slen1,
28164 b = layeroffset + k + slen1,
28165 c = layeroffset + k + slen2,
28166 d = layeroffset + j + slen2;
28167
28168 f4( a, b, c, d );
28169
28170 }
28171
28172 }
28173
28174 }
28175
28176 function v( x, y, z ) {
28177
28178 placeholder.push( x );
28179 placeholder.push( y );
28180 placeholder.push( z );
28181
28182 }
28183
28184
28185 function f3( a, b, c ) {
28186
28187 addVertex( a );
28188 addVertex( b );
28189 addVertex( c );
28190
28191 var nextIndex = verticesArray.length / 3;
28192 var uvs = uvgen.generateTopUV( scope, verticesArray, nextIndex - 3, nextIndex - 2, nextIndex - 1 );
28193
28194 addUV( uvs[ 0 ] );
28195 addUV( uvs[ 1 ] );
28196 addUV( uvs[ 2 ] );
28197
28198 }
28199
28200 function f4( a, b, c, d ) {
28201
28202 addVertex( a );
28203 addVertex( b );
28204 addVertex( d );
28205
28206 addVertex( b );
28207 addVertex( c );
28208 addVertex( d );
28209
28210
28211 var nextIndex = verticesArray.length / 3;
28212 var uvs = uvgen.generateSideWallUV( scope, verticesArray, nextIndex - 6, nextIndex - 3, nextIndex - 2, nextIndex - 1 );
28213
28214 addUV( uvs[ 0 ] );
28215 addUV( uvs[ 1 ] );
28216 addUV( uvs[ 3 ] );
28217
28218 addUV( uvs[ 1 ] );
28219 addUV( uvs[ 2 ] );
28220 addUV( uvs[ 3 ] );
28221
28222 }
28223
28224 function addVertex( index ) {
28225
28226 verticesArray.push( placeholder[ index * 3 + 0 ] );
28227 verticesArray.push( placeholder[ index * 3 + 1 ] );
28228 verticesArray.push( placeholder[ index * 3 + 2 ] );
28229
28230 }
28231
28232
28233 function addUV( vector2 ) {
28234
28235 uvArray.push( vector2.x );
28236 uvArray.push( vector2.y );
28237
28238 }
28239
28240 }
28241
28242}
28243
28244ExtrudeBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
28245ExtrudeBufferGeometry.prototype.constructor = ExtrudeBufferGeometry;
28246
28247var WorldUVGenerator = {
28248
28249 generateTopUV: function ( geometry, vertices, indexA, indexB, indexC ) {
28250
28251 var a_x = vertices[ indexA * 3 ];
28252 var a_y = vertices[ indexA * 3 + 1 ];
28253 var b_x = vertices[ indexB * 3 ];
28254 var b_y = vertices[ indexB * 3 + 1 ];
28255 var c_x = vertices[ indexC * 3 ];
28256 var c_y = vertices[ indexC * 3 + 1 ];
28257
28258 return [
28259 new Vector2( a_x, a_y ),
28260 new Vector2( b_x, b_y ),
28261 new Vector2( c_x, c_y )
28262 ];
28263
28264 },
28265
28266 generateSideWallUV: function ( geometry, vertices, indexA, indexB, indexC, indexD ) {
28267
28268 var a_x = vertices[ indexA * 3 ];
28269 var a_y = vertices[ indexA * 3 + 1 ];
28270 var a_z = vertices[ indexA * 3 + 2 ];
28271 var b_x = vertices[ indexB * 3 ];
28272 var b_y = vertices[ indexB * 3 + 1 ];
28273 var b_z = vertices[ indexB * 3 + 2 ];
28274 var c_x = vertices[ indexC * 3 ];
28275 var c_y = vertices[ indexC * 3 + 1 ];
28276 var c_z = vertices[ indexC * 3 + 2 ];
28277 var d_x = vertices[ indexD * 3 ];
28278 var d_y = vertices[ indexD * 3 + 1 ];
28279 var d_z = vertices[ indexD * 3 + 2 ];
28280
28281 if ( Math.abs( a_y - b_y ) < 0.01 ) {
28282
28283 return [
28284 new Vector2( a_x, 1 - a_z ),
28285 new Vector2( b_x, 1 - b_z ),
28286 new Vector2( c_x, 1 - c_z ),
28287 new Vector2( d_x, 1 - d_z )
28288 ];
28289
28290 } else {
28291
28292 return [
28293 new Vector2( a_y, 1 - a_z ),
28294 new Vector2( b_y, 1 - b_z ),
28295 new Vector2( c_y, 1 - c_z ),
28296 new Vector2( d_y, 1 - d_z )
28297 ];
28298
28299 }
28300
28301 }
28302};
28303
28304/**
28305 * @author zz85 / http://www.lab4games.net/zz85/blog
28306 * @author alteredq / http://alteredqualia.com/
28307 *
28308 * Text = 3D Text
28309 *
28310 * parameters = {
28311 * font: <THREE.Font>, // font
28312 *
28313 * size: <float>, // size of the text
28314 * height: <float>, // thickness to extrude text
28315 * curveSegments: <int>, // number of points on the curves
28316 *
28317 * bevelEnabled: <bool>, // turn on bevel
28318 * bevelThickness: <float>, // how deep into text bevel goes
28319 * bevelSize: <float> // how far from text outline is bevel
28320 * }
28321 */
28322
28323// TextGeometry
28324
28325function TextGeometry( text, parameters ) {
28326
28327 Geometry.call( this );
28328
28329 this.type = 'TextGeometry';
28330
28331 this.parameters = {
28332 text: text,
28333 parameters: parameters
28334 };
28335
28336 this.fromBufferGeometry( new TextBufferGeometry( text, parameters ) );
28337 this.mergeVertices();
28338
28339}
28340
28341TextGeometry.prototype = Object.create( Geometry.prototype );
28342TextGeometry.prototype.constructor = TextGeometry;
28343
28344// TextBufferGeometry
28345
28346function TextBufferGeometry( text, parameters ) {
28347
28348 parameters = parameters || {};
28349
28350 var font = parameters.font;
28351
28352 if ( ! ( font && font.isFont ) ) {
28353
28354 console.error( 'THREE.TextGeometry: font parameter is not an instance of THREE.Font.' );
28355 return new Geometry();
28356
28357 }
28358
28359 var shapes = font.generateShapes( text, parameters.size, parameters.curveSegments );
28360
28361 // translate parameters to ExtrudeGeometry API
28362
28363 parameters.amount = parameters.height !== undefined ? parameters.height : 50;
28364
28365 // defaults
28366
28367 if ( parameters.bevelThickness === undefined ) parameters.bevelThickness = 10;
28368 if ( parameters.bevelSize === undefined ) parameters.bevelSize = 8;
28369 if ( parameters.bevelEnabled === undefined ) parameters.bevelEnabled = false;
28370
28371 ExtrudeBufferGeometry.call( this, shapes, parameters );
28372
28373 this.type = 'TextBufferGeometry';
28374
28375}
28376
28377TextBufferGeometry.prototype = Object.create( ExtrudeBufferGeometry.prototype );
28378TextBufferGeometry.prototype.constructor = TextBufferGeometry;
28379
28380/**
28381 * @author mrdoob / http://mrdoob.com/
28382 * @author benaadams / https://twitter.com/ben_a_adams
28383 * @author Mugen87 / https://github.com/Mugen87
28384 */
28385
28386// SphereGeometry
28387
28388function SphereGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) {
28389
28390 Geometry.call( this );
28391
28392 this.type = 'SphereGeometry';
28393
28394 this.parameters = {
28395 radius: radius,
28396 widthSegments: widthSegments,
28397 heightSegments: heightSegments,
28398 phiStart: phiStart,
28399 phiLength: phiLength,
28400 thetaStart: thetaStart,
28401 thetaLength: thetaLength
28402 };
28403
28404 this.fromBufferGeometry( new SphereBufferGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) );
28405 this.mergeVertices();
28406
28407}
28408
28409SphereGeometry.prototype = Object.create( Geometry.prototype );
28410SphereGeometry.prototype.constructor = SphereGeometry;
28411
28412// SphereBufferGeometry
28413
28414function SphereBufferGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) {
28415
28416 BufferGeometry.call( this );
28417
28418 this.type = 'SphereBufferGeometry';
28419
28420 this.parameters = {
28421 radius: radius,
28422 widthSegments: widthSegments,
28423 heightSegments: heightSegments,
28424 phiStart: phiStart,
28425 phiLength: phiLength,
28426 thetaStart: thetaStart,
28427 thetaLength: thetaLength
28428 };
28429
28430 radius = radius || 1;
28431
28432 widthSegments = Math.max( 3, Math.floor( widthSegments ) || 8 );
28433 heightSegments = Math.max( 2, Math.floor( heightSegments ) || 6 );
28434
28435 phiStart = phiStart !== undefined ? phiStart : 0;
28436 phiLength = phiLength !== undefined ? phiLength : Math.PI * 2;
28437
28438 thetaStart = thetaStart !== undefined ? thetaStart : 0;
28439 thetaLength = thetaLength !== undefined ? thetaLength : Math.PI;
28440
28441 var thetaEnd = thetaStart + thetaLength;
28442
28443 var ix, iy;
28444
28445 var index = 0;
28446 var grid = [];
28447
28448 var vertex = new Vector3();
28449 var normal = new Vector3();
28450
28451 // buffers
28452
28453 var indices = [];
28454 var vertices = [];
28455 var normals = [];
28456 var uvs = [];
28457
28458 // generate vertices, normals and uvs
28459
28460 for ( iy = 0; iy <= heightSegments; iy ++ ) {
28461
28462 var verticesRow = [];
28463
28464 var v = iy / heightSegments;
28465
28466 for ( ix = 0; ix <= widthSegments; ix ++ ) {
28467
28468 var u = ix / widthSegments;
28469
28470 // vertex
28471
28472 vertex.x = - radius * Math.cos( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
28473 vertex.y = radius * Math.cos( thetaStart + v * thetaLength );
28474 vertex.z = radius * Math.sin( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
28475
28476 vertices.push( vertex.x, vertex.y, vertex.z );
28477
28478 // normal
28479
28480 normal.set( vertex.x, vertex.y, vertex.z ).normalize();
28481 normals.push( normal.x, normal.y, normal.z );
28482
28483 // uv
28484
28485 uvs.push( u, 1 - v );
28486
28487 verticesRow.push( index ++ );
28488
28489 }
28490
28491 grid.push( verticesRow );
28492
28493 }
28494
28495 // indices
28496
28497 for ( iy = 0; iy < heightSegments; iy ++ ) {
28498
28499 for ( ix = 0; ix < widthSegments; ix ++ ) {
28500
28501 var a = grid[ iy ][ ix + 1 ];
28502 var b = grid[ iy ][ ix ];
28503 var c = grid[ iy + 1 ][ ix ];
28504 var d = grid[ iy + 1 ][ ix + 1 ];
28505
28506 if ( iy !== 0 || thetaStart > 0 ) indices.push( a, b, d );
28507 if ( iy !== heightSegments - 1 || thetaEnd < Math.PI ) indices.push( b, c, d );
28508
28509 }
28510
28511 }
28512
28513 // build geometry
28514
28515 this.setIndex( indices );
28516 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
28517 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
28518 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
28519
28520}
28521
28522SphereBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
28523SphereBufferGeometry.prototype.constructor = SphereBufferGeometry;
28524
28525/**
28526 * @author Kaleb Murphy
28527 * @author Mugen87 / https://github.com/Mugen87
28528 */
28529
28530// RingGeometry
28531
28532function RingGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) {
28533
28534 Geometry.call( this );
28535
28536 this.type = 'RingGeometry';
28537
28538 this.parameters = {
28539 innerRadius: innerRadius,
28540 outerRadius: outerRadius,
28541 thetaSegments: thetaSegments,
28542 phiSegments: phiSegments,
28543 thetaStart: thetaStart,
28544 thetaLength: thetaLength
28545 };
28546
28547 this.fromBufferGeometry( new RingBufferGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) );
28548 this.mergeVertices();
28549
28550}
28551
28552RingGeometry.prototype = Object.create( Geometry.prototype );
28553RingGeometry.prototype.constructor = RingGeometry;
28554
28555// RingBufferGeometry
28556
28557function RingBufferGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) {
28558
28559 BufferGeometry.call( this );
28560
28561 this.type = 'RingBufferGeometry';
28562
28563 this.parameters = {
28564 innerRadius: innerRadius,
28565 outerRadius: outerRadius,
28566 thetaSegments: thetaSegments,
28567 phiSegments: phiSegments,
28568 thetaStart: thetaStart,
28569 thetaLength: thetaLength
28570 };
28571
28572 innerRadius = innerRadius || 0.5;
28573 outerRadius = outerRadius || 1;
28574
28575 thetaStart = thetaStart !== undefined ? thetaStart : 0;
28576 thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2;
28577
28578 thetaSegments = thetaSegments !== undefined ? Math.max( 3, thetaSegments ) : 8;
28579 phiSegments = phiSegments !== undefined ? Math.max( 1, phiSegments ) : 1;
28580
28581 // buffers
28582
28583 var indices = [];
28584 var vertices = [];
28585 var normals = [];
28586 var uvs = [];
28587
28588 // some helper variables
28589
28590 var segment;
28591 var radius = innerRadius;
28592 var radiusStep = ( ( outerRadius - innerRadius ) / phiSegments );
28593 var vertex = new Vector3();
28594 var uv = new Vector2();
28595 var j, i;
28596
28597 // generate vertices, normals and uvs
28598
28599 for ( j = 0; j <= phiSegments; j ++ ) {
28600
28601 for ( i = 0; i <= thetaSegments; i ++ ) {
28602
28603 // values are generate from the inside of the ring to the outside
28604
28605 segment = thetaStart + i / thetaSegments * thetaLength;
28606
28607 // vertex
28608
28609 vertex.x = radius * Math.cos( segment );
28610 vertex.y = radius * Math.sin( segment );
28611
28612 vertices.push( vertex.x, vertex.y, vertex.z );
28613
28614 // normal
28615
28616 normals.push( 0, 0, 1 );
28617
28618 // uv
28619
28620 uv.x = ( vertex.x / outerRadius + 1 ) / 2;
28621 uv.y = ( vertex.y / outerRadius + 1 ) / 2;
28622
28623 uvs.push( uv.x, uv.y );
28624
28625 }
28626
28627 // increase the radius for next row of vertices
28628
28629 radius += radiusStep;
28630
28631 }
28632
28633 // indices
28634
28635 for ( j = 0; j < phiSegments; j ++ ) {
28636
28637 var thetaSegmentLevel = j * ( thetaSegments + 1 );
28638
28639 for ( i = 0; i < thetaSegments; i ++ ) {
28640
28641 segment = i + thetaSegmentLevel;
28642
28643 var a = segment;
28644 var b = segment + thetaSegments + 1;
28645 var c = segment + thetaSegments + 2;
28646 var d = segment + 1;
28647
28648 // faces
28649
28650 indices.push( a, b, d );
28651 indices.push( b, c, d );
28652
28653 }
28654
28655 }
28656
28657 // build geometry
28658
28659 this.setIndex( indices );
28660 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
28661 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
28662 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
28663
28664}
28665
28666RingBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
28667RingBufferGeometry.prototype.constructor = RingBufferGeometry;
28668
28669/**
28670 * @author astrodud / http://astrodud.isgreat.org/
28671 * @author zz85 / https://github.com/zz85
28672 * @author bhouston / http://clara.io
28673 * @author Mugen87 / https://github.com/Mugen87
28674 */
28675
28676// LatheGeometry
28677
28678function LatheGeometry( points, segments, phiStart, phiLength ) {
28679
28680 Geometry.call( this );
28681
28682 this.type = 'LatheGeometry';
28683
28684 this.parameters = {
28685 points: points,
28686 segments: segments,
28687 phiStart: phiStart,
28688 phiLength: phiLength
28689 };
28690
28691 this.fromBufferGeometry( new LatheBufferGeometry( points, segments, phiStart, phiLength ) );
28692 this.mergeVertices();
28693
28694}
28695
28696LatheGeometry.prototype = Object.create( Geometry.prototype );
28697LatheGeometry.prototype.constructor = LatheGeometry;
28698
28699// LatheBufferGeometry
28700
28701function LatheBufferGeometry( points, segments, phiStart, phiLength ) {
28702
28703 BufferGeometry.call( this );
28704
28705 this.type = 'LatheBufferGeometry';
28706
28707 this.parameters = {
28708 points: points,
28709 segments: segments,
28710 phiStart: phiStart,
28711 phiLength: phiLength
28712 };
28713
28714 segments = Math.floor( segments ) || 12;
28715 phiStart = phiStart || 0;
28716 phiLength = phiLength || Math.PI * 2;
28717
28718 // clamp phiLength so it's in range of [ 0, 2PI ]
28719
28720 phiLength = _Math.clamp( phiLength, 0, Math.PI * 2 );
28721
28722
28723 // buffers
28724
28725 var indices = [];
28726 var vertices = [];
28727 var uvs = [];
28728
28729 // helper variables
28730
28731 var base;
28732 var inverseSegments = 1.0 / segments;
28733 var vertex = new Vector3();
28734 var uv = new Vector2();
28735 var i, j;
28736
28737 // generate vertices and uvs
28738
28739 for ( i = 0; i <= segments; i ++ ) {
28740
28741 var phi = phiStart + i * inverseSegments * phiLength;
28742
28743 var sin = Math.sin( phi );
28744 var cos = Math.cos( phi );
28745
28746 for ( j = 0; j <= ( points.length - 1 ); j ++ ) {
28747
28748 // vertex
28749
28750 vertex.x = points[ j ].x * sin;
28751 vertex.y = points[ j ].y;
28752 vertex.z = points[ j ].x * cos;
28753
28754 vertices.push( vertex.x, vertex.y, vertex.z );
28755
28756 // uv
28757
28758 uv.x = i / segments;
28759 uv.y = j / ( points.length - 1 );
28760
28761 uvs.push( uv.x, uv.y );
28762
28763
28764 }
28765
28766 }
28767
28768 // indices
28769
28770 for ( i = 0; i < segments; i ++ ) {
28771
28772 for ( j = 0; j < ( points.length - 1 ); j ++ ) {
28773
28774 base = j + i * points.length;
28775
28776 var a = base;
28777 var b = base + points.length;
28778 var c = base + points.length + 1;
28779 var d = base + 1;
28780
28781 // faces
28782
28783 indices.push( a, b, d );
28784 indices.push( b, c, d );
28785
28786 }
28787
28788 }
28789
28790 // build geometry
28791
28792 this.setIndex( indices );
28793 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
28794 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
28795
28796 // generate normals
28797
28798 this.computeVertexNormals();
28799
28800 // if the geometry is closed, we need to average the normals along the seam.
28801 // because the corresponding vertices are identical (but still have different UVs).
28802
28803 if ( phiLength === Math.PI * 2 ) {
28804
28805 var normals = this.attributes.normal.array;
28806 var n1 = new Vector3();
28807 var n2 = new Vector3();
28808 var n = new Vector3();
28809
28810 // this is the buffer offset for the last line of vertices
28811
28812 base = segments * points.length * 3;
28813
28814 for ( i = 0, j = 0; i < points.length; i ++, j += 3 ) {
28815
28816 // select the normal of the vertex in the first line
28817
28818 n1.x = normals[ j + 0 ];
28819 n1.y = normals[ j + 1 ];
28820 n1.z = normals[ j + 2 ];
28821
28822 // select the normal of the vertex in the last line
28823
28824 n2.x = normals[ base + j + 0 ];
28825 n2.y = normals[ base + j + 1 ];
28826 n2.z = normals[ base + j + 2 ];
28827
28828 // average normals
28829
28830 n.addVectors( n1, n2 ).normalize();
28831
28832 // assign the new values to both normals
28833
28834 normals[ j + 0 ] = normals[ base + j + 0 ] = n.x;
28835 normals[ j + 1 ] = normals[ base + j + 1 ] = n.y;
28836 normals[ j + 2 ] = normals[ base + j + 2 ] = n.z;
28837
28838 }
28839
28840 }
28841
28842}
28843
28844LatheBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
28845LatheBufferGeometry.prototype.constructor = LatheBufferGeometry;
28846
28847/**
28848 * @author jonobr1 / http://jonobr1.com
28849 * @author Mugen87 / https://github.com/Mugen87
28850 */
28851
28852// ShapeGeometry
28853
28854function ShapeGeometry( shapes, curveSegments ) {
28855
28856 Geometry.call( this );
28857
28858 this.type = 'ShapeGeometry';
28859
28860 if ( typeof curveSegments === 'object' ) {
28861
28862 console.warn( 'THREE.ShapeGeometry: Options parameter has been removed.' );
28863
28864 curveSegments = curveSegments.curveSegments;
28865
28866 }
28867
28868 this.parameters = {
28869 shapes: shapes,
28870 curveSegments: curveSegments
28871 };
28872
28873 this.fromBufferGeometry( new ShapeBufferGeometry( shapes, curveSegments ) );
28874 this.mergeVertices();
28875
28876}
28877
28878ShapeGeometry.prototype = Object.create( Geometry.prototype );
28879ShapeGeometry.prototype.constructor = ShapeGeometry;
28880
28881ShapeGeometry.prototype.toJSON = function () {
28882
28883 var data = Geometry.prototype.toJSON.call( this );
28884
28885 var shapes = this.parameters.shapes;
28886
28887 return toJSON( shapes, data );
28888
28889};
28890
28891// ShapeBufferGeometry
28892
28893function ShapeBufferGeometry( shapes, curveSegments ) {
28894
28895 BufferGeometry.call( this );
28896
28897 this.type = 'ShapeBufferGeometry';
28898
28899 this.parameters = {
28900 shapes: shapes,
28901 curveSegments: curveSegments
28902 };
28903
28904 curveSegments = curveSegments || 12;
28905
28906 // buffers
28907
28908 var indices = [];
28909 var vertices = [];
28910 var normals = [];
28911 var uvs = [];
28912
28913 // helper variables
28914
28915 var groupStart = 0;
28916 var groupCount = 0;
28917
28918 // allow single and array values for "shapes" parameter
28919
28920 if ( Array.isArray( shapes ) === false ) {
28921
28922 addShape( shapes );
28923
28924 } else {
28925
28926 for ( var i = 0; i < shapes.length; i ++ ) {
28927
28928 addShape( shapes[ i ] );
28929
28930 this.addGroup( groupStart, groupCount, i ); // enables MultiMaterial support
28931
28932 groupStart += groupCount;
28933 groupCount = 0;
28934
28935 }
28936
28937 }
28938
28939 // build geometry
28940
28941 this.setIndex( indices );
28942 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
28943 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
28944 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
28945
28946
28947 // helper functions
28948
28949 function addShape( shape ) {
28950
28951 var i, l, shapeHole;
28952
28953 var indexOffset = vertices.length / 3;
28954 var points = shape.extractPoints( curveSegments );
28955
28956 var shapeVertices = points.shape;
28957 var shapeHoles = points.holes;
28958
28959 // check direction of vertices
28960
28961 if ( ShapeUtils.isClockWise( shapeVertices ) === false ) {
28962
28963 shapeVertices = shapeVertices.reverse();
28964
28965 // also check if holes are in the opposite direction
28966
28967 for ( i = 0, l = shapeHoles.length; i < l; i ++ ) {
28968
28969 shapeHole = shapeHoles[ i ];
28970
28971 if ( ShapeUtils.isClockWise( shapeHole ) === true ) {
28972
28973 shapeHoles[ i ] = shapeHole.reverse();
28974
28975 }
28976
28977 }
28978
28979 }
28980
28981 var faces = ShapeUtils.triangulateShape( shapeVertices, shapeHoles );
28982
28983 // join vertices of inner and outer paths to a single array
28984
28985 for ( i = 0, l = shapeHoles.length; i < l; i ++ ) {
28986
28987 shapeHole = shapeHoles[ i ];
28988 shapeVertices = shapeVertices.concat( shapeHole );
28989
28990 }
28991
28992 // vertices, normals, uvs
28993
28994 for ( i = 0, l = shapeVertices.length; i < l; i ++ ) {
28995
28996 var vertex = shapeVertices[ i ];
28997
28998 vertices.push( vertex.x, vertex.y, 0 );
28999 normals.push( 0, 0, 1 );
29000 uvs.push( vertex.x, vertex.y ); // world uvs
29001
29002 }
29003
29004 // incides
29005
29006 for ( i = 0, l = faces.length; i < l; i ++ ) {
29007
29008 var face = faces[ i ];
29009
29010 var a = face[ 0 ] + indexOffset;
29011 var b = face[ 1 ] + indexOffset;
29012 var c = face[ 2 ] + indexOffset;
29013
29014 indices.push( a, b, c );
29015 groupCount += 3;
29016
29017 }
29018
29019 }
29020
29021}
29022
29023ShapeBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
29024ShapeBufferGeometry.prototype.constructor = ShapeBufferGeometry;
29025
29026ShapeBufferGeometry.prototype.toJSON = function () {
29027
29028 var data = BufferGeometry.prototype.toJSON.call( this );
29029
29030 var shapes = this.parameters.shapes;
29031
29032 return toJSON( shapes, data );
29033
29034};
29035
29036//
29037
29038function toJSON( shapes, data ) {
29039
29040 data.shapes = [];
29041
29042 if ( Array.isArray( shapes ) ) {
29043
29044 for ( var i = 0, l = shapes.length; i < l; i ++ ) {
29045
29046 var shape = shapes[ i ];
29047
29048 data.shapes.push( shape.uuid );
29049
29050 }
29051
29052 } else {
29053
29054 data.shapes.push( shapes.uuid );
29055
29056 }
29057
29058 return data;
29059
29060}
29061
29062/**
29063 * @author WestLangley / http://github.com/WestLangley
29064 * @author Mugen87 / https://github.com/Mugen87
29065 */
29066
29067function EdgesGeometry( geometry, thresholdAngle ) {
29068
29069 BufferGeometry.call( this );
29070
29071 this.type = 'EdgesGeometry';
29072
29073 this.parameters = {
29074 thresholdAngle: thresholdAngle
29075 };
29076
29077 thresholdAngle = ( thresholdAngle !== undefined ) ? thresholdAngle : 1;
29078
29079 // buffer
29080
29081 var vertices = [];
29082
29083 // helper variables
29084
29085 var thresholdDot = Math.cos( _Math.DEG2RAD * thresholdAngle );
29086 var edge = [ 0, 0 ], edges = {}, edge1, edge2;
29087 var key, keys = [ 'a', 'b', 'c' ];
29088
29089 // prepare source geometry
29090
29091 var geometry2;
29092
29093 if ( geometry.isBufferGeometry ) {
29094
29095 geometry2 = new Geometry();
29096 geometry2.fromBufferGeometry( geometry );
29097
29098 } else {
29099
29100 geometry2 = geometry.clone();
29101
29102 }
29103
29104 geometry2.mergeVertices();
29105 geometry2.computeFaceNormals();
29106
29107 var sourceVertices = geometry2.vertices;
29108 var faces = geometry2.faces;
29109
29110 // now create a data structure where each entry represents an edge with its adjoining faces
29111
29112 for ( var i = 0, l = faces.length; i < l; i ++ ) {
29113
29114 var face = faces[ i ];
29115
29116 for ( var j = 0; j < 3; j ++ ) {
29117
29118 edge1 = face[ keys[ j ] ];
29119 edge2 = face[ keys[ ( j + 1 ) % 3 ] ];
29120 edge[ 0 ] = Math.min( edge1, edge2 );
29121 edge[ 1 ] = Math.max( edge1, edge2 );
29122
29123 key = edge[ 0 ] + ',' + edge[ 1 ];
29124
29125 if ( edges[ key ] === undefined ) {
29126
29127 edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ], face1: i, face2: undefined };
29128
29129 } else {
29130
29131 edges[ key ].face2 = i;
29132
29133 }
29134
29135 }
29136
29137 }
29138
29139 // generate vertices
29140
29141 for ( key in edges ) {
29142
29143 var e = edges[ key ];
29144
29145 // an edge is only rendered if the angle (in degrees) between the face normals of the adjoining faces exceeds this value. default = 1 degree.
29146
29147 if ( e.face2 === undefined || faces[ e.face1 ].normal.dot( faces[ e.face2 ].normal ) <= thresholdDot ) {
29148
29149 var vertex = sourceVertices[ e.index1 ];
29150 vertices.push( vertex.x, vertex.y, vertex.z );
29151
29152 vertex = sourceVertices[ e.index2 ];
29153 vertices.push( vertex.x, vertex.y, vertex.z );
29154
29155 }
29156
29157 }
29158
29159 // build geometry
29160
29161 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
29162
29163}
29164
29165EdgesGeometry.prototype = Object.create( BufferGeometry.prototype );
29166EdgesGeometry.prototype.constructor = EdgesGeometry;
29167
29168/**
29169 * @author mrdoob / http://mrdoob.com/
29170 * @author Mugen87 / https://github.com/Mugen87
29171 */
29172
29173// CylinderGeometry
29174
29175function CylinderGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {
29176
29177 Geometry.call( this );
29178
29179 this.type = 'CylinderGeometry';
29180
29181 this.parameters = {
29182 radiusTop: radiusTop,
29183 radiusBottom: radiusBottom,
29184 height: height,
29185 radialSegments: radialSegments,
29186 heightSegments: heightSegments,
29187 openEnded: openEnded,
29188 thetaStart: thetaStart,
29189 thetaLength: thetaLength
29190 };
29191
29192 this.fromBufferGeometry( new CylinderBufferGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) );
29193 this.mergeVertices();
29194
29195}
29196
29197CylinderGeometry.prototype = Object.create( Geometry.prototype );
29198CylinderGeometry.prototype.constructor = CylinderGeometry;
29199
29200// CylinderBufferGeometry
29201
29202function CylinderBufferGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {
29203
29204 BufferGeometry.call( this );
29205
29206 this.type = 'CylinderBufferGeometry';
29207
29208 this.parameters = {
29209 radiusTop: radiusTop,
29210 radiusBottom: radiusBottom,
29211 height: height,
29212 radialSegments: radialSegments,
29213 heightSegments: heightSegments,
29214 openEnded: openEnded,
29215 thetaStart: thetaStart,
29216 thetaLength: thetaLength
29217 };
29218
29219 var scope = this;
29220
29221 radiusTop = radiusTop !== undefined ? radiusTop : 1;
29222 radiusBottom = radiusBottom !== undefined ? radiusBottom : 1;
29223 height = height || 1;
29224
29225 radialSegments = Math.floor( radialSegments ) || 8;
29226 heightSegments = Math.floor( heightSegments ) || 1;
29227
29228 openEnded = openEnded !== undefined ? openEnded : false;
29229 thetaStart = thetaStart !== undefined ? thetaStart : 0.0;
29230 thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2;
29231
29232 // buffers
29233
29234 var indices = [];
29235 var vertices = [];
29236 var normals = [];
29237 var uvs = [];
29238
29239 // helper variables
29240
29241 var index = 0;
29242 var indexArray = [];
29243 var halfHeight = height / 2;
29244 var groupStart = 0;
29245
29246 // generate geometry
29247
29248 generateTorso();
29249
29250 if ( openEnded === false ) {
29251
29252 if ( radiusTop > 0 ) generateCap( true );
29253 if ( radiusBottom > 0 ) generateCap( false );
29254
29255 }
29256
29257 // build geometry
29258
29259 this.setIndex( indices );
29260 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
29261 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
29262 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
29263
29264 function generateTorso() {
29265
29266 var x, y;
29267 var normal = new Vector3();
29268 var vertex = new Vector3();
29269
29270 var groupCount = 0;
29271
29272 // this will be used to calculate the normal
29273 var slope = ( radiusBottom - radiusTop ) / height;
29274
29275 // generate vertices, normals and uvs
29276
29277 for ( y = 0; y <= heightSegments; y ++ ) {
29278
29279 var indexRow = [];
29280
29281 var v = y / heightSegments;
29282
29283 // calculate the radius of the current row
29284
29285 var radius = v * ( radiusBottom - radiusTop ) + radiusTop;
29286
29287 for ( x = 0; x <= radialSegments; x ++ ) {
29288
29289 var u = x / radialSegments;
29290
29291 var theta = u * thetaLength + thetaStart;
29292
29293 var sinTheta = Math.sin( theta );
29294 var cosTheta = Math.cos( theta );
29295
29296 // vertex
29297
29298 vertex.x = radius * sinTheta;
29299 vertex.y = - v * height + halfHeight;
29300 vertex.z = radius * cosTheta;
29301 vertices.push( vertex.x, vertex.y, vertex.z );
29302
29303 // normal
29304
29305 normal.set( sinTheta, slope, cosTheta ).normalize();
29306 normals.push( normal.x, normal.y, normal.z );
29307
29308 // uv
29309
29310 uvs.push( u, 1 - v );
29311
29312 // save index of vertex in respective row
29313
29314 indexRow.push( index ++ );
29315
29316 }
29317
29318 // now save vertices of the row in our index array
29319
29320 indexArray.push( indexRow );
29321
29322 }
29323
29324 // generate indices
29325
29326 for ( x = 0; x < radialSegments; x ++ ) {
29327
29328 for ( y = 0; y < heightSegments; y ++ ) {
29329
29330 // we use the index array to access the correct indices
29331
29332 var a = indexArray[ y ][ x ];
29333 var b = indexArray[ y + 1 ][ x ];
29334 var c = indexArray[ y + 1 ][ x + 1 ];
29335 var d = indexArray[ y ][ x + 1 ];
29336
29337 // faces
29338
29339 indices.push( a, b, d );
29340 indices.push( b, c, d );
29341
29342 // update group counter
29343
29344 groupCount += 6;
29345
29346 }
29347
29348 }
29349
29350 // add a group to the geometry. this will ensure multi material support
29351
29352 scope.addGroup( groupStart, groupCount, 0 );
29353
29354 // calculate new start value for groups
29355
29356 groupStart += groupCount;
29357
29358 }
29359
29360 function generateCap( top ) {
29361
29362 var x, centerIndexStart, centerIndexEnd;
29363
29364 var uv = new Vector2();
29365 var vertex = new Vector3();
29366
29367 var groupCount = 0;
29368
29369 var radius = ( top === true ) ? radiusTop : radiusBottom;
29370 var sign = ( top === true ) ? 1 : - 1;
29371
29372 // save the index of the first center vertex
29373 centerIndexStart = index;
29374
29375 // first we generate the center vertex data of the cap.
29376 // because the geometry needs one set of uvs per face,
29377 // we must generate a center vertex per face/segment
29378
29379 for ( x = 1; x <= radialSegments; x ++ ) {
29380
29381 // vertex
29382
29383 vertices.push( 0, halfHeight * sign, 0 );
29384
29385 // normal
29386
29387 normals.push( 0, sign, 0 );
29388
29389 // uv
29390
29391 uvs.push( 0.5, 0.5 );
29392
29393 // increase index
29394
29395 index ++;
29396
29397 }
29398
29399 // save the index of the last center vertex
29400
29401 centerIndexEnd = index;
29402
29403 // now we generate the surrounding vertices, normals and uvs
29404
29405 for ( x = 0; x <= radialSegments; x ++ ) {
29406
29407 var u = x / radialSegments;
29408 var theta = u * thetaLength + thetaStart;
29409
29410 var cosTheta = Math.cos( theta );
29411 var sinTheta = Math.sin( theta );
29412
29413 // vertex
29414
29415 vertex.x = radius * sinTheta;
29416 vertex.y = halfHeight * sign;
29417 vertex.z = radius * cosTheta;
29418 vertices.push( vertex.x, vertex.y, vertex.z );
29419
29420 // normal
29421
29422 normals.push( 0, sign, 0 );
29423
29424 // uv
29425
29426 uv.x = ( cosTheta * 0.5 ) + 0.5;
29427 uv.y = ( sinTheta * 0.5 * sign ) + 0.5;
29428 uvs.push( uv.x, uv.y );
29429
29430 // increase index
29431
29432 index ++;
29433
29434 }
29435
29436 // generate indices
29437
29438 for ( x = 0; x < radialSegments; x ++ ) {
29439
29440 var c = centerIndexStart + x;
29441 var i = centerIndexEnd + x;
29442
29443 if ( top === true ) {
29444
29445 // face top
29446
29447 indices.push( i, i + 1, c );
29448
29449 } else {
29450
29451 // face bottom
29452
29453 indices.push( i + 1, i, c );
29454
29455 }
29456
29457 groupCount += 3;
29458
29459 }
29460
29461 // add a group to the geometry. this will ensure multi material support
29462
29463 scope.addGroup( groupStart, groupCount, top === true ? 1 : 2 );
29464
29465 // calculate new start value for groups
29466
29467 groupStart += groupCount;
29468
29469 }
29470
29471}
29472
29473CylinderBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
29474CylinderBufferGeometry.prototype.constructor = CylinderBufferGeometry;
29475
29476/**
29477 * @author abelnation / http://github.com/abelnation
29478 */
29479
29480// ConeGeometry
29481
29482function ConeGeometry( radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {
29483
29484 CylinderGeometry.call( this, 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength );
29485
29486 this.type = 'ConeGeometry';
29487
29488 this.parameters = {
29489 radius: radius,
29490 height: height,
29491 radialSegments: radialSegments,
29492 heightSegments: heightSegments,
29493 openEnded: openEnded,
29494 thetaStart: thetaStart,
29495 thetaLength: thetaLength
29496 };
29497
29498}
29499
29500ConeGeometry.prototype = Object.create( CylinderGeometry.prototype );
29501ConeGeometry.prototype.constructor = ConeGeometry;
29502
29503// ConeBufferGeometry
29504
29505function ConeBufferGeometry( radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {
29506
29507 CylinderBufferGeometry.call( this, 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength );
29508
29509 this.type = 'ConeBufferGeometry';
29510
29511 this.parameters = {
29512 radius: radius,
29513 height: height,
29514 radialSegments: radialSegments,
29515 heightSegments: heightSegments,
29516 openEnded: openEnded,
29517 thetaStart: thetaStart,
29518 thetaLength: thetaLength
29519 };
29520
29521}
29522
29523ConeBufferGeometry.prototype = Object.create( CylinderBufferGeometry.prototype );
29524ConeBufferGeometry.prototype.constructor = ConeBufferGeometry;
29525
29526/**
29527 * @author benaadams / https://twitter.com/ben_a_adams
29528 * @author Mugen87 / https://github.com/Mugen87
29529 * @author hughes
29530 */
29531
29532// CircleGeometry
29533
29534function CircleGeometry( radius, segments, thetaStart, thetaLength ) {
29535
29536 Geometry.call( this );
29537
29538 this.type = 'CircleGeometry';
29539
29540 this.parameters = {
29541 radius: radius,
29542 segments: segments,
29543 thetaStart: thetaStart,
29544 thetaLength: thetaLength
29545 };
29546
29547 this.fromBufferGeometry( new CircleBufferGeometry( radius, segments, thetaStart, thetaLength ) );
29548 this.mergeVertices();
29549
29550}
29551
29552CircleGeometry.prototype = Object.create( Geometry.prototype );
29553CircleGeometry.prototype.constructor = CircleGeometry;
29554
29555// CircleBufferGeometry
29556
29557function CircleBufferGeometry( radius, segments, thetaStart, thetaLength ) {
29558
29559 BufferGeometry.call( this );
29560
29561 this.type = 'CircleBufferGeometry';
29562
29563 this.parameters = {
29564 radius: radius,
29565 segments: segments,
29566 thetaStart: thetaStart,
29567 thetaLength: thetaLength
29568 };
29569
29570 radius = radius || 1;
29571 segments = segments !== undefined ? Math.max( 3, segments ) : 8;
29572
29573 thetaStart = thetaStart !== undefined ? thetaStart : 0;
29574 thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2;
29575
29576 // buffers
29577
29578 var indices = [];
29579 var vertices = [];
29580 var normals = [];
29581 var uvs = [];
29582
29583 // helper variables
29584
29585 var i, s;
29586 var vertex = new Vector3();
29587 var uv = new Vector2();
29588
29589 // center point
29590
29591 vertices.push( 0, 0, 0 );
29592 normals.push( 0, 0, 1 );
29593 uvs.push( 0.5, 0.5 );
29594
29595 for ( s = 0, i = 3; s <= segments; s ++, i += 3 ) {
29596
29597 var segment = thetaStart + s / segments * thetaLength;
29598
29599 // vertex
29600
29601 vertex.x = radius * Math.cos( segment );
29602 vertex.y = radius * Math.sin( segment );
29603
29604 vertices.push( vertex.x, vertex.y, vertex.z );
29605
29606 // normal
29607
29608 normals.push( 0, 0, 1 );
29609
29610 // uvs
29611
29612 uv.x = ( vertices[ i ] / radius + 1 ) / 2;
29613 uv.y = ( vertices[ i + 1 ] / radius + 1 ) / 2;
29614
29615 uvs.push( uv.x, uv.y );
29616
29617 }
29618
29619 // indices
29620
29621 for ( i = 1; i <= segments; i ++ ) {
29622
29623 indices.push( i, i + 1, 0 );
29624
29625 }
29626
29627 // build geometry
29628
29629 this.setIndex( indices );
29630 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
29631 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
29632 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
29633
29634}
29635
29636CircleBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
29637CircleBufferGeometry.prototype.constructor = CircleBufferGeometry;
29638
29639
29640
29641var Geometries = Object.freeze({
29642 WireframeGeometry: WireframeGeometry,
29643 ParametricGeometry: ParametricGeometry,
29644 ParametricBufferGeometry: ParametricBufferGeometry,
29645 TetrahedronGeometry: TetrahedronGeometry,
29646 TetrahedronBufferGeometry: TetrahedronBufferGeometry,
29647 OctahedronGeometry: OctahedronGeometry,
29648 OctahedronBufferGeometry: OctahedronBufferGeometry,
29649 IcosahedronGeometry: IcosahedronGeometry,
29650 IcosahedronBufferGeometry: IcosahedronBufferGeometry,
29651 DodecahedronGeometry: DodecahedronGeometry,
29652 DodecahedronBufferGeometry: DodecahedronBufferGeometry,
29653 PolyhedronGeometry: PolyhedronGeometry,
29654 PolyhedronBufferGeometry: PolyhedronBufferGeometry,
29655 TubeGeometry: TubeGeometry,
29656 TubeBufferGeometry: TubeBufferGeometry,
29657 TorusKnotGeometry: TorusKnotGeometry,
29658 TorusKnotBufferGeometry: TorusKnotBufferGeometry,
29659 TorusGeometry: TorusGeometry,
29660 TorusBufferGeometry: TorusBufferGeometry,
29661 TextGeometry: TextGeometry,
29662 TextBufferGeometry: TextBufferGeometry,
29663 SphereGeometry: SphereGeometry,
29664 SphereBufferGeometry: SphereBufferGeometry,
29665 RingGeometry: RingGeometry,
29666 RingBufferGeometry: RingBufferGeometry,
29667 PlaneGeometry: PlaneGeometry,
29668 PlaneBufferGeometry: PlaneBufferGeometry,
29669 LatheGeometry: LatheGeometry,
29670 LatheBufferGeometry: LatheBufferGeometry,
29671 ShapeGeometry: ShapeGeometry,
29672 ShapeBufferGeometry: ShapeBufferGeometry,
29673 ExtrudeGeometry: ExtrudeGeometry,
29674 ExtrudeBufferGeometry: ExtrudeBufferGeometry,
29675 EdgesGeometry: EdgesGeometry,
29676 ConeGeometry: ConeGeometry,
29677 ConeBufferGeometry: ConeBufferGeometry,
29678 CylinderGeometry: CylinderGeometry,
29679 CylinderBufferGeometry: CylinderBufferGeometry,
29680 CircleGeometry: CircleGeometry,
29681 CircleBufferGeometry: CircleBufferGeometry,
29682 BoxGeometry: BoxGeometry,
29683 BoxBufferGeometry: BoxBufferGeometry
29684});
29685
29686/**
29687 * @author mrdoob / http://mrdoob.com/
29688 *
29689 * parameters = {
29690 * color: <THREE.Color>
29691 * }
29692 */
29693
29694function ShadowMaterial( parameters ) {
29695
29696 Material.call( this );
29697
29698 this.type = 'ShadowMaterial';
29699
29700 this.color = new Color( 0x000000 );
29701 this.transparent = true;
29702
29703 this.setValues( parameters );
29704
29705}
29706
29707ShadowMaterial.prototype = Object.create( Material.prototype );
29708ShadowMaterial.prototype.constructor = ShadowMaterial;
29709
29710ShadowMaterial.prototype.isShadowMaterial = true;
29711
29712ShadowMaterial.prototype.copy = function ( source ) {
29713
29714 Material.prototype.copy.call( this, source );
29715
29716 this.color.copy( source.color );
29717
29718 return this;
29719
29720};
29721
29722/**
29723 * @author mrdoob / http://mrdoob.com/
29724 */
29725
29726function RawShaderMaterial( parameters ) {
29727
29728 ShaderMaterial.call( this, parameters );
29729
29730 this.type = 'RawShaderMaterial';
29731
29732}
29733
29734RawShaderMaterial.prototype = Object.create( ShaderMaterial.prototype );
29735RawShaderMaterial.prototype.constructor = RawShaderMaterial;
29736
29737RawShaderMaterial.prototype.isRawShaderMaterial = true;
29738
29739/**
29740 * @author WestLangley / http://github.com/WestLangley
29741 *
29742 * parameters = {
29743 * color: <hex>,
29744 * roughness: <float>,
29745 * metalness: <float>,
29746 * opacity: <float>,
29747 *
29748 * map: new THREE.Texture( <Image> ),
29749 *
29750 * lightMap: new THREE.Texture( <Image> ),
29751 * lightMapIntensity: <float>
29752 *
29753 * aoMap: new THREE.Texture( <Image> ),
29754 * aoMapIntensity: <float>
29755 *
29756 * emissive: <hex>,
29757 * emissiveIntensity: <float>
29758 * emissiveMap: new THREE.Texture( <Image> ),
29759 *
29760 * bumpMap: new THREE.Texture( <Image> ),
29761 * bumpScale: <float>,
29762 *
29763 * normalMap: new THREE.Texture( <Image> ),
29764 * normalScale: <Vector2>,
29765 *
29766 * displacementMap: new THREE.Texture( <Image> ),
29767 * displacementScale: <float>,
29768 * displacementBias: <float>,
29769 *
29770 * roughnessMap: new THREE.Texture( <Image> ),
29771 *
29772 * metalnessMap: new THREE.Texture( <Image> ),
29773 *
29774 * alphaMap: new THREE.Texture( <Image> ),
29775 *
29776 * envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
29777 * envMapIntensity: <float>
29778 *
29779 * refractionRatio: <float>,
29780 *
29781 * wireframe: <boolean>,
29782 * wireframeLinewidth: <float>,
29783 *
29784 * skinning: <bool>,
29785 * morphTargets: <bool>,
29786 * morphNormals: <bool>
29787 * }
29788 */
29789
29790function MeshStandardMaterial( parameters ) {
29791
29792 Material.call( this );
29793
29794 this.defines = { 'STANDARD': '' };
29795
29796 this.type = 'MeshStandardMaterial';
29797
29798 this.color = new Color( 0xffffff ); // diffuse
29799 this.roughness = 0.5;
29800 this.metalness = 0.5;
29801
29802 this.map = null;
29803
29804 this.lightMap = null;
29805 this.lightMapIntensity = 1.0;
29806
29807 this.aoMap = null;
29808 this.aoMapIntensity = 1.0;
29809
29810 this.emissive = new Color( 0x000000 );
29811 this.emissiveIntensity = 1.0;
29812 this.emissiveMap = null;
29813
29814 this.bumpMap = null;
29815 this.bumpScale = 1;
29816
29817 this.normalMap = null;
29818 this.normalScale = new Vector2( 1, 1 );
29819
29820 this.displacementMap = null;
29821 this.displacementScale = 1;
29822 this.displacementBias = 0;
29823
29824 this.roughnessMap = null;
29825
29826 this.metalnessMap = null;
29827
29828 this.alphaMap = null;
29829
29830 this.envMap = null;
29831 this.envMapIntensity = 1.0;
29832
29833 this.refractionRatio = 0.98;
29834
29835 this.wireframe = false;
29836 this.wireframeLinewidth = 1;
29837 this.wireframeLinecap = 'round';
29838 this.wireframeLinejoin = 'round';
29839
29840 this.skinning = false;
29841 this.morphTargets = false;
29842 this.morphNormals = false;
29843
29844 this.setValues( parameters );
29845
29846}
29847
29848MeshStandardMaterial.prototype = Object.create( Material.prototype );
29849MeshStandardMaterial.prototype.constructor = MeshStandardMaterial;
29850
29851MeshStandardMaterial.prototype.isMeshStandardMaterial = true;
29852
29853MeshStandardMaterial.prototype.copy = function ( source ) {
29854
29855 Material.prototype.copy.call( this, source );
29856
29857 this.defines = { 'STANDARD': '' };
29858
29859 this.color.copy( source.color );
29860 this.roughness = source.roughness;
29861 this.metalness = source.metalness;
29862
29863 this.map = source.map;
29864
29865 this.lightMap = source.lightMap;
29866 this.lightMapIntensity = source.lightMapIntensity;
29867
29868 this.aoMap = source.aoMap;
29869 this.aoMapIntensity = source.aoMapIntensity;
29870
29871 this.emissive.copy( source.emissive );
29872 this.emissiveMap = source.emissiveMap;
29873 this.emissiveIntensity = source.emissiveIntensity;
29874
29875 this.bumpMap = source.bumpMap;
29876 this.bumpScale = source.bumpScale;
29877
29878 this.normalMap = source.normalMap;
29879 this.normalScale.copy( source.normalScale );
29880
29881 this.displacementMap = source.displacementMap;
29882 this.displacementScale = source.displacementScale;
29883 this.displacementBias = source.displacementBias;
29884
29885 this.roughnessMap = source.roughnessMap;
29886
29887 this.metalnessMap = source.metalnessMap;
29888
29889 this.alphaMap = source.alphaMap;
29890
29891 this.envMap = source.envMap;
29892 this.envMapIntensity = source.envMapIntensity;
29893
29894 this.refractionRatio = source.refractionRatio;
29895
29896 this.wireframe = source.wireframe;
29897 this.wireframeLinewidth = source.wireframeLinewidth;
29898 this.wireframeLinecap = source.wireframeLinecap;
29899 this.wireframeLinejoin = source.wireframeLinejoin;
29900
29901 this.skinning = source.skinning;
29902 this.morphTargets = source.morphTargets;
29903 this.morphNormals = source.morphNormals;
29904
29905 return this;
29906
29907};
29908
29909/**
29910 * @author WestLangley / http://github.com/WestLangley
29911 *
29912 * parameters = {
29913 * reflectivity: <float>
29914 * }
29915 */
29916
29917function MeshPhysicalMaterial( parameters ) {
29918
29919 MeshStandardMaterial.call( this );
29920
29921 this.defines = { 'PHYSICAL': '' };
29922
29923 this.type = 'MeshPhysicalMaterial';
29924
29925 this.reflectivity = 0.5; // maps to F0 = 0.04
29926
29927 this.clearCoat = 0.0;
29928 this.clearCoatRoughness = 0.0;
29929
29930 this.setValues( parameters );
29931
29932}
29933
29934MeshPhysicalMaterial.prototype = Object.create( MeshStandardMaterial.prototype );
29935MeshPhysicalMaterial.prototype.constructor = MeshPhysicalMaterial;
29936
29937MeshPhysicalMaterial.prototype.isMeshPhysicalMaterial = true;
29938
29939MeshPhysicalMaterial.prototype.copy = function ( source ) {
29940
29941 MeshStandardMaterial.prototype.copy.call( this, source );
29942
29943 this.defines = { 'PHYSICAL': '' };
29944
29945 this.reflectivity = source.reflectivity;
29946
29947 this.clearCoat = source.clearCoat;
29948 this.clearCoatRoughness = source.clearCoatRoughness;
29949
29950 return this;
29951
29952};
29953
29954/**
29955 * @author mrdoob / http://mrdoob.com/
29956 * @author alteredq / http://alteredqualia.com/
29957 *
29958 * parameters = {
29959 * color: <hex>,
29960 * specular: <hex>,
29961 * shininess: <float>,
29962 * opacity: <float>,
29963 *
29964 * map: new THREE.Texture( <Image> ),
29965 *
29966 * lightMap: new THREE.Texture( <Image> ),
29967 * lightMapIntensity: <float>
29968 *
29969 * aoMap: new THREE.Texture( <Image> ),
29970 * aoMapIntensity: <float>
29971 *
29972 * emissive: <hex>,
29973 * emissiveIntensity: <float>
29974 * emissiveMap: new THREE.Texture( <Image> ),
29975 *
29976 * bumpMap: new THREE.Texture( <Image> ),
29977 * bumpScale: <float>,
29978 *
29979 * normalMap: new THREE.Texture( <Image> ),
29980 * normalScale: <Vector2>,
29981 *
29982 * displacementMap: new THREE.Texture( <Image> ),
29983 * displacementScale: <float>,
29984 * displacementBias: <float>,
29985 *
29986 * specularMap: new THREE.Texture( <Image> ),
29987 *
29988 * alphaMap: new THREE.Texture( <Image> ),
29989 *
29990 * envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
29991 * combine: THREE.Multiply,
29992 * reflectivity: <float>,
29993 * refractionRatio: <float>,
29994 *
29995 * wireframe: <boolean>,
29996 * wireframeLinewidth: <float>,
29997 *
29998 * skinning: <bool>,
29999 * morphTargets: <bool>,
30000 * morphNormals: <bool>
30001 * }
30002 */
30003
30004function MeshPhongMaterial( parameters ) {
30005
30006 Material.call( this );
30007
30008 this.type = 'MeshPhongMaterial';
30009
30010 this.color = new Color( 0xffffff ); // diffuse
30011 this.specular = new Color( 0x111111 );
30012 this.shininess = 30;
30013
30014 this.map = null;
30015
30016 this.lightMap = null;
30017 this.lightMapIntensity = 1.0;
30018
30019 this.aoMap = null;
30020 this.aoMapIntensity = 1.0;
30021
30022 this.emissive = new Color( 0x000000 );
30023 this.emissiveIntensity = 1.0;
30024 this.emissiveMap = null;
30025
30026 this.bumpMap = null;
30027 this.bumpScale = 1;
30028
30029 this.normalMap = null;
30030 this.normalScale = new Vector2( 1, 1 );
30031
30032 this.displacementMap = null;
30033 this.displacementScale = 1;
30034 this.displacementBias = 0;
30035
30036 this.specularMap = null;
30037
30038 this.alphaMap = null;
30039
30040 this.envMap = null;
30041 this.combine = MultiplyOperation;
30042 this.reflectivity = 1;
30043 this.refractionRatio = 0.98;
30044
30045 this.wireframe = false;
30046 this.wireframeLinewidth = 1;
30047 this.wireframeLinecap = 'round';
30048 this.wireframeLinejoin = 'round';
30049
30050 this.skinning = false;
30051 this.morphTargets = false;
30052 this.morphNormals = false;
30053
30054 this.setValues( parameters );
30055
30056}
30057
30058MeshPhongMaterial.prototype = Object.create( Material.prototype );
30059MeshPhongMaterial.prototype.constructor = MeshPhongMaterial;
30060
30061MeshPhongMaterial.prototype.isMeshPhongMaterial = true;
30062
30063MeshPhongMaterial.prototype.copy = function ( source ) {
30064
30065 Material.prototype.copy.call( this, source );
30066
30067 this.color.copy( source.color );
30068 this.specular.copy( source.specular );
30069 this.shininess = source.shininess;
30070
30071 this.map = source.map;
30072
30073 this.lightMap = source.lightMap;
30074 this.lightMapIntensity = source.lightMapIntensity;
30075
30076 this.aoMap = source.aoMap;
30077 this.aoMapIntensity = source.aoMapIntensity;
30078
30079 this.emissive.copy( source.emissive );
30080 this.emissiveMap = source.emissiveMap;
30081 this.emissiveIntensity = source.emissiveIntensity;
30082
30083 this.bumpMap = source.bumpMap;
30084 this.bumpScale = source.bumpScale;
30085
30086 this.normalMap = source.normalMap;
30087 this.normalScale.copy( source.normalScale );
30088
30089 this.displacementMap = source.displacementMap;
30090 this.displacementScale = source.displacementScale;
30091 this.displacementBias = source.displacementBias;
30092
30093 this.specularMap = source.specularMap;
30094
30095 this.alphaMap = source.alphaMap;
30096
30097 this.envMap = source.envMap;
30098 this.combine = source.combine;
30099 this.reflectivity = source.reflectivity;
30100 this.refractionRatio = source.refractionRatio;
30101
30102 this.wireframe = source.wireframe;
30103 this.wireframeLinewidth = source.wireframeLinewidth;
30104 this.wireframeLinecap = source.wireframeLinecap;
30105 this.wireframeLinejoin = source.wireframeLinejoin;
30106
30107 this.skinning = source.skinning;
30108 this.morphTargets = source.morphTargets;
30109 this.morphNormals = source.morphNormals;
30110
30111 return this;
30112
30113};
30114
30115/**
30116 * @author takahirox / http://github.com/takahirox
30117 *
30118 * parameters = {
30119 * gradientMap: new THREE.Texture( <Image> )
30120 * }
30121 */
30122
30123function MeshToonMaterial( parameters ) {
30124
30125 MeshPhongMaterial.call( this );
30126
30127 this.defines = { 'TOON': '' };
30128
30129 this.type = 'MeshToonMaterial';
30130
30131 this.gradientMap = null;
30132
30133 this.setValues( parameters );
30134
30135}
30136
30137MeshToonMaterial.prototype = Object.create( MeshPhongMaterial.prototype );
30138MeshToonMaterial.prototype.constructor = MeshToonMaterial;
30139
30140MeshToonMaterial.prototype.isMeshToonMaterial = true;
30141
30142MeshToonMaterial.prototype.copy = function ( source ) {
30143
30144 MeshPhongMaterial.prototype.copy.call( this, source );
30145
30146 this.gradientMap = source.gradientMap;
30147
30148 return this;
30149
30150};
30151
30152/**
30153 * @author mrdoob / http://mrdoob.com/
30154 * @author WestLangley / http://github.com/WestLangley
30155 *
30156 * parameters = {
30157 * opacity: <float>,
30158 *
30159 * bumpMap: new THREE.Texture( <Image> ),
30160 * bumpScale: <float>,
30161 *
30162 * normalMap: new THREE.Texture( <Image> ),
30163 * normalScale: <Vector2>,
30164 *
30165 * displacementMap: new THREE.Texture( <Image> ),
30166 * displacementScale: <float>,
30167 * displacementBias: <float>,
30168 *
30169 * wireframe: <boolean>,
30170 * wireframeLinewidth: <float>
30171 *
30172 * skinning: <bool>,
30173 * morphTargets: <bool>,
30174 * morphNormals: <bool>
30175 * }
30176 */
30177
30178function MeshNormalMaterial( parameters ) {
30179
30180 Material.call( this );
30181
30182 this.type = 'MeshNormalMaterial';
30183
30184 this.bumpMap = null;
30185 this.bumpScale = 1;
30186
30187 this.normalMap = null;
30188 this.normalScale = new Vector2( 1, 1 );
30189
30190 this.displacementMap = null;
30191 this.displacementScale = 1;
30192 this.displacementBias = 0;
30193
30194 this.wireframe = false;
30195 this.wireframeLinewidth = 1;
30196
30197 this.fog = false;
30198 this.lights = false;
30199
30200 this.skinning = false;
30201 this.morphTargets = false;
30202 this.morphNormals = false;
30203
30204 this.setValues( parameters );
30205
30206}
30207
30208MeshNormalMaterial.prototype = Object.create( Material.prototype );
30209MeshNormalMaterial.prototype.constructor = MeshNormalMaterial;
30210
30211MeshNormalMaterial.prototype.isMeshNormalMaterial = true;
30212
30213MeshNormalMaterial.prototype.copy = function ( source ) {
30214
30215 Material.prototype.copy.call( this, source );
30216
30217 this.bumpMap = source.bumpMap;
30218 this.bumpScale = source.bumpScale;
30219
30220 this.normalMap = source.normalMap;
30221 this.normalScale.copy( source.normalScale );
30222
30223 this.displacementMap = source.displacementMap;
30224 this.displacementScale = source.displacementScale;
30225 this.displacementBias = source.displacementBias;
30226
30227 this.wireframe = source.wireframe;
30228 this.wireframeLinewidth = source.wireframeLinewidth;
30229
30230 this.skinning = source.skinning;
30231 this.morphTargets = source.morphTargets;
30232 this.morphNormals = source.morphNormals;
30233
30234 return this;
30235
30236};
30237
30238/**
30239 * @author mrdoob / http://mrdoob.com/
30240 * @author alteredq / http://alteredqualia.com/
30241 *
30242 * parameters = {
30243 * color: <hex>,
30244 * opacity: <float>,
30245 *
30246 * map: new THREE.Texture( <Image> ),
30247 *
30248 * lightMap: new THREE.Texture( <Image> ),
30249 * lightMapIntensity: <float>
30250 *
30251 * aoMap: new THREE.Texture( <Image> ),
30252 * aoMapIntensity: <float>
30253 *
30254 * emissive: <hex>,
30255 * emissiveIntensity: <float>
30256 * emissiveMap: new THREE.Texture( <Image> ),
30257 *
30258 * specularMap: new THREE.Texture( <Image> ),
30259 *
30260 * alphaMap: new THREE.Texture( <Image> ),
30261 *
30262 * envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
30263 * combine: THREE.Multiply,
30264 * reflectivity: <float>,
30265 * refractionRatio: <float>,
30266 *
30267 * wireframe: <boolean>,
30268 * wireframeLinewidth: <float>,
30269 *
30270 * skinning: <bool>,
30271 * morphTargets: <bool>,
30272 * morphNormals: <bool>
30273 * }
30274 */
30275
30276function MeshLambertMaterial( parameters ) {
30277
30278 Material.call( this );
30279
30280 this.type = 'MeshLambertMaterial';
30281
30282 this.color = new Color( 0xffffff ); // diffuse
30283
30284 this.map = null;
30285
30286 this.lightMap = null;
30287 this.lightMapIntensity = 1.0;
30288
30289 this.aoMap = null;
30290 this.aoMapIntensity = 1.0;
30291
30292 this.emissive = new Color( 0x000000 );
30293 this.emissiveIntensity = 1.0;
30294 this.emissiveMap = null;
30295
30296 this.specularMap = null;
30297
30298 this.alphaMap = null;
30299
30300 this.envMap = null;
30301 this.combine = MultiplyOperation;
30302 this.reflectivity = 1;
30303 this.refractionRatio = 0.98;
30304
30305 this.wireframe = false;
30306 this.wireframeLinewidth = 1;
30307 this.wireframeLinecap = 'round';
30308 this.wireframeLinejoin = 'round';
30309
30310 this.skinning = false;
30311 this.morphTargets = false;
30312 this.morphNormals = false;
30313
30314 this.setValues( parameters );
30315
30316}
30317
30318MeshLambertMaterial.prototype = Object.create( Material.prototype );
30319MeshLambertMaterial.prototype.constructor = MeshLambertMaterial;
30320
30321MeshLambertMaterial.prototype.isMeshLambertMaterial = true;
30322
30323MeshLambertMaterial.prototype.copy = function ( source ) {
30324
30325 Material.prototype.copy.call( this, source );
30326
30327 this.color.copy( source.color );
30328
30329 this.map = source.map;
30330
30331 this.lightMap = source.lightMap;
30332 this.lightMapIntensity = source.lightMapIntensity;
30333
30334 this.aoMap = source.aoMap;
30335 this.aoMapIntensity = source.aoMapIntensity;
30336
30337 this.emissive.copy( source.emissive );
30338 this.emissiveMap = source.emissiveMap;
30339 this.emissiveIntensity = source.emissiveIntensity;
30340
30341 this.specularMap = source.specularMap;
30342
30343 this.alphaMap = source.alphaMap;
30344
30345 this.envMap = source.envMap;
30346 this.combine = source.combine;
30347 this.reflectivity = source.reflectivity;
30348 this.refractionRatio = source.refractionRatio;
30349
30350 this.wireframe = source.wireframe;
30351 this.wireframeLinewidth = source.wireframeLinewidth;
30352 this.wireframeLinecap = source.wireframeLinecap;
30353 this.wireframeLinejoin = source.wireframeLinejoin;
30354
30355 this.skinning = source.skinning;
30356 this.morphTargets = source.morphTargets;
30357 this.morphNormals = source.morphNormals;
30358
30359 return this;
30360
30361};
30362
30363/**
30364 * @author alteredq / http://alteredqualia.com/
30365 *
30366 * parameters = {
30367 * color: <hex>,
30368 * opacity: <float>,
30369 *
30370 * linewidth: <float>,
30371 *
30372 * scale: <float>,
30373 * dashSize: <float>,
30374 * gapSize: <float>
30375 * }
30376 */
30377
30378function LineDashedMaterial( parameters ) {
30379
30380 LineBasicMaterial.call( this );
30381
30382 this.type = 'LineDashedMaterial';
30383
30384 this.scale = 1;
30385 this.dashSize = 3;
30386 this.gapSize = 1;
30387
30388 this.setValues( parameters );
30389
30390}
30391
30392LineDashedMaterial.prototype = Object.create( LineBasicMaterial.prototype );
30393LineDashedMaterial.prototype.constructor = LineDashedMaterial;
30394
30395LineDashedMaterial.prototype.isLineDashedMaterial = true;
30396
30397LineDashedMaterial.prototype.copy = function ( source ) {
30398
30399 LineBasicMaterial.prototype.copy.call( this, source );
30400
30401 this.scale = source.scale;
30402 this.dashSize = source.dashSize;
30403 this.gapSize = source.gapSize;
30404
30405 return this;
30406
30407};
30408
30409
30410
30411var Materials = Object.freeze({
30412 ShadowMaterial: ShadowMaterial,
30413 SpriteMaterial: SpriteMaterial,
30414 RawShaderMaterial: RawShaderMaterial,
30415 ShaderMaterial: ShaderMaterial,
30416 PointsMaterial: PointsMaterial,
30417 MeshPhysicalMaterial: MeshPhysicalMaterial,
30418 MeshStandardMaterial: MeshStandardMaterial,
30419 MeshPhongMaterial: MeshPhongMaterial,
30420 MeshToonMaterial: MeshToonMaterial,
30421 MeshNormalMaterial: MeshNormalMaterial,
30422 MeshLambertMaterial: MeshLambertMaterial,
30423 MeshDepthMaterial: MeshDepthMaterial,
30424 MeshDistanceMaterial: MeshDistanceMaterial,
30425 MeshBasicMaterial: MeshBasicMaterial,
30426 LineDashedMaterial: LineDashedMaterial,
30427 LineBasicMaterial: LineBasicMaterial,
30428 Material: Material
30429});
30430
30431/**
30432 * @author mrdoob / http://mrdoob.com/
30433 */
30434
30435var Cache = {
30436
30437 enabled: false,
30438
30439 files: {},
30440
30441 add: function ( key, file ) {
30442
30443 if ( this.enabled === false ) return;
30444
30445 // console.log( 'THREE.Cache', 'Adding key:', key );
30446
30447 this.files[ key ] = file;
30448
30449 },
30450
30451 get: function ( key ) {
30452
30453 if ( this.enabled === false ) return;
30454
30455 // console.log( 'THREE.Cache', 'Checking key:', key );
30456
30457 return this.files[ key ];
30458
30459 },
30460
30461 remove: function ( key ) {
30462
30463 delete this.files[ key ];
30464
30465 },
30466
30467 clear: function () {
30468
30469 this.files = {};
30470
30471 }
30472
30473};
30474
30475/**
30476 * @author mrdoob / http://mrdoob.com/
30477 */
30478
30479function LoadingManager( onLoad, onProgress, onError ) {
30480
30481 var scope = this;
30482
30483 var isLoading = false;
30484 var itemsLoaded = 0;
30485 var itemsTotal = 0;
30486 var urlModifier = undefined;
30487
30488 this.onStart = undefined;
30489 this.onLoad = onLoad;
30490 this.onProgress = onProgress;
30491 this.onError = onError;
30492
30493 this.itemStart = function ( url ) {
30494
30495 itemsTotal ++;
30496
30497 if ( isLoading === false ) {
30498
30499 if ( scope.onStart !== undefined ) {
30500
30501 scope.onStart( url, itemsLoaded, itemsTotal );
30502
30503 }
30504
30505 }
30506
30507 isLoading = true;
30508
30509 };
30510
30511 this.itemEnd = function ( url ) {
30512
30513 itemsLoaded ++;
30514
30515 if ( scope.onProgress !== undefined ) {
30516
30517 scope.onProgress( url, itemsLoaded, itemsTotal );
30518
30519 }
30520
30521 if ( itemsLoaded === itemsTotal ) {
30522
30523 isLoading = false;
30524
30525 if ( scope.onLoad !== undefined ) {
30526
30527 scope.onLoad();
30528
30529 }
30530
30531 }
30532
30533 };
30534
30535 this.itemError = function ( url ) {
30536
30537 if ( scope.onError !== undefined ) {
30538
30539 scope.onError( url );
30540
30541 }
30542
30543 };
30544
30545 this.resolveURL = function ( url ) {
30546
30547 if ( urlModifier ) {
30548
30549 return urlModifier( url );
30550
30551 }
30552
30553 return url;
30554
30555 };
30556
30557 this.setURLModifier = function ( transform ) {
30558
30559 urlModifier = transform;
30560 return this;
30561
30562 };
30563
30564}
30565
30566var DefaultLoadingManager = new LoadingManager();
30567
30568/**
30569 * @author mrdoob / http://mrdoob.com/
30570 */
30571
30572var loading = {};
30573
30574function FileLoader( manager ) {
30575
30576 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
30577
30578}
30579
30580Object.assign( FileLoader.prototype, {
30581
30582 load: function ( url, onLoad, onProgress, onError ) {
30583
30584 if ( url === undefined ) url = '';
30585
30586 if ( this.path !== undefined ) url = this.path + url;
30587
30588 url = this.manager.resolveURL( url );
30589
30590 var scope = this;
30591
30592 var cached = Cache.get( url );
30593
30594 if ( cached !== undefined ) {
30595
30596 scope.manager.itemStart( url );
30597
30598 setTimeout( function () {
30599
30600 if ( onLoad ) onLoad( cached );
30601
30602 scope.manager.itemEnd( url );
30603
30604 }, 0 );
30605
30606 return cached;
30607
30608 }
30609
30610 // Check if request is duplicate
30611
30612 if ( loading[ url ] !== undefined ) {
30613
30614 loading[ url ].push( {
30615
30616 onLoad: onLoad,
30617 onProgress: onProgress,
30618 onError: onError
30619
30620 } );
30621
30622 return;
30623
30624 }
30625
30626 // Check for data: URI
30627 var dataUriRegex = /^data:(.*?)(;base64)?,(.*)$/;
30628 var dataUriRegexResult = url.match( dataUriRegex );
30629
30630 // Safari can not handle Data URIs through XMLHttpRequest so process manually
30631 if ( dataUriRegexResult ) {
30632
30633 var mimeType = dataUriRegexResult[ 1 ];
30634 var isBase64 = !! dataUriRegexResult[ 2 ];
30635 var data = dataUriRegexResult[ 3 ];
30636
30637 data = window.decodeURIComponent( data );
30638
30639 if ( isBase64 ) data = window.atob( data );
30640
30641 try {
30642
30643 var response;
30644 var responseType = ( this.responseType || '' ).toLowerCase();
30645
30646 switch ( responseType ) {
30647
30648 case 'arraybuffer':
30649 case 'blob':
30650
30651 var view = new Uint8Array( data.length );
30652
30653 for ( var i = 0; i < data.length; i ++ ) {
30654
30655 view[ i ] = data.charCodeAt( i );
30656
30657 }
30658
30659 if ( responseType === 'blob' ) {
30660
30661 response = new Blob( [ view.buffer ], { type: mimeType } );
30662
30663 } else {
30664
30665 response = view.buffer;
30666
30667 }
30668
30669 break;
30670
30671 case 'document':
30672
30673 var parser = new DOMParser();
30674 response = parser.parseFromString( data, mimeType );
30675
30676 break;
30677
30678 case 'json':
30679
30680 response = JSON.parse( data );
30681
30682 break;
30683
30684 default: // 'text' or other
30685
30686 response = data;
30687
30688 break;
30689
30690 }
30691
30692 // Wait for next browser tick like standard XMLHttpRequest event dispatching does
30693 window.setTimeout( function () {
30694
30695 if ( onLoad ) onLoad( response );
30696
30697 scope.manager.itemEnd( url );
30698
30699 }, 0 );
30700
30701 } catch ( error ) {
30702
30703 // Wait for next browser tick like standard XMLHttpRequest event dispatching does
30704 window.setTimeout( function () {
30705
30706 if ( onError ) onError( error );
30707
30708 scope.manager.itemEnd( url );
30709 scope.manager.itemError( url );
30710
30711 }, 0 );
30712
30713 }
30714
30715 } else {
30716
30717 // Initialise array for duplicate requests
30718
30719 loading[ url ] = [];
30720
30721 loading[ url ].push( {
30722
30723 onLoad: onLoad,
30724 onProgress: onProgress,
30725 onError: onError
30726
30727 } );
30728
30729 var request = new XMLHttpRequest();
30730
30731 request.open( 'GET', url, true );
30732
30733 request.addEventListener( 'load', function ( event ) {
30734
30735 var response = this.response;
30736
30737 Cache.add( url, response );
30738
30739 var callbacks = loading[ url ];
30740
30741 delete loading[ url ];
30742
30743 if ( this.status === 200 ) {
30744
30745 for ( var i = 0, il = callbacks.length; i < il; i ++ ) {
30746
30747 var callback = callbacks[ i ];
30748 if ( callback.onLoad ) callback.onLoad( response );
30749
30750 }
30751
30752 scope.manager.itemEnd( url );
30753
30754 } else if ( this.status === 0 ) {
30755
30756 // Some browsers return HTTP Status 0 when using non-http protocol
30757 // e.g. 'file://' or 'data://'. Handle as success.
30758
30759 console.warn( 'THREE.FileLoader: HTTP Status 0 received.' );
30760
30761 for ( var i = 0, il = callbacks.length; i < il; i ++ ) {
30762
30763 var callback = callbacks[ i ];
30764 if ( callback.onLoad ) callback.onLoad( response );
30765
30766 }
30767
30768 scope.manager.itemEnd( url );
30769
30770 } else {
30771
30772 for ( var i = 0, il = callbacks.length; i < il; i ++ ) {
30773
30774 var callback = callbacks[ i ];
30775 if ( callback.onError ) callback.onError( event );
30776
30777 }
30778
30779 scope.manager.itemEnd( url );
30780 scope.manager.itemError( url );
30781
30782 }
30783
30784 }, false );
30785
30786 request.addEventListener( 'progress', function ( event ) {
30787
30788 var callbacks = loading[ url ];
30789
30790 for ( var i = 0, il = callbacks.length; i < il; i ++ ) {
30791
30792 var callback = callbacks[ i ];
30793 if ( callback.onProgress ) callback.onProgress( event );
30794
30795 }
30796
30797 }, false );
30798
30799 request.addEventListener( 'error', function ( event ) {
30800
30801 var callbacks = loading[ url ];
30802
30803 delete loading[ url ];
30804
30805 for ( var i = 0, il = callbacks.length; i < il; i ++ ) {
30806
30807 var callback = callbacks[ i ];
30808 if ( callback.onError ) callback.onError( event );
30809
30810 }
30811
30812 scope.manager.itemEnd( url );
30813 scope.manager.itemError( url );
30814
30815 }, false );
30816
30817 if ( this.responseType !== undefined ) request.responseType = this.responseType;
30818 if ( this.withCredentials !== undefined ) request.withCredentials = this.withCredentials;
30819
30820 if ( request.overrideMimeType ) request.overrideMimeType( this.mimeType !== undefined ? this.mimeType : 'text/plain' );
30821
30822 for ( var header in this.requestHeader ) {
30823
30824 request.setRequestHeader( header, this.requestHeader[ header ] );
30825
30826 }
30827
30828 request.send( null );
30829
30830 }
30831
30832 scope.manager.itemStart( url );
30833
30834 return request;
30835
30836 },
30837
30838 setPath: function ( value ) {
30839
30840 this.path = value;
30841 return this;
30842
30843 },
30844
30845 setResponseType: function ( value ) {
30846
30847 this.responseType = value;
30848 return this;
30849
30850 },
30851
30852 setWithCredentials: function ( value ) {
30853
30854 this.withCredentials = value;
30855 return this;
30856
30857 },
30858
30859 setMimeType: function ( value ) {
30860
30861 this.mimeType = value;
30862 return this;
30863
30864 },
30865
30866 setRequestHeader: function ( value ) {
30867
30868 this.requestHeader = value;
30869 return this;
30870
30871 }
30872
30873} );
30874
30875/**
30876 * @author mrdoob / http://mrdoob.com/
30877 *
30878 * Abstract Base class to block based textures loader (dds, pvr, ...)
30879 */
30880
30881function CompressedTextureLoader( manager ) {
30882
30883 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
30884
30885 // override in sub classes
30886 this._parser = null;
30887
30888}
30889
30890Object.assign( CompressedTextureLoader.prototype, {
30891
30892 load: function ( url, onLoad, onProgress, onError ) {
30893
30894 var scope = this;
30895
30896 var images = [];
30897
30898 var texture = new CompressedTexture();
30899 texture.image = images;
30900
30901 var loader = new FileLoader( this.manager );
30902 loader.setPath( this.path );
30903 loader.setResponseType( 'arraybuffer' );
30904
30905 function loadTexture( i ) {
30906
30907 loader.load( url[ i ], function ( buffer ) {
30908
30909 var texDatas = scope._parser( buffer, true );
30910
30911 images[ i ] = {
30912 width: texDatas.width,
30913 height: texDatas.height,
30914 format: texDatas.format,
30915 mipmaps: texDatas.mipmaps
30916 };
30917
30918 loaded += 1;
30919
30920 if ( loaded === 6 ) {
30921
30922 if ( texDatas.mipmapCount === 1 )
30923 texture.minFilter = LinearFilter;
30924
30925 texture.format = texDatas.format;
30926 texture.needsUpdate = true;
30927
30928 if ( onLoad ) onLoad( texture );
30929
30930 }
30931
30932 }, onProgress, onError );
30933
30934 }
30935
30936 if ( Array.isArray( url ) ) {
30937
30938 var loaded = 0;
30939
30940 for ( var i = 0, il = url.length; i < il; ++ i ) {
30941
30942 loadTexture( i );
30943
30944 }
30945
30946 } else {
30947
30948 // compressed cubemap texture stored in a single DDS file
30949
30950 loader.load( url, function ( buffer ) {
30951
30952 var texDatas = scope._parser( buffer, true );
30953
30954 if ( texDatas.isCubemap ) {
30955
30956 var faces = texDatas.mipmaps.length / texDatas.mipmapCount;
30957
30958 for ( var f = 0; f < faces; f ++ ) {
30959
30960 images[ f ] = { mipmaps: [] };
30961
30962 for ( var i = 0; i < texDatas.mipmapCount; i ++ ) {
30963
30964 images[ f ].mipmaps.push( texDatas.mipmaps[ f * texDatas.mipmapCount + i ] );
30965 images[ f ].format = texDatas.format;
30966 images[ f ].width = texDatas.width;
30967 images[ f ].height = texDatas.height;
30968
30969 }
30970
30971 }
30972
30973 } else {
30974
30975 texture.image.width = texDatas.width;
30976 texture.image.height = texDatas.height;
30977 texture.mipmaps = texDatas.mipmaps;
30978
30979 }
30980
30981 if ( texDatas.mipmapCount === 1 ) {
30982
30983 texture.minFilter = LinearFilter;
30984
30985 }
30986
30987 texture.format = texDatas.format;
30988 texture.needsUpdate = true;
30989
30990 if ( onLoad ) onLoad( texture );
30991
30992 }, onProgress, onError );
30993
30994 }
30995
30996 return texture;
30997
30998 },
30999
31000 setPath: function ( value ) {
31001
31002 this.path = value;
31003 return this;
31004
31005 }
31006
31007} );
31008
31009/**
31010 * @author Nikos M. / https://github.com/foo123/
31011 *
31012 * Abstract Base class to load generic binary textures formats (rgbe, hdr, ...)
31013 */
31014
31015function DataTextureLoader( manager ) {
31016
31017 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
31018
31019 // override in sub classes
31020 this._parser = null;
31021
31022}
31023
31024Object.assign( DataTextureLoader.prototype, {
31025
31026 load: function ( url, onLoad, onProgress, onError ) {
31027
31028 var scope = this;
31029
31030 var texture = new DataTexture();
31031
31032 var loader = new FileLoader( this.manager );
31033 loader.setResponseType( 'arraybuffer' );
31034
31035 loader.load( url, function ( buffer ) {
31036
31037 var texData = scope._parser( buffer );
31038
31039 if ( ! texData ) return;
31040
31041 if ( undefined !== texData.image ) {
31042
31043 texture.image = texData.image;
31044
31045 } else if ( undefined !== texData.data ) {
31046
31047 texture.image.width = texData.width;
31048 texture.image.height = texData.height;
31049 texture.image.data = texData.data;
31050
31051 }
31052
31053 texture.wrapS = undefined !== texData.wrapS ? texData.wrapS : ClampToEdgeWrapping;
31054 texture.wrapT = undefined !== texData.wrapT ? texData.wrapT : ClampToEdgeWrapping;
31055
31056 texture.magFilter = undefined !== texData.magFilter ? texData.magFilter : LinearFilter;
31057 texture.minFilter = undefined !== texData.minFilter ? texData.minFilter : LinearMipMapLinearFilter;
31058
31059 texture.anisotropy = undefined !== texData.anisotropy ? texData.anisotropy : 1;
31060
31061 if ( undefined !== texData.format ) {
31062
31063 texture.format = texData.format;
31064
31065 }
31066 if ( undefined !== texData.type ) {
31067
31068 texture.type = texData.type;
31069
31070 }
31071
31072 if ( undefined !== texData.mipmaps ) {
31073
31074 texture.mipmaps = texData.mipmaps;
31075
31076 }
31077
31078 if ( 1 === texData.mipmapCount ) {
31079
31080 texture.minFilter = LinearFilter;
31081
31082 }
31083
31084 texture.needsUpdate = true;
31085
31086 if ( onLoad ) onLoad( texture, texData );
31087
31088 }, onProgress, onError );
31089
31090
31091 return texture;
31092
31093 }
31094
31095} );
31096
31097/**
31098 * @author mrdoob / http://mrdoob.com/
31099 */
31100
31101function ImageLoader( manager ) {
31102
31103 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
31104
31105}
31106
31107Object.assign( ImageLoader.prototype, {
31108
31109 crossOrigin: 'Anonymous',
31110
31111 load: function ( url, onLoad, onProgress, onError ) {
31112
31113 if ( url === undefined ) url = '';
31114
31115 if ( this.path !== undefined ) url = this.path + url;
31116
31117 url = this.manager.resolveURL( url );
31118
31119 var scope = this;
31120
31121 var cached = Cache.get( url );
31122
31123 if ( cached !== undefined ) {
31124
31125 scope.manager.itemStart( url );
31126
31127 setTimeout( function () {
31128
31129 if ( onLoad ) onLoad( cached );
31130
31131 scope.manager.itemEnd( url );
31132
31133 }, 0 );
31134
31135 return cached;
31136
31137 }
31138
31139 var image = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'img' );
31140
31141 image.addEventListener( 'load', function () {
31142
31143 Cache.add( url, this );
31144
31145 if ( onLoad ) onLoad( this );
31146
31147 scope.manager.itemEnd( url );
31148
31149 }, false );
31150
31151 /*
31152 image.addEventListener( 'progress', function ( event ) {
31153
31154 if ( onProgress ) onProgress( event );
31155
31156 }, false );
31157 */
31158
31159 image.addEventListener( 'error', function ( event ) {
31160
31161 if ( onError ) onError( event );
31162
31163 scope.manager.itemEnd( url );
31164 scope.manager.itemError( url );
31165
31166 }, false );
31167
31168 if ( url.substr( 0, 5 ) !== 'data:' ) {
31169
31170 if ( this.crossOrigin !== undefined ) image.crossOrigin = this.crossOrigin;
31171
31172 }
31173
31174 scope.manager.itemStart( url );
31175
31176 image.src = url;
31177
31178 return image;
31179
31180 },
31181
31182 setCrossOrigin: function ( value ) {
31183
31184 this.crossOrigin = value;
31185 return this;
31186
31187 },
31188
31189 setPath: function ( value ) {
31190
31191 this.path = value;
31192 return this;
31193
31194 }
31195
31196} );
31197
31198/**
31199 * @author mrdoob / http://mrdoob.com/
31200 */
31201
31202function CubeTextureLoader( manager ) {
31203
31204 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
31205
31206}
31207
31208Object.assign( CubeTextureLoader.prototype, {
31209
31210 crossOrigin: 'Anonymous',
31211
31212 load: function ( urls, onLoad, onProgress, onError ) {
31213
31214 var texture = new CubeTexture();
31215
31216 var loader = new ImageLoader( this.manager );
31217 loader.setCrossOrigin( this.crossOrigin );
31218 loader.setPath( this.path );
31219
31220 var loaded = 0;
31221
31222 function loadTexture( i ) {
31223
31224 loader.load( urls[ i ], function ( image ) {
31225
31226 texture.images[ i ] = image;
31227
31228 loaded ++;
31229
31230 if ( loaded === 6 ) {
31231
31232 texture.needsUpdate = true;
31233
31234 if ( onLoad ) onLoad( texture );
31235
31236 }
31237
31238 }, undefined, onError );
31239
31240 }
31241
31242 for ( var i = 0; i < urls.length; ++ i ) {
31243
31244 loadTexture( i );
31245
31246 }
31247
31248 return texture;
31249
31250 },
31251
31252 setCrossOrigin: function ( value ) {
31253
31254 this.crossOrigin = value;
31255 return this;
31256
31257 },
31258
31259 setPath: function ( value ) {
31260
31261 this.path = value;
31262 return this;
31263
31264 }
31265
31266} );
31267
31268/**
31269 * @author mrdoob / http://mrdoob.com/
31270 */
31271
31272function TextureLoader( manager ) {
31273
31274 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
31275
31276}
31277
31278Object.assign( TextureLoader.prototype, {
31279
31280 crossOrigin: 'Anonymous',
31281
31282 load: function ( url, onLoad, onProgress, onError ) {
31283
31284 var texture = new Texture();
31285
31286 var loader = new ImageLoader( this.manager );
31287 loader.setCrossOrigin( this.crossOrigin );
31288 loader.setPath( this.path );
31289
31290 loader.load( url, function ( image ) {
31291
31292 texture.image = image;
31293
31294 // JPEGs can't have an alpha channel, so memory can be saved by storing them as RGB.
31295 var isJPEG = url.search( /\.(jpg|jpeg)$/ ) > 0 || url.search( /^data\:image\/jpeg/ ) === 0;
31296
31297 texture.format = isJPEG ? RGBFormat : RGBAFormat;
31298 texture.needsUpdate = true;
31299
31300 if ( onLoad !== undefined ) {
31301
31302 onLoad( texture );
31303
31304 }
31305
31306 }, onProgress, onError );
31307
31308 return texture;
31309
31310 },
31311
31312 setCrossOrigin: function ( value ) {
31313
31314 this.crossOrigin = value;
31315 return this;
31316
31317 },
31318
31319 setPath: function ( value ) {
31320
31321 this.path = value;
31322 return this;
31323
31324 }
31325
31326} );
31327
31328/**
31329 * @author zz85 / http://www.lab4games.net/zz85/blog
31330 * Extensible curve object
31331 *
31332 * Some common of curve methods:
31333 * .getPoint( t, optionalTarget ), .getTangent( t )
31334 * .getPointAt( u, optionalTarget ), .getTangentAt( u )
31335 * .getPoints(), .getSpacedPoints()
31336 * .getLength()
31337 * .updateArcLengths()
31338 *
31339 * This following curves inherit from THREE.Curve:
31340 *
31341 * -- 2D curves --
31342 * THREE.ArcCurve
31343 * THREE.CubicBezierCurve
31344 * THREE.EllipseCurve
31345 * THREE.LineCurve
31346 * THREE.QuadraticBezierCurve
31347 * THREE.SplineCurve
31348 *
31349 * -- 3D curves --
31350 * THREE.CatmullRomCurve3
31351 * THREE.CubicBezierCurve3
31352 * THREE.LineCurve3
31353 * THREE.QuadraticBezierCurve3
31354 *
31355 * A series of curves can be represented as a THREE.CurvePath.
31356 *
31357 **/
31358
31359/**************************************************************
31360 * Abstract Curve base class
31361 **************************************************************/
31362
31363function Curve() {
31364
31365 this.type = 'Curve';
31366
31367 this.arcLengthDivisions = 200;
31368
31369}
31370
31371Object.assign( Curve.prototype, {
31372
31373 // Virtual base class method to overwrite and implement in subclasses
31374 // - t [0 .. 1]
31375
31376 getPoint: function ( /* t, optionalTarget */ ) {
31377
31378 console.warn( 'THREE.Curve: .getPoint() not implemented.' );
31379 return null;
31380
31381 },
31382
31383 // Get point at relative position in curve according to arc length
31384 // - u [0 .. 1]
31385
31386 getPointAt: function ( u, optionalTarget ) {
31387
31388 var t = this.getUtoTmapping( u );
31389 return this.getPoint( t, optionalTarget );
31390
31391 },
31392
31393 // Get sequence of points using getPoint( t )
31394
31395 getPoints: function ( divisions ) {
31396
31397 if ( divisions === undefined ) divisions = 5;
31398
31399 var points = [];
31400
31401 for ( var d = 0; d <= divisions; d ++ ) {
31402
31403 points.push( this.getPoint( d / divisions ) );
31404
31405 }
31406
31407 return points;
31408
31409 },
31410
31411 // Get sequence of points using getPointAt( u )
31412
31413 getSpacedPoints: function ( divisions ) {
31414
31415 if ( divisions === undefined ) divisions = 5;
31416
31417 var points = [];
31418
31419 for ( var d = 0; d <= divisions; d ++ ) {
31420
31421 points.push( this.getPointAt( d / divisions ) );
31422
31423 }
31424
31425 return points;
31426
31427 },
31428
31429 // Get total curve arc length
31430
31431 getLength: function () {
31432
31433 var lengths = this.getLengths();
31434 return lengths[ lengths.length - 1 ];
31435
31436 },
31437
31438 // Get list of cumulative segment lengths
31439
31440 getLengths: function ( divisions ) {
31441
31442 if ( divisions === undefined ) divisions = this.arcLengthDivisions;
31443
31444 if ( this.cacheArcLengths &&
31445 ( this.cacheArcLengths.length === divisions + 1 ) &&
31446 ! this.needsUpdate ) {
31447
31448 return this.cacheArcLengths;
31449
31450 }
31451
31452 this.needsUpdate = false;
31453
31454 var cache = [];
31455 var current, last = this.getPoint( 0 );
31456 var p, sum = 0;
31457
31458 cache.push( 0 );
31459
31460 for ( p = 1; p <= divisions; p ++ ) {
31461
31462 current = this.getPoint( p / divisions );
31463 sum += current.distanceTo( last );
31464 cache.push( sum );
31465 last = current;
31466
31467 }
31468
31469 this.cacheArcLengths = cache;
31470
31471 return cache; // { sums: cache, sum: sum }; Sum is in the last element.
31472
31473 },
31474
31475 updateArcLengths: function () {
31476
31477 this.needsUpdate = true;
31478 this.getLengths();
31479
31480 },
31481
31482 // Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equidistant
31483
31484 getUtoTmapping: function ( u, distance ) {
31485
31486 var arcLengths = this.getLengths();
31487
31488 var i = 0, il = arcLengths.length;
31489
31490 var targetArcLength; // The targeted u distance value to get
31491
31492 if ( distance ) {
31493
31494 targetArcLength = distance;
31495
31496 } else {
31497
31498 targetArcLength = u * arcLengths[ il - 1 ];
31499
31500 }
31501
31502 // binary search for the index with largest value smaller than target u distance
31503
31504 var low = 0, high = il - 1, comparison;
31505
31506 while ( low <= high ) {
31507
31508 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
31509
31510 comparison = arcLengths[ i ] - targetArcLength;
31511
31512 if ( comparison < 0 ) {
31513
31514 low = i + 1;
31515
31516 } else if ( comparison > 0 ) {
31517
31518 high = i - 1;
31519
31520 } else {
31521
31522 high = i;
31523 break;
31524
31525 // DONE
31526
31527 }
31528
31529 }
31530
31531 i = high;
31532
31533 if ( arcLengths[ i ] === targetArcLength ) {
31534
31535 return i / ( il - 1 );
31536
31537 }
31538
31539 // we could get finer grain at lengths, or use simple interpolation between two points
31540
31541 var lengthBefore = arcLengths[ i ];
31542 var lengthAfter = arcLengths[ i + 1 ];
31543
31544 var segmentLength = lengthAfter - lengthBefore;
31545
31546 // determine where we are between the 'before' and 'after' points
31547
31548 var segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength;
31549
31550 // add that fractional amount to t
31551
31552 var t = ( i + segmentFraction ) / ( il - 1 );
31553
31554 return t;
31555
31556 },
31557
31558 // Returns a unit vector tangent at t
31559 // In case any sub curve does not implement its tangent derivation,
31560 // 2 points a small delta apart will be used to find its gradient
31561 // which seems to give a reasonable approximation
31562
31563 getTangent: function ( t ) {
31564
31565 var delta = 0.0001;
31566 var t1 = t - delta;
31567 var t2 = t + delta;
31568
31569 // Capping in case of danger
31570
31571 if ( t1 < 0 ) t1 = 0;
31572 if ( t2 > 1 ) t2 = 1;
31573
31574 var pt1 = this.getPoint( t1 );
31575 var pt2 = this.getPoint( t2 );
31576
31577 var vec = pt2.clone().sub( pt1 );
31578 return vec.normalize();
31579
31580 },
31581
31582 getTangentAt: function ( u ) {
31583
31584 var t = this.getUtoTmapping( u );
31585 return this.getTangent( t );
31586
31587 },
31588
31589 computeFrenetFrames: function ( segments, closed ) {
31590
31591 // see http://www.cs.indiana.edu/pub/techreports/TR425.pdf
31592
31593 var normal = new Vector3();
31594
31595 var tangents = [];
31596 var normals = [];
31597 var binormals = [];
31598
31599 var vec = new Vector3();
31600 var mat = new Matrix4();
31601
31602 var i, u, theta;
31603
31604 // compute the tangent vectors for each segment on the curve
31605
31606 for ( i = 0; i <= segments; i ++ ) {
31607
31608 u = i / segments;
31609
31610 tangents[ i ] = this.getTangentAt( u );
31611 tangents[ i ].normalize();
31612
31613 }
31614
31615 // select an initial normal vector perpendicular to the first tangent vector,
31616 // and in the direction of the minimum tangent xyz component
31617
31618 normals[ 0 ] = new Vector3();
31619 binormals[ 0 ] = new Vector3();
31620 var min = Number.MAX_VALUE;
31621 var tx = Math.abs( tangents[ 0 ].x );
31622 var ty = Math.abs( tangents[ 0 ].y );
31623 var tz = Math.abs( tangents[ 0 ].z );
31624
31625 if ( tx <= min ) {
31626
31627 min = tx;
31628 normal.set( 1, 0, 0 );
31629
31630 }
31631
31632 if ( ty <= min ) {
31633
31634 min = ty;
31635 normal.set( 0, 1, 0 );
31636
31637 }
31638
31639 if ( tz <= min ) {
31640
31641 normal.set( 0, 0, 1 );
31642
31643 }
31644
31645 vec.crossVectors( tangents[ 0 ], normal ).normalize();
31646
31647 normals[ 0 ].crossVectors( tangents[ 0 ], vec );
31648 binormals[ 0 ].crossVectors( tangents[ 0 ], normals[ 0 ] );
31649
31650
31651 // compute the slowly-varying normal and binormal vectors for each segment on the curve
31652
31653 for ( i = 1; i <= segments; i ++ ) {
31654
31655 normals[ i ] = normals[ i - 1 ].clone();
31656
31657 binormals[ i ] = binormals[ i - 1 ].clone();
31658
31659 vec.crossVectors( tangents[ i - 1 ], tangents[ i ] );
31660
31661 if ( vec.length() > Number.EPSILON ) {
31662
31663 vec.normalize();
31664
31665 theta = Math.acos( _Math.clamp( tangents[ i - 1 ].dot( tangents[ i ] ), - 1, 1 ) ); // clamp for floating pt errors
31666
31667 normals[ i ].applyMatrix4( mat.makeRotationAxis( vec, theta ) );
31668
31669 }
31670
31671 binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
31672
31673 }
31674
31675 // if the curve is closed, postprocess the vectors so the first and last normal vectors are the same
31676
31677 if ( closed === true ) {
31678
31679 theta = Math.acos( _Math.clamp( normals[ 0 ].dot( normals[ segments ] ), - 1, 1 ) );
31680 theta /= segments;
31681
31682 if ( tangents[ 0 ].dot( vec.crossVectors( normals[ 0 ], normals[ segments ] ) ) > 0 ) {
31683
31684 theta = - theta;
31685
31686 }
31687
31688 for ( i = 1; i <= segments; i ++ ) {
31689
31690 // twist a little...
31691 normals[ i ].applyMatrix4( mat.makeRotationAxis( tangents[ i ], theta * i ) );
31692 binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
31693
31694 }
31695
31696 }
31697
31698 return {
31699 tangents: tangents,
31700 normals: normals,
31701 binormals: binormals
31702 };
31703
31704 },
31705
31706 clone: function () {
31707
31708 return new this.constructor().copy( this );
31709
31710 },
31711
31712 copy: function ( source ) {
31713
31714 this.arcLengthDivisions = source.arcLengthDivisions;
31715
31716 return this;
31717
31718 },
31719
31720 toJSON: function () {
31721
31722 var data = {
31723 metadata: {
31724 version: 4.5,
31725 type: 'Curve',
31726 generator: 'Curve.toJSON'
31727 }
31728 };
31729
31730 data.arcLengthDivisions = this.arcLengthDivisions;
31731 data.type = this.type;
31732
31733 return data;
31734
31735 },
31736
31737 fromJSON: function ( json ) {
31738
31739 this.arcLengthDivisions = json.arcLengthDivisions;
31740
31741 return this;
31742
31743 }
31744
31745} );
31746
31747function EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
31748
31749 Curve.call( this );
31750
31751 this.type = 'EllipseCurve';
31752
31753 this.aX = aX || 0;
31754 this.aY = aY || 0;
31755
31756 this.xRadius = xRadius || 1;
31757 this.yRadius = yRadius || 1;
31758
31759 this.aStartAngle = aStartAngle || 0;
31760 this.aEndAngle = aEndAngle || 2 * Math.PI;
31761
31762 this.aClockwise = aClockwise || false;
31763
31764 this.aRotation = aRotation || 0;
31765
31766}
31767
31768EllipseCurve.prototype = Object.create( Curve.prototype );
31769EllipseCurve.prototype.constructor = EllipseCurve;
31770
31771EllipseCurve.prototype.isEllipseCurve = true;
31772
31773EllipseCurve.prototype.getPoint = function ( t, optionalTarget ) {
31774
31775 var point = optionalTarget || new Vector2();
31776
31777 var twoPi = Math.PI * 2;
31778 var deltaAngle = this.aEndAngle - this.aStartAngle;
31779 var samePoints = Math.abs( deltaAngle ) < Number.EPSILON;
31780
31781 // ensures that deltaAngle is 0 .. 2 PI
31782 while ( deltaAngle < 0 ) deltaAngle += twoPi;
31783 while ( deltaAngle > twoPi ) deltaAngle -= twoPi;
31784
31785 if ( deltaAngle < Number.EPSILON ) {
31786
31787 if ( samePoints ) {
31788
31789 deltaAngle = 0;
31790
31791 } else {
31792
31793 deltaAngle = twoPi;
31794
31795 }
31796
31797 }
31798
31799 if ( this.aClockwise === true && ! samePoints ) {
31800
31801 if ( deltaAngle === twoPi ) {
31802
31803 deltaAngle = - twoPi;
31804
31805 } else {
31806
31807 deltaAngle = deltaAngle - twoPi;
31808
31809 }
31810
31811 }
31812
31813 var angle = this.aStartAngle + t * deltaAngle;
31814 var x = this.aX + this.xRadius * Math.cos( angle );
31815 var y = this.aY + this.yRadius * Math.sin( angle );
31816
31817 if ( this.aRotation !== 0 ) {
31818
31819 var cos = Math.cos( this.aRotation );
31820 var sin = Math.sin( this.aRotation );
31821
31822 var tx = x - this.aX;
31823 var ty = y - this.aY;
31824
31825 // Rotate the point about the center of the ellipse.
31826 x = tx * cos - ty * sin + this.aX;
31827 y = tx * sin + ty * cos + this.aY;
31828
31829 }
31830
31831 return point.set( x, y );
31832
31833};
31834
31835EllipseCurve.prototype.copy = function ( source ) {
31836
31837 Curve.prototype.copy.call( this, source );
31838
31839 this.aX = source.aX;
31840 this.aY = source.aY;
31841
31842 this.xRadius = source.xRadius;
31843 this.yRadius = source.yRadius;
31844
31845 this.aStartAngle = source.aStartAngle;
31846 this.aEndAngle = source.aEndAngle;
31847
31848 this.aClockwise = source.aClockwise;
31849
31850 this.aRotation = source.aRotation;
31851
31852 return this;
31853
31854};
31855
31856
31857EllipseCurve.prototype.toJSON = function () {
31858
31859 var data = Curve.prototype.toJSON.call( this );
31860
31861 data.aX = this.aX;
31862 data.aY = this.aY;
31863
31864 data.xRadius = this.xRadius;
31865 data.yRadius = this.yRadius;
31866
31867 data.aStartAngle = this.aStartAngle;
31868 data.aEndAngle = this.aEndAngle;
31869
31870 data.aClockwise = this.aClockwise;
31871
31872 data.aRotation = this.aRotation;
31873
31874 return data;
31875
31876};
31877
31878EllipseCurve.prototype.fromJSON = function ( json ) {
31879
31880 Curve.prototype.fromJSON.call( this, json );
31881
31882 this.aX = json.aX;
31883 this.aY = json.aY;
31884
31885 this.xRadius = json.xRadius;
31886 this.yRadius = json.yRadius;
31887
31888 this.aStartAngle = json.aStartAngle;
31889 this.aEndAngle = json.aEndAngle;
31890
31891 this.aClockwise = json.aClockwise;
31892
31893 this.aRotation = json.aRotation;
31894
31895 return this;
31896
31897};
31898
31899function ArcCurve( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
31900
31901 EllipseCurve.call( this, aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
31902
31903 this.type = 'ArcCurve';
31904
31905}
31906
31907ArcCurve.prototype = Object.create( EllipseCurve.prototype );
31908ArcCurve.prototype.constructor = ArcCurve;
31909
31910ArcCurve.prototype.isArcCurve = true;
31911
31912/**
31913 * @author zz85 https://github.com/zz85
31914 *
31915 * Centripetal CatmullRom Curve - which is useful for avoiding
31916 * cusps and self-intersections in non-uniform catmull rom curves.
31917 * http://www.cemyuksel.com/research/catmullrom_param/catmullrom.pdf
31918 *
31919 * curve.type accepts centripetal(default), chordal and catmullrom
31920 * curve.tension is used for catmullrom which defaults to 0.5
31921 */
31922
31923
31924/*
31925Based on an optimized c++ solution in
31926 - http://stackoverflow.com/questions/9489736/catmull-rom-curve-with-no-cusps-and-no-self-intersections/
31927 - http://ideone.com/NoEbVM
31928
31929This CubicPoly class could be used for reusing some variables and calculations,
31930but for three.js curve use, it could be possible inlined and flatten into a single function call
31931which can be placed in CurveUtils.
31932*/
31933
31934function CubicPoly() {
31935
31936 var c0 = 0, c1 = 0, c2 = 0, c3 = 0;
31937
31938 /*
31939 * Compute coefficients for a cubic polynomial
31940 * p(s) = c0 + c1*s + c2*s^2 + c3*s^3
31941 * such that
31942 * p(0) = x0, p(1) = x1
31943 * and
31944 * p'(0) = t0, p'(1) = t1.
31945 */
31946 function init( x0, x1, t0, t1 ) {
31947
31948 c0 = x0;
31949 c1 = t0;
31950 c2 = - 3 * x0 + 3 * x1 - 2 * t0 - t1;
31951 c3 = 2 * x0 - 2 * x1 + t0 + t1;
31952
31953 }
31954
31955 return {
31956
31957 initCatmullRom: function ( x0, x1, x2, x3, tension ) {
31958
31959 init( x1, x2, tension * ( x2 - x0 ), tension * ( x3 - x1 ) );
31960
31961 },
31962
31963 initNonuniformCatmullRom: function ( x0, x1, x2, x3, dt0, dt1, dt2 ) {
31964
31965 // compute tangents when parameterized in [t1,t2]
31966 var t1 = ( x1 - x0 ) / dt0 - ( x2 - x0 ) / ( dt0 + dt1 ) + ( x2 - x1 ) / dt1;
31967 var t2 = ( x2 - x1 ) / dt1 - ( x3 - x1 ) / ( dt1 + dt2 ) + ( x3 - x2 ) / dt2;
31968
31969 // rescale tangents for parametrization in [0,1]
31970 t1 *= dt1;
31971 t2 *= dt1;
31972
31973 init( x1, x2, t1, t2 );
31974
31975 },
31976
31977 calc: function ( t ) {
31978
31979 var t2 = t * t;
31980 var t3 = t2 * t;
31981 return c0 + c1 * t + c2 * t2 + c3 * t3;
31982
31983 }
31984
31985 };
31986
31987}
31988
31989//
31990
31991var tmp = new Vector3();
31992var px = new CubicPoly();
31993var py = new CubicPoly();
31994var pz = new CubicPoly();
31995
31996function CatmullRomCurve3( points, closed, curveType, tension ) {
31997
31998 Curve.call( this );
31999
32000 this.type = 'CatmullRomCurve3';
32001
32002 this.points = points || [];
32003 this.closed = closed || false;
32004 this.curveType = curveType || 'centripetal';
32005 this.tension = tension || 0.5;
32006
32007}
32008
32009CatmullRomCurve3.prototype = Object.create( Curve.prototype );
32010CatmullRomCurve3.prototype.constructor = CatmullRomCurve3;
32011
32012CatmullRomCurve3.prototype.isCatmullRomCurve3 = true;
32013
32014CatmullRomCurve3.prototype.getPoint = function ( t, optionalTarget ) {
32015
32016 var point = optionalTarget || new Vector3();
32017
32018 var points = this.points;
32019 var l = points.length;
32020
32021 var p = ( l - ( this.closed ? 0 : 1 ) ) * t;
32022 var intPoint = Math.floor( p );
32023 var weight = p - intPoint;
32024
32025 if ( this.closed ) {
32026
32027 intPoint += intPoint > 0 ? 0 : ( Math.floor( Math.abs( intPoint ) / l ) + 1 ) * l;
32028
32029 } else if ( weight === 0 && intPoint === l - 1 ) {
32030
32031 intPoint = l - 2;
32032 weight = 1;
32033
32034 }
32035
32036 var p0, p1, p2, p3; // 4 points
32037
32038 if ( this.closed || intPoint > 0 ) {
32039
32040 p0 = points[ ( intPoint - 1 ) % l ];
32041
32042 } else {
32043
32044 // extrapolate first point
32045 tmp.subVectors( points[ 0 ], points[ 1 ] ).add( points[ 0 ] );
32046 p0 = tmp;
32047
32048 }
32049
32050 p1 = points[ intPoint % l ];
32051 p2 = points[ ( intPoint + 1 ) % l ];
32052
32053 if ( this.closed || intPoint + 2 < l ) {
32054
32055 p3 = points[ ( intPoint + 2 ) % l ];
32056
32057 } else {
32058
32059 // extrapolate last point
32060 tmp.subVectors( points[ l - 1 ], points[ l - 2 ] ).add( points[ l - 1 ] );
32061 p3 = tmp;
32062
32063 }
32064
32065 if ( this.curveType === 'centripetal' || this.curveType === 'chordal' ) {
32066
32067 // init Centripetal / Chordal Catmull-Rom
32068 var pow = this.curveType === 'chordal' ? 0.5 : 0.25;
32069 var dt0 = Math.pow( p0.distanceToSquared( p1 ), pow );
32070 var dt1 = Math.pow( p1.distanceToSquared( p2 ), pow );
32071 var dt2 = Math.pow( p2.distanceToSquared( p3 ), pow );
32072
32073 // safety check for repeated points
32074 if ( dt1 < 1e-4 ) dt1 = 1.0;
32075 if ( dt0 < 1e-4 ) dt0 = dt1;
32076 if ( dt2 < 1e-4 ) dt2 = dt1;
32077
32078 px.initNonuniformCatmullRom( p0.x, p1.x, p2.x, p3.x, dt0, dt1, dt2 );
32079 py.initNonuniformCatmullRom( p0.y, p1.y, p2.y, p3.y, dt0, dt1, dt2 );
32080 pz.initNonuniformCatmullRom( p0.z, p1.z, p2.z, p3.z, dt0, dt1, dt2 );
32081
32082 } else if ( this.curveType === 'catmullrom' ) {
32083
32084 px.initCatmullRom( p0.x, p1.x, p2.x, p3.x, this.tension );
32085 py.initCatmullRom( p0.y, p1.y, p2.y, p3.y, this.tension );
32086 pz.initCatmullRom( p0.z, p1.z, p2.z, p3.z, this.tension );
32087
32088 }
32089
32090 point.set(
32091 px.calc( weight ),
32092 py.calc( weight ),
32093 pz.calc( weight )
32094 );
32095
32096 return point;
32097
32098};
32099
32100CatmullRomCurve3.prototype.copy = function ( source ) {
32101
32102 Curve.prototype.copy.call( this, source );
32103
32104 this.points = [];
32105
32106 for ( var i = 0, l = source.points.length; i < l; i ++ ) {
32107
32108 var point = source.points[ i ];
32109
32110 this.points.push( point.clone() );
32111
32112 }
32113
32114 this.closed = source.closed;
32115 this.curveType = source.curveType;
32116 this.tension = source.tension;
32117
32118 return this;
32119
32120};
32121
32122CatmullRomCurve3.prototype.toJSON = function () {
32123
32124 var data = Curve.prototype.toJSON.call( this );
32125
32126 data.points = [];
32127
32128 for ( var i = 0, l = this.points.length; i < l; i ++ ) {
32129
32130 var point = this.points[ i ];
32131 data.points.push( point.toArray() );
32132
32133 }
32134
32135 data.closed = this.closed;
32136 data.curveType = this.curveType;
32137 data.tension = this.tension;
32138
32139 return data;
32140
32141};
32142
32143CatmullRomCurve3.prototype.fromJSON = function ( json ) {
32144
32145 Curve.prototype.fromJSON.call( this, json );
32146
32147 this.points = [];
32148
32149 for ( var i = 0, l = json.points.length; i < l; i ++ ) {
32150
32151 var point = json.points[ i ];
32152 this.points.push( new Vector3().fromArray( point ) );
32153
32154 }
32155
32156 this.closed = json.closed;
32157 this.curveType = json.curveType;
32158 this.tension = json.tension;
32159
32160 return this;
32161
32162};
32163
32164/**
32165 * @author zz85 / http://www.lab4games.net/zz85/blog
32166 *
32167 * Bezier Curves formulas obtained from
32168 * http://en.wikipedia.org/wiki/Bézier_curve
32169 */
32170
32171function CatmullRom( t, p0, p1, p2, p3 ) {
32172
32173 var v0 = ( p2 - p0 ) * 0.5;
32174 var v1 = ( p3 - p1 ) * 0.5;
32175 var t2 = t * t;
32176 var t3 = t * t2;
32177 return ( 2 * p1 - 2 * p2 + v0 + v1 ) * t3 + ( - 3 * p1 + 3 * p2 - 2 * v0 - v1 ) * t2 + v0 * t + p1;
32178
32179}
32180
32181//
32182
32183function QuadraticBezierP0( t, p ) {
32184
32185 var k = 1 - t;
32186 return k * k * p;
32187
32188}
32189
32190function QuadraticBezierP1( t, p ) {
32191
32192 return 2 * ( 1 - t ) * t * p;
32193
32194}
32195
32196function QuadraticBezierP2( t, p ) {
32197
32198 return t * t * p;
32199
32200}
32201
32202function QuadraticBezier( t, p0, p1, p2 ) {
32203
32204 return QuadraticBezierP0( t, p0 ) + QuadraticBezierP1( t, p1 ) +
32205 QuadraticBezierP2( t, p2 );
32206
32207}
32208
32209//
32210
32211function CubicBezierP0( t, p ) {
32212
32213 var k = 1 - t;
32214 return k * k * k * p;
32215
32216}
32217
32218function CubicBezierP1( t, p ) {
32219
32220 var k = 1 - t;
32221 return 3 * k * k * t * p;
32222
32223}
32224
32225function CubicBezierP2( t, p ) {
32226
32227 return 3 * ( 1 - t ) * t * t * p;
32228
32229}
32230
32231function CubicBezierP3( t, p ) {
32232
32233 return t * t * t * p;
32234
32235}
32236
32237function CubicBezier( t, p0, p1, p2, p3 ) {
32238
32239 return CubicBezierP0( t, p0 ) + CubicBezierP1( t, p1 ) + CubicBezierP2( t, p2 ) +
32240 CubicBezierP3( t, p3 );
32241
32242}
32243
32244function CubicBezierCurve( v0, v1, v2, v3 ) {
32245
32246 Curve.call( this );
32247
32248 this.type = 'CubicBezierCurve';
32249
32250 this.v0 = v0 || new Vector2();
32251 this.v1 = v1 || new Vector2();
32252 this.v2 = v2 || new Vector2();
32253 this.v3 = v3 || new Vector2();
32254
32255}
32256
32257CubicBezierCurve.prototype = Object.create( Curve.prototype );
32258CubicBezierCurve.prototype.constructor = CubicBezierCurve;
32259
32260CubicBezierCurve.prototype.isCubicBezierCurve = true;
32261
32262CubicBezierCurve.prototype.getPoint = function ( t, optionalTarget ) {
32263
32264 var point = optionalTarget || new Vector2();
32265
32266 var v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3;
32267
32268 point.set(
32269 CubicBezier( t, v0.x, v1.x, v2.x, v3.x ),
32270 CubicBezier( t, v0.y, v1.y, v2.y, v3.y )
32271 );
32272
32273 return point;
32274
32275};
32276
32277CubicBezierCurve.prototype.copy = function ( source ) {
32278
32279 Curve.prototype.copy.call( this, source );
32280
32281 this.v0.copy( source.v0 );
32282 this.v1.copy( source.v1 );
32283 this.v2.copy( source.v2 );
32284 this.v3.copy( source.v3 );
32285
32286 return this;
32287
32288};
32289
32290CubicBezierCurve.prototype.toJSON = function () {
32291
32292 var data = Curve.prototype.toJSON.call( this );
32293
32294 data.v0 = this.v0.toArray();
32295 data.v1 = this.v1.toArray();
32296 data.v2 = this.v2.toArray();
32297 data.v3 = this.v3.toArray();
32298
32299 return data;
32300
32301};
32302
32303CubicBezierCurve.prototype.fromJSON = function ( json ) {
32304
32305 Curve.prototype.fromJSON.call( this, json );
32306
32307 this.v0.fromArray( json.v0 );
32308 this.v1.fromArray( json.v1 );
32309 this.v2.fromArray( json.v2 );
32310 this.v3.fromArray( json.v3 );
32311
32312 return this;
32313
32314};
32315
32316function CubicBezierCurve3( v0, v1, v2, v3 ) {
32317
32318 Curve.call( this );
32319
32320 this.type = 'CubicBezierCurve3';
32321
32322 this.v0 = v0 || new Vector3();
32323 this.v1 = v1 || new Vector3();
32324 this.v2 = v2 || new Vector3();
32325 this.v3 = v3 || new Vector3();
32326
32327}
32328
32329CubicBezierCurve3.prototype = Object.create( Curve.prototype );
32330CubicBezierCurve3.prototype.constructor = CubicBezierCurve3;
32331
32332CubicBezierCurve3.prototype.isCubicBezierCurve3 = true;
32333
32334CubicBezierCurve3.prototype.getPoint = function ( t, optionalTarget ) {
32335
32336 var point = optionalTarget || new Vector3();
32337
32338 var v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3;
32339
32340 point.set(
32341 CubicBezier( t, v0.x, v1.x, v2.x, v3.x ),
32342 CubicBezier( t, v0.y, v1.y, v2.y, v3.y ),
32343 CubicBezier( t, v0.z, v1.z, v2.z, v3.z )
32344 );
32345
32346 return point;
32347
32348};
32349
32350CubicBezierCurve3.prototype.copy = function ( source ) {
32351
32352 Curve.prototype.copy.call( this, source );
32353
32354 this.v0.copy( source.v0 );
32355 this.v1.copy( source.v1 );
32356 this.v2.copy( source.v2 );
32357 this.v3.copy( source.v3 );
32358
32359 return this;
32360
32361};
32362
32363CubicBezierCurve3.prototype.toJSON = function () {
32364
32365 var data = Curve.prototype.toJSON.call( this );
32366
32367 data.v0 = this.v0.toArray();
32368 data.v1 = this.v1.toArray();
32369 data.v2 = this.v2.toArray();
32370 data.v3 = this.v3.toArray();
32371
32372 return data;
32373
32374};
32375
32376CubicBezierCurve3.prototype.fromJSON = function ( json ) {
32377
32378 Curve.prototype.fromJSON.call( this, json );
32379
32380 this.v0.fromArray( json.v0 );
32381 this.v1.fromArray( json.v1 );
32382 this.v2.fromArray( json.v2 );
32383 this.v3.fromArray( json.v3 );
32384
32385 return this;
32386
32387};
32388
32389function LineCurve( v1, v2 ) {
32390
32391 Curve.call( this );
32392
32393 this.type = 'LineCurve';
32394
32395 this.v1 = v1 || new Vector2();
32396 this.v2 = v2 || new Vector2();
32397
32398}
32399
32400LineCurve.prototype = Object.create( Curve.prototype );
32401LineCurve.prototype.constructor = LineCurve;
32402
32403LineCurve.prototype.isLineCurve = true;
32404
32405LineCurve.prototype.getPoint = function ( t, optionalTarget ) {
32406
32407 var point = optionalTarget || new Vector2();
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
32426LineCurve.prototype.getPointAt = function ( u, optionalTarget ) {
32427
32428 return this.getPoint( u, optionalTarget );
32429
32430};
32431
32432LineCurve.prototype.getTangent = function ( /* t */ ) {
32433
32434 var tangent = this.v2.clone().sub( this.v1 );
32435
32436 return tangent.normalize();
32437
32438};
32439
32440LineCurve.prototype.copy = function ( source ) {
32441
32442 Curve.prototype.copy.call( this, source );
32443
32444 this.v1.copy( source.v1 );
32445 this.v2.copy( source.v2 );
32446
32447 return this;
32448
32449};
32450
32451LineCurve.prototype.toJSON = function () {
32452
32453 var data = Curve.prototype.toJSON.call( this );
32454
32455 data.v1 = this.v1.toArray();
32456 data.v2 = this.v2.toArray();
32457
32458 return data;
32459
32460};
32461
32462LineCurve.prototype.fromJSON = function ( json ) {
32463
32464 Curve.prototype.fromJSON.call( this, json );
32465
32466 this.v1.fromArray( json.v1 );
32467 this.v2.fromArray( json.v2 );
32468
32469 return this;
32470
32471};
32472
32473function LineCurve3( v1, v2 ) {
32474
32475 Curve.call( this );
32476
32477 this.type = 'LineCurve3';
32478
32479 this.v1 = v1 || new Vector3();
32480 this.v2 = v2 || new Vector3();
32481
32482}
32483
32484LineCurve3.prototype = Object.create( Curve.prototype );
32485LineCurve3.prototype.constructor = LineCurve3;
32486
32487LineCurve3.prototype.isLineCurve3 = true;
32488
32489LineCurve3.prototype.getPoint = function ( t, optionalTarget ) {
32490
32491 var point = optionalTarget || new Vector3();
32492
32493 if ( t === 1 ) {
32494
32495 point.copy( this.v2 );
32496
32497 } else {
32498
32499 point.copy( this.v2 ).sub( this.v1 );
32500 point.multiplyScalar( t ).add( this.v1 );
32501
32502 }
32503
32504 return point;
32505
32506};
32507
32508// Line curve is linear, so we can overwrite default getPointAt
32509
32510LineCurve3.prototype.getPointAt = function ( u, optionalTarget ) {
32511
32512 return this.getPoint( u, optionalTarget );
32513
32514};
32515
32516LineCurve3.prototype.copy = function ( source ) {
32517
32518 Curve.prototype.copy.call( this, source );
32519
32520 this.v1.copy( source.v1 );
32521 this.v2.copy( source.v2 );
32522
32523 return this;
32524
32525};
32526
32527LineCurve3.prototype.toJSON = function () {
32528
32529 var data = Curve.prototype.toJSON.call( this );
32530
32531 data.v1 = this.v1.toArray();
32532 data.v2 = this.v2.toArray();
32533
32534 return data;
32535
32536};
32537
32538LineCurve3.prototype.fromJSON = function ( json ) {
32539
32540 Curve.prototype.fromJSON.call( this, json );
32541
32542 this.v1.fromArray( json.v1 );
32543 this.v2.fromArray( json.v2 );
32544
32545 return this;
32546
32547};
32548
32549function QuadraticBezierCurve( v0, v1, v2 ) {
32550
32551 Curve.call( this );
32552
32553 this.type = 'QuadraticBezierCurve';
32554
32555 this.v0 = v0 || new Vector2();
32556 this.v1 = v1 || new Vector2();
32557 this.v2 = v2 || new Vector2();
32558
32559}
32560
32561QuadraticBezierCurve.prototype = Object.create( Curve.prototype );
32562QuadraticBezierCurve.prototype.constructor = QuadraticBezierCurve;
32563
32564QuadraticBezierCurve.prototype.isQuadraticBezierCurve = true;
32565
32566QuadraticBezierCurve.prototype.getPoint = function ( t, optionalTarget ) {
32567
32568 var point = optionalTarget || new Vector2();
32569
32570 var v0 = this.v0, v1 = this.v1, v2 = this.v2;
32571
32572 point.set(
32573 QuadraticBezier( t, v0.x, v1.x, v2.x ),
32574 QuadraticBezier( t, v0.y, v1.y, v2.y )
32575 );
32576
32577 return point;
32578
32579};
32580
32581QuadraticBezierCurve.prototype.copy = function ( source ) {
32582
32583 Curve.prototype.copy.call( this, source );
32584
32585 this.v0.copy( source.v0 );
32586 this.v1.copy( source.v1 );
32587 this.v2.copy( source.v2 );
32588
32589 return this;
32590
32591};
32592
32593QuadraticBezierCurve.prototype.toJSON = function () {
32594
32595 var data = Curve.prototype.toJSON.call( this );
32596
32597 data.v0 = this.v0.toArray();
32598 data.v1 = this.v1.toArray();
32599 data.v2 = this.v2.toArray();
32600
32601 return data;
32602
32603};
32604
32605QuadraticBezierCurve.prototype.fromJSON = function ( json ) {
32606
32607 Curve.prototype.fromJSON.call( this, json );
32608
32609 this.v0.fromArray( json.v0 );
32610 this.v1.fromArray( json.v1 );
32611 this.v2.fromArray( json.v2 );
32612
32613 return this;
32614
32615};
32616
32617function QuadraticBezierCurve3( v0, v1, v2 ) {
32618
32619 Curve.call( this );
32620
32621 this.type = 'QuadraticBezierCurve3';
32622
32623 this.v0 = v0 || new Vector3();
32624 this.v1 = v1 || new Vector3();
32625 this.v2 = v2 || new Vector3();
32626
32627}
32628
32629QuadraticBezierCurve3.prototype = Object.create( Curve.prototype );
32630QuadraticBezierCurve3.prototype.constructor = QuadraticBezierCurve3;
32631
32632QuadraticBezierCurve3.prototype.isQuadraticBezierCurve3 = true;
32633
32634QuadraticBezierCurve3.prototype.getPoint = function ( t, optionalTarget ) {
32635
32636 var point = optionalTarget || new Vector3();
32637
32638 var v0 = this.v0, v1 = this.v1, v2 = this.v2;
32639
32640 point.set(
32641 QuadraticBezier( t, v0.x, v1.x, v2.x ),
32642 QuadraticBezier( t, v0.y, v1.y, v2.y ),
32643 QuadraticBezier( t, v0.z, v1.z, v2.z )
32644 );
32645
32646 return point;
32647
32648};
32649
32650QuadraticBezierCurve3.prototype.copy = function ( source ) {
32651
32652 Curve.prototype.copy.call( this, source );
32653
32654 this.v0.copy( source.v0 );
32655 this.v1.copy( source.v1 );
32656 this.v2.copy( source.v2 );
32657
32658 return this;
32659
32660};
32661
32662QuadraticBezierCurve3.prototype.toJSON = function () {
32663
32664 var data = Curve.prototype.toJSON.call( this );
32665
32666 data.v0 = this.v0.toArray();
32667 data.v1 = this.v1.toArray();
32668 data.v2 = this.v2.toArray();
32669
32670 return data;
32671
32672};
32673
32674QuadraticBezierCurve3.prototype.fromJSON = function ( json ) {
32675
32676 Curve.prototype.fromJSON.call( this, json );
32677
32678 this.v0.fromArray( json.v0 );
32679 this.v1.fromArray( json.v1 );
32680 this.v2.fromArray( json.v2 );
32681
32682 return this;
32683
32684};
32685
32686function SplineCurve( points /* array of Vector2 */ ) {
32687
32688 Curve.call( this );
32689
32690 this.type = 'SplineCurve';
32691
32692 this.points = points || [];
32693
32694}
32695
32696SplineCurve.prototype = Object.create( Curve.prototype );
32697SplineCurve.prototype.constructor = SplineCurve;
32698
32699SplineCurve.prototype.isSplineCurve = true;
32700
32701SplineCurve.prototype.getPoint = function ( t, optionalTarget ) {
32702
32703 var point = optionalTarget || new Vector2();
32704
32705 var points = this.points;
32706 var p = ( points.length - 1 ) * t;
32707
32708 var intPoint = Math.floor( p );
32709 var weight = p - intPoint;
32710
32711 var p0 = points[ intPoint === 0 ? intPoint : intPoint - 1 ];
32712 var p1 = points[ intPoint ];
32713 var p2 = points[ intPoint > points.length - 2 ? points.length - 1 : intPoint + 1 ];
32714 var p3 = points[ intPoint > points.length - 3 ? points.length - 1 : intPoint + 2 ];
32715
32716 point.set(
32717 CatmullRom( weight, p0.x, p1.x, p2.x, p3.x ),
32718 CatmullRom( weight, p0.y, p1.y, p2.y, p3.y )
32719 );
32720
32721 return point;
32722
32723};
32724
32725SplineCurve.prototype.copy = function ( source ) {
32726
32727 Curve.prototype.copy.call( this, source );
32728
32729 this.points = [];
32730
32731 for ( var i = 0, l = source.points.length; i < l; i ++ ) {
32732
32733 var point = source.points[ i ];
32734
32735 this.points.push( point.clone() );
32736
32737 }
32738
32739 return this;
32740
32741};
32742
32743SplineCurve.prototype.toJSON = function () {
32744
32745 var data = Curve.prototype.toJSON.call( this );
32746
32747 data.points = [];
32748
32749 for ( var i = 0, l = this.points.length; i < l; i ++ ) {
32750
32751 var point = this.points[ i ];
32752 data.points.push( point.toArray() );
32753
32754 }
32755
32756 return data;
32757
32758};
32759
32760SplineCurve.prototype.fromJSON = function ( json ) {
32761
32762 Curve.prototype.fromJSON.call( this, json );
32763
32764 this.points = [];
32765
32766 for ( var i = 0, l = json.points.length; i < l; i ++ ) {
32767
32768 var point = json.points[ i ];
32769 this.points.push( new Vector2().fromArray( point ) );
32770
32771 }
32772
32773 return this;
32774
32775};
32776
32777
32778
32779var Curves = Object.freeze({
32780 ArcCurve: ArcCurve,
32781 CatmullRomCurve3: CatmullRomCurve3,
32782 CubicBezierCurve: CubicBezierCurve,
32783 CubicBezierCurve3: CubicBezierCurve3,
32784 EllipseCurve: EllipseCurve,
32785 LineCurve: LineCurve,
32786 LineCurve3: LineCurve3,
32787 QuadraticBezierCurve: QuadraticBezierCurve,
32788 QuadraticBezierCurve3: QuadraticBezierCurve3,
32789 SplineCurve: SplineCurve
32790});
32791
32792/**
32793 * @author zz85 / http://www.lab4games.net/zz85/blog
32794 *
32795 **/
32796
32797/**************************************************************
32798 * Curved Path - a curve path is simply a array of connected
32799 * curves, but retains the api of a curve
32800 **************************************************************/
32801
32802function CurvePath() {
32803
32804 Curve.call( this );
32805
32806 this.type = 'CurvePath';
32807
32808 this.curves = [];
32809 this.autoClose = false; // Automatically closes the path
32810
32811}
32812
32813CurvePath.prototype = Object.assign( Object.create( Curve.prototype ), {
32814
32815 constructor: CurvePath,
32816
32817 add: function ( curve ) {
32818
32819 this.curves.push( curve );
32820
32821 },
32822
32823 closePath: function () {
32824
32825 // Add a line curve if start and end of lines are not connected
32826 var startPoint = this.curves[ 0 ].getPoint( 0 );
32827 var endPoint = this.curves[ this.curves.length - 1 ].getPoint( 1 );
32828
32829 if ( ! startPoint.equals( endPoint ) ) {
32830
32831 this.curves.push( new LineCurve( endPoint, startPoint ) );
32832
32833 }
32834
32835 },
32836
32837 // To get accurate point with reference to
32838 // entire path distance at time t,
32839 // following has to be done:
32840
32841 // 1. Length of each sub path have to be known
32842 // 2. Locate and identify type of curve
32843 // 3. Get t for the curve
32844 // 4. Return curve.getPointAt(t')
32845
32846 getPoint: function ( t ) {
32847
32848 var d = t * this.getLength();
32849 var curveLengths = this.getCurveLengths();
32850 var i = 0;
32851
32852 // To think about boundaries points.
32853
32854 while ( i < curveLengths.length ) {
32855
32856 if ( curveLengths[ i ] >= d ) {
32857
32858 var diff = curveLengths[ i ] - d;
32859 var curve = this.curves[ i ];
32860
32861 var segmentLength = curve.getLength();
32862 var u = segmentLength === 0 ? 0 : 1 - diff / segmentLength;
32863
32864 return curve.getPointAt( u );
32865
32866 }
32867
32868 i ++;
32869
32870 }
32871
32872 return null;
32873
32874 // loop where sum != 0, sum > d , sum+1 <d
32875
32876 },
32877
32878 // We cannot use the default THREE.Curve getPoint() with getLength() because in
32879 // THREE.Curve, getLength() depends on getPoint() but in THREE.CurvePath
32880 // getPoint() depends on getLength
32881
32882 getLength: function () {
32883
32884 var lens = this.getCurveLengths();
32885 return lens[ lens.length - 1 ];
32886
32887 },
32888
32889 // cacheLengths must be recalculated.
32890 updateArcLengths: function () {
32891
32892 this.needsUpdate = true;
32893 this.cacheLengths = null;
32894 this.getCurveLengths();
32895
32896 },
32897
32898 // Compute lengths and cache them
32899 // We cannot overwrite getLengths() because UtoT mapping uses it.
32900
32901 getCurveLengths: function () {
32902
32903 // We use cache values if curves and cache array are same length
32904
32905 if ( this.cacheLengths && this.cacheLengths.length === this.curves.length ) {
32906
32907 return this.cacheLengths;
32908
32909 }
32910
32911 // Get length of sub-curve
32912 // Push sums into cached array
32913
32914 var lengths = [], sums = 0;
32915
32916 for ( var i = 0, l = this.curves.length; i < l; i ++ ) {
32917
32918 sums += this.curves[ i ].getLength();
32919 lengths.push( sums );
32920
32921 }
32922
32923 this.cacheLengths = lengths;
32924
32925 return lengths;
32926
32927 },
32928
32929 getSpacedPoints: function ( divisions ) {
32930
32931 if ( divisions === undefined ) divisions = 40;
32932
32933 var points = [];
32934
32935 for ( var i = 0; i <= divisions; i ++ ) {
32936
32937 points.push( this.getPoint( i / divisions ) );
32938
32939 }
32940
32941 if ( this.autoClose ) {
32942
32943 points.push( points[ 0 ] );
32944
32945 }
32946
32947 return points;
32948
32949 },
32950
32951 getPoints: function ( divisions ) {
32952
32953 divisions = divisions || 12;
32954
32955 var points = [], last;
32956
32957 for ( var i = 0, curves = this.curves; i < curves.length; i ++ ) {
32958
32959 var curve = curves[ i ];
32960 var resolution = ( curve && curve.isEllipseCurve ) ? divisions * 2
32961 : ( curve && curve.isLineCurve ) ? 1
32962 : ( curve && curve.isSplineCurve ) ? divisions * curve.points.length
32963 : divisions;
32964
32965 var pts = curve.getPoints( resolution );
32966
32967 for ( var j = 0; j < pts.length; j ++ ) {
32968
32969 var point = pts[ j ];
32970
32971 if ( last && last.equals( point ) ) continue; // ensures no consecutive points are duplicates
32972
32973 points.push( point );
32974 last = point;
32975
32976 }
32977
32978 }
32979
32980 if ( this.autoClose && points.length > 1 && ! points[ points.length - 1 ].equals( points[ 0 ] ) ) {
32981
32982 points.push( points[ 0 ] );
32983
32984 }
32985
32986 return points;
32987
32988 },
32989
32990 copy: function ( source ) {
32991
32992 Curve.prototype.copy.call( this, source );
32993
32994 this.curves = [];
32995
32996 for ( var i = 0, l = source.curves.length; i < l; i ++ ) {
32997
32998 var curve = source.curves[ i ];
32999
33000 this.curves.push( curve.clone() );
33001
33002 }
33003
33004 this.autoClose = source.autoClose;
33005
33006 return this;
33007
33008 },
33009
33010 toJSON: function () {
33011
33012 var data = Curve.prototype.toJSON.call( this );
33013
33014 data.autoClose = this.autoClose;
33015 data.curves = [];
33016
33017 for ( var i = 0, l = this.curves.length; i < l; i ++ ) {
33018
33019 var curve = this.curves[ i ];
33020 data.curves.push( curve.toJSON() );
33021
33022 }
33023
33024 return data;
33025
33026 },
33027
33028 fromJSON: function ( json ) {
33029
33030 Curve.prototype.fromJSON.call( this, json );
33031
33032 this.autoClose = json.autoClose;
33033 this.curves = [];
33034
33035 for ( var i = 0, l = json.curves.length; i < l; i ++ ) {
33036
33037 var curve = json.curves[ i ];
33038 this.curves.push( new Curves[ curve.type ]().fromJSON( curve ) );
33039
33040 }
33041
33042 return this;
33043
33044 }
33045
33046} );
33047
33048/**
33049 * @author zz85 / http://www.lab4games.net/zz85/blog
33050 * Creates free form 2d path using series of points, lines or curves.
33051 **/
33052
33053function Path( points ) {
33054
33055 CurvePath.call( this );
33056
33057 this.type = 'Path';
33058
33059 this.currentPoint = new Vector2();
33060
33061 if ( points ) {
33062
33063 this.setFromPoints( points );
33064
33065 }
33066
33067}
33068
33069Path.prototype = Object.assign( Object.create( CurvePath.prototype ), {
33070
33071 constructor: Path,
33072
33073 setFromPoints: function ( points ) {
33074
33075 this.moveTo( points[ 0 ].x, points[ 0 ].y );
33076
33077 for ( var i = 1, l = points.length; i < l; i ++ ) {
33078
33079 this.lineTo( points[ i ].x, points[ i ].y );
33080
33081 }
33082
33083 },
33084
33085 moveTo: function ( x, y ) {
33086
33087 this.currentPoint.set( x, y ); // TODO consider referencing vectors instead of copying?
33088
33089 },
33090
33091 lineTo: function ( x, y ) {
33092
33093 var curve = new LineCurve( this.currentPoint.clone(), new Vector2( x, y ) );
33094 this.curves.push( curve );
33095
33096 this.currentPoint.set( x, y );
33097
33098 },
33099
33100 quadraticCurveTo: function ( aCPx, aCPy, aX, aY ) {
33101
33102 var curve = new QuadraticBezierCurve(
33103 this.currentPoint.clone(),
33104 new Vector2( aCPx, aCPy ),
33105 new Vector2( aX, aY )
33106 );
33107
33108 this.curves.push( curve );
33109
33110 this.currentPoint.set( aX, aY );
33111
33112 },
33113
33114 bezierCurveTo: function ( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) {
33115
33116 var curve = new CubicBezierCurve(
33117 this.currentPoint.clone(),
33118 new Vector2( aCP1x, aCP1y ),
33119 new Vector2( aCP2x, aCP2y ),
33120 new Vector2( aX, aY )
33121 );
33122
33123 this.curves.push( curve );
33124
33125 this.currentPoint.set( aX, aY );
33126
33127 },
33128
33129 splineThru: function ( pts /*Array of Vector*/ ) {
33130
33131 var npts = [ this.currentPoint.clone() ].concat( pts );
33132
33133 var curve = new SplineCurve( npts );
33134 this.curves.push( curve );
33135
33136 this.currentPoint.copy( pts[ pts.length - 1 ] );
33137
33138 },
33139
33140 arc: function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
33141
33142 var x0 = this.currentPoint.x;
33143 var y0 = this.currentPoint.y;
33144
33145 this.absarc( aX + x0, aY + y0, aRadius,
33146 aStartAngle, aEndAngle, aClockwise );
33147
33148 },
33149
33150 absarc: function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
33151
33152 this.absellipse( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
33153
33154 },
33155
33156 ellipse: function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
33157
33158 var x0 = this.currentPoint.x;
33159 var y0 = this.currentPoint.y;
33160
33161 this.absellipse( aX + x0, aY + y0, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
33162
33163 },
33164
33165 absellipse: function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
33166
33167 var curve = new EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
33168
33169 if ( this.curves.length > 0 ) {
33170
33171 // if a previous curve is present, attempt to join
33172 var firstPoint = curve.getPoint( 0 );
33173
33174 if ( ! firstPoint.equals( this.currentPoint ) ) {
33175
33176 this.lineTo( firstPoint.x, firstPoint.y );
33177
33178 }
33179
33180 }
33181
33182 this.curves.push( curve );
33183
33184 var lastPoint = curve.getPoint( 1 );
33185 this.currentPoint.copy( lastPoint );
33186
33187 },
33188
33189 copy: function ( source ) {
33190
33191 CurvePath.prototype.copy.call( this, source );
33192
33193 this.currentPoint.copy( source.currentPoint );
33194
33195 return this;
33196
33197 },
33198
33199 toJSON: function () {
33200
33201 var data = CurvePath.prototype.toJSON.call( this );
33202
33203 data.currentPoint = this.currentPoint.toArray();
33204
33205 return data;
33206
33207 },
33208
33209 fromJSON: function ( json ) {
33210
33211 CurvePath.prototype.fromJSON.call( this, json );
33212
33213 this.currentPoint.fromArray( json.currentPoint );
33214
33215 return this;
33216
33217 }
33218
33219} );
33220
33221/**
33222 * @author zz85 / http://www.lab4games.net/zz85/blog
33223 * Defines a 2d shape plane using paths.
33224 **/
33225
33226// STEP 1 Create a path.
33227// STEP 2 Turn path into shape.
33228// STEP 3 ExtrudeGeometry takes in Shape/Shapes
33229// STEP 3a - Extract points from each shape, turn to vertices
33230// STEP 3b - Triangulate each shape, add faces.
33231
33232function Shape( points ) {
33233
33234 Path.call( this, points );
33235
33236 this.uuid = _Math.generateUUID();
33237
33238 this.type = 'Shape';
33239
33240 this.holes = [];
33241
33242}
33243
33244Shape.prototype = Object.assign( Object.create( Path.prototype ), {
33245
33246 constructor: Shape,
33247
33248 getPointsHoles: function ( divisions ) {
33249
33250 var holesPts = [];
33251
33252 for ( var i = 0, l = this.holes.length; i < l; i ++ ) {
33253
33254 holesPts[ i ] = this.holes[ i ].getPoints( divisions );
33255
33256 }
33257
33258 return holesPts;
33259
33260 },
33261
33262 // get points of shape and holes (keypoints based on segments parameter)
33263
33264 extractPoints: function ( divisions ) {
33265
33266 return {
33267
33268 shape: this.getPoints( divisions ),
33269 holes: this.getPointsHoles( divisions )
33270
33271 };
33272
33273 },
33274
33275 copy: function ( source ) {
33276
33277 Path.prototype.copy.call( this, source );
33278
33279 this.holes = [];
33280
33281 for ( var i = 0, l = source.holes.length; i < l; i ++ ) {
33282
33283 var hole = source.holes[ i ];
33284
33285 this.holes.push( hole.clone() );
33286
33287 }
33288
33289 return this;
33290
33291 },
33292
33293 toJSON: function () {
33294
33295 var data = Path.prototype.toJSON.call( this );
33296
33297 data.uuid = this.uuid;
33298 data.holes = [];
33299
33300 for ( var i = 0, l = this.holes.length; i < l; i ++ ) {
33301
33302 var hole = this.holes[ i ];
33303 data.holes.push( hole.toJSON() );
33304
33305 }
33306
33307 return data;
33308
33309 },
33310
33311 fromJSON: function ( json ) {
33312
33313 Path.prototype.fromJSON.call( this, json );
33314
33315 this.uuid = json.uuid;
33316 this.holes = [];
33317
33318 for ( var i = 0, l = json.holes.length; i < l; i ++ ) {
33319
33320 var hole = json.holes[ i ];
33321 this.holes.push( new Path().fromJSON( hole ) );
33322
33323 }
33324
33325 return this;
33326
33327 }
33328
33329} );
33330
33331/**
33332 * @author mrdoob / http://mrdoob.com/
33333 * @author alteredq / http://alteredqualia.com/
33334 */
33335
33336function Light( color, intensity ) {
33337
33338 Object3D.call( this );
33339
33340 this.type = 'Light';
33341
33342 this.color = new Color( color );
33343 this.intensity = intensity !== undefined ? intensity : 1;
33344
33345 this.receiveShadow = undefined;
33346
33347}
33348
33349Light.prototype = Object.assign( Object.create( Object3D.prototype ), {
33350
33351 constructor: Light,
33352
33353 isLight: true,
33354
33355 copy: function ( source ) {
33356
33357 Object3D.prototype.copy.call( this, source );
33358
33359 this.color.copy( source.color );
33360 this.intensity = source.intensity;
33361
33362 return this;
33363
33364 },
33365
33366 toJSON: function ( meta ) {
33367
33368 var data = Object3D.prototype.toJSON.call( this, meta );
33369
33370 data.object.color = this.color.getHex();
33371 data.object.intensity = this.intensity;
33372
33373 if ( this.groundColor !== undefined ) data.object.groundColor = this.groundColor.getHex();
33374
33375 if ( this.distance !== undefined ) data.object.distance = this.distance;
33376 if ( this.angle !== undefined ) data.object.angle = this.angle;
33377 if ( this.decay !== undefined ) data.object.decay = this.decay;
33378 if ( this.penumbra !== undefined ) data.object.penumbra = this.penumbra;
33379
33380 if ( this.shadow !== undefined ) data.object.shadow = this.shadow.toJSON();
33381
33382 return data;
33383
33384 }
33385
33386} );
33387
33388/**
33389 * @author alteredq / http://alteredqualia.com/
33390 */
33391
33392function HemisphereLight( skyColor, groundColor, intensity ) {
33393
33394 Light.call( this, skyColor, intensity );
33395
33396 this.type = 'HemisphereLight';
33397
33398 this.castShadow = undefined;
33399
33400 this.position.copy( Object3D.DefaultUp );
33401 this.updateMatrix();
33402
33403 this.groundColor = new Color( groundColor );
33404
33405}
33406
33407HemisphereLight.prototype = Object.assign( Object.create( Light.prototype ), {
33408
33409 constructor: HemisphereLight,
33410
33411 isHemisphereLight: true,
33412
33413 copy: function ( source ) {
33414
33415 Light.prototype.copy.call( this, source );
33416
33417 this.groundColor.copy( source.groundColor );
33418
33419 return this;
33420
33421 }
33422
33423} );
33424
33425/**
33426 * @author mrdoob / http://mrdoob.com/
33427 */
33428
33429function LightShadow( camera ) {
33430
33431 this.camera = camera;
33432
33433 this.bias = 0;
33434 this.radius = 1;
33435
33436 this.mapSize = new Vector2( 512, 512 );
33437
33438 this.map = null;
33439 this.matrix = new Matrix4();
33440
33441}
33442
33443Object.assign( LightShadow.prototype, {
33444
33445 copy: function ( source ) {
33446
33447 this.camera = source.camera.clone();
33448
33449 this.bias = source.bias;
33450 this.radius = source.radius;
33451
33452 this.mapSize.copy( source.mapSize );
33453
33454 return this;
33455
33456 },
33457
33458 clone: function () {
33459
33460 return new this.constructor().copy( this );
33461
33462 },
33463
33464 toJSON: function () {
33465
33466 var object = {};
33467
33468 if ( this.bias !== 0 ) object.bias = this.bias;
33469 if ( this.radius !== 1 ) object.radius = this.radius;
33470 if ( this.mapSize.x !== 512 || this.mapSize.y !== 512 ) object.mapSize = this.mapSize.toArray();
33471
33472 object.camera = this.camera.toJSON( false ).object;
33473 delete object.camera.matrix;
33474
33475 return object;
33476
33477 }
33478
33479} );
33480
33481/**
33482 * @author mrdoob / http://mrdoob.com/
33483 */
33484
33485function SpotLightShadow() {
33486
33487 LightShadow.call( this, new PerspectiveCamera( 50, 1, 0.5, 500 ) );
33488
33489}
33490
33491SpotLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype ), {
33492
33493 constructor: SpotLightShadow,
33494
33495 isSpotLightShadow: true,
33496
33497 update: function ( light ) {
33498
33499 var camera = this.camera;
33500
33501 var fov = _Math.RAD2DEG * 2 * light.angle;
33502 var aspect = this.mapSize.width / this.mapSize.height;
33503 var far = light.distance || camera.far;
33504
33505 if ( fov !== camera.fov || aspect !== camera.aspect || far !== camera.far ) {
33506
33507 camera.fov = fov;
33508 camera.aspect = aspect;
33509 camera.far = far;
33510 camera.updateProjectionMatrix();
33511
33512 }
33513
33514 }
33515
33516} );
33517
33518/**
33519 * @author alteredq / http://alteredqualia.com/
33520 */
33521
33522function SpotLight( color, intensity, distance, angle, penumbra, decay ) {
33523
33524 Light.call( this, color, intensity );
33525
33526 this.type = 'SpotLight';
33527
33528 this.position.copy( Object3D.DefaultUp );
33529 this.updateMatrix();
33530
33531 this.target = new Object3D();
33532
33533 Object.defineProperty( this, 'power', {
33534 get: function () {
33535
33536 // intensity = power per solid angle.
33537 // ref: equation (17) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
33538 return this.intensity * Math.PI;
33539
33540 },
33541 set: function ( power ) {
33542
33543 // intensity = power per solid angle.
33544 // ref: equation (17) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
33545 this.intensity = power / Math.PI;
33546
33547 }
33548 } );
33549
33550 this.distance = ( distance !== undefined ) ? distance : 0;
33551 this.angle = ( angle !== undefined ) ? angle : Math.PI / 3;
33552 this.penumbra = ( penumbra !== undefined ) ? penumbra : 0;
33553 this.decay = ( decay !== undefined ) ? decay : 1; // for physically correct lights, should be 2.
33554
33555 this.shadow = new SpotLightShadow();
33556
33557}
33558
33559SpotLight.prototype = Object.assign( Object.create( Light.prototype ), {
33560
33561 constructor: SpotLight,
33562
33563 isSpotLight: true,
33564
33565 copy: function ( source ) {
33566
33567 Light.prototype.copy.call( this, source );
33568
33569 this.distance = source.distance;
33570 this.angle = source.angle;
33571 this.penumbra = source.penumbra;
33572 this.decay = source.decay;
33573
33574 this.target = source.target.clone();
33575
33576 this.shadow = source.shadow.clone();
33577
33578 return this;
33579
33580 }
33581
33582} );
33583
33584/**
33585 * @author mrdoob / http://mrdoob.com/
33586 */
33587
33588
33589function PointLight( color, intensity, distance, decay ) {
33590
33591 Light.call( this, color, intensity );
33592
33593 this.type = 'PointLight';
33594
33595 Object.defineProperty( this, 'power', {
33596 get: function () {
33597
33598 // intensity = power per solid angle.
33599 // ref: equation (15) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
33600 return this.intensity * 4 * Math.PI;
33601
33602 },
33603 set: function ( power ) {
33604
33605 // intensity = power per solid angle.
33606 // ref: equation (15) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
33607 this.intensity = power / ( 4 * Math.PI );
33608
33609 }
33610 } );
33611
33612 this.distance = ( distance !== undefined ) ? distance : 0;
33613 this.decay = ( decay !== undefined ) ? decay : 1; // for physically correct lights, should be 2.
33614
33615 this.shadow = new LightShadow( new PerspectiveCamera( 90, 1, 0.5, 500 ) );
33616
33617}
33618
33619PointLight.prototype = Object.assign( Object.create( Light.prototype ), {
33620
33621 constructor: PointLight,
33622
33623 isPointLight: true,
33624
33625 copy: function ( source ) {
33626
33627 Light.prototype.copy.call( this, source );
33628
33629 this.distance = source.distance;
33630 this.decay = source.decay;
33631
33632 this.shadow = source.shadow.clone();
33633
33634 return this;
33635
33636 }
33637
33638} );
33639
33640/**
33641 * @author mrdoob / http://mrdoob.com/
33642 */
33643
33644function DirectionalLightShadow( ) {
33645
33646 LightShadow.call( this, new OrthographicCamera( - 5, 5, 5, - 5, 0.5, 500 ) );
33647
33648}
33649
33650DirectionalLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype ), {
33651
33652 constructor: DirectionalLightShadow
33653
33654} );
33655
33656/**
33657 * @author mrdoob / http://mrdoob.com/
33658 * @author alteredq / http://alteredqualia.com/
33659 */
33660
33661function DirectionalLight( color, intensity ) {
33662
33663 Light.call( this, color, intensity );
33664
33665 this.type = 'DirectionalLight';
33666
33667 this.position.copy( Object3D.DefaultUp );
33668 this.updateMatrix();
33669
33670 this.target = new Object3D();
33671
33672 this.shadow = new DirectionalLightShadow();
33673
33674}
33675
33676DirectionalLight.prototype = Object.assign( Object.create( Light.prototype ), {
33677
33678 constructor: DirectionalLight,
33679
33680 isDirectionalLight: true,
33681
33682 copy: function ( source ) {
33683
33684 Light.prototype.copy.call( this, source );
33685
33686 this.target = source.target.clone();
33687
33688 this.shadow = source.shadow.clone();
33689
33690 return this;
33691
33692 }
33693
33694} );
33695
33696/**
33697 * @author mrdoob / http://mrdoob.com/
33698 */
33699
33700function AmbientLight( color, intensity ) {
33701
33702 Light.call( this, color, intensity );
33703
33704 this.type = 'AmbientLight';
33705
33706 this.castShadow = undefined;
33707
33708}
33709
33710AmbientLight.prototype = Object.assign( Object.create( Light.prototype ), {
33711
33712 constructor: AmbientLight,
33713
33714 isAmbientLight: true
33715
33716} );
33717
33718/**
33719 * @author abelnation / http://github.com/abelnation
33720 */
33721
33722function RectAreaLight( color, intensity, width, height ) {
33723
33724 Light.call( this, color, intensity );
33725
33726 this.type = 'RectAreaLight';
33727
33728 this.width = ( width !== undefined ) ? width : 10;
33729 this.height = ( height !== undefined ) ? height : 10;
33730
33731}
33732
33733RectAreaLight.prototype = Object.assign( Object.create( Light.prototype ), {
33734
33735 constructor: RectAreaLight,
33736
33737 isRectAreaLight: true,
33738
33739 copy: function ( source ) {
33740
33741 Light.prototype.copy.call( this, source );
33742
33743 this.width = source.width;
33744 this.height = source.height;
33745
33746 return this;
33747
33748 },
33749
33750 toJSON: function ( meta ) {
33751
33752 var data = Light.prototype.toJSON.call( this, meta );
33753
33754 data.object.width = this.width;
33755 data.object.height = this.height;
33756
33757 return data;
33758
33759 }
33760
33761} );
33762
33763/**
33764 *
33765 * A Track that interpolates Strings
33766 *
33767 *
33768 * @author Ben Houston / http://clara.io/
33769 * @author David Sarno / http://lighthaus.us/
33770 * @author tschw
33771 */
33772
33773function StringKeyframeTrack( name, times, values, interpolation ) {
33774
33775 KeyframeTrack.call( this, name, times, values, interpolation );
33776
33777}
33778
33779StringKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
33780
33781 constructor: StringKeyframeTrack,
33782
33783 ValueTypeName: 'string',
33784 ValueBufferType: Array,
33785
33786 DefaultInterpolation: InterpolateDiscrete,
33787
33788 InterpolantFactoryMethodLinear: undefined,
33789
33790 InterpolantFactoryMethodSmooth: undefined
33791
33792} );
33793
33794/**
33795 *
33796 * A Track of Boolean keyframe values.
33797 *
33798 *
33799 * @author Ben Houston / http://clara.io/
33800 * @author David Sarno / http://lighthaus.us/
33801 * @author tschw
33802 */
33803
33804function BooleanKeyframeTrack( name, times, values ) {
33805
33806 KeyframeTrack.call( this, name, times, values );
33807
33808}
33809
33810BooleanKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
33811
33812 constructor: BooleanKeyframeTrack,
33813
33814 ValueTypeName: 'bool',
33815 ValueBufferType: Array,
33816
33817 DefaultInterpolation: InterpolateDiscrete,
33818
33819 InterpolantFactoryMethodLinear: undefined,
33820 InterpolantFactoryMethodSmooth: undefined
33821
33822 // Note: Actually this track could have a optimized / compressed
33823 // representation of a single value and a custom interpolant that
33824 // computes "firstValue ^ isOdd( index )".
33825
33826} );
33827
33828/**
33829 * Abstract base class of interpolants over parametric samples.
33830 *
33831 * The parameter domain is one dimensional, typically the time or a path
33832 * along a curve defined by the data.
33833 *
33834 * The sample values can have any dimensionality and derived classes may
33835 * apply special interpretations to the data.
33836 *
33837 * This class provides the interval seek in a Template Method, deferring
33838 * the actual interpolation to derived classes.
33839 *
33840 * Time complexity is O(1) for linear access crossing at most two points
33841 * and O(log N) for random access, where N is the number of positions.
33842 *
33843 * References:
33844 *
33845 * http://www.oodesign.com/template-method-pattern.html
33846 *
33847 * @author tschw
33848 */
33849
33850function Interpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
33851
33852 this.parameterPositions = parameterPositions;
33853 this._cachedIndex = 0;
33854
33855 this.resultBuffer = resultBuffer !== undefined ?
33856 resultBuffer : new sampleValues.constructor( sampleSize );
33857 this.sampleValues = sampleValues;
33858 this.valueSize = sampleSize;
33859
33860}
33861
33862Object.assign( Interpolant.prototype, {
33863
33864 evaluate: function ( t ) {
33865
33866 var pp = this.parameterPositions,
33867 i1 = this._cachedIndex,
33868
33869 t1 = pp[ i1 ],
33870 t0 = pp[ i1 - 1 ];
33871
33872 validate_interval: {
33873
33874 seek: {
33875
33876 var right;
33877
33878 linear_scan: {
33879
33880 //- See http://jsperf.com/comparison-to-undefined/3
33881 //- slower code:
33882 //-
33883 //- if ( t >= t1 || t1 === undefined ) {
33884 forward_scan: if ( ! ( t < t1 ) ) {
33885
33886 for ( var giveUpAt = i1 + 2; ; ) {
33887
33888 if ( t1 === undefined ) {
33889
33890 if ( t < t0 ) break forward_scan;
33891
33892 // after end
33893
33894 i1 = pp.length;
33895 this._cachedIndex = i1;
33896 return this.afterEnd_( i1 - 1, t, t0 );
33897
33898 }
33899
33900 if ( i1 === giveUpAt ) break; // this loop
33901
33902 t0 = t1;
33903 t1 = pp[ ++ i1 ];
33904
33905 if ( t < t1 ) {
33906
33907 // we have arrived at the sought interval
33908 break seek;
33909
33910 }
33911
33912 }
33913
33914 // prepare binary search on the right side of the index
33915 right = pp.length;
33916 break linear_scan;
33917
33918 }
33919
33920 //- slower code:
33921 //- if ( t < t0 || t0 === undefined ) {
33922 if ( ! ( t >= t0 ) ) {
33923
33924 // looping?
33925
33926 var t1global = pp[ 1 ];
33927
33928 if ( t < t1global ) {
33929
33930 i1 = 2; // + 1, using the scan for the details
33931 t0 = t1global;
33932
33933 }
33934
33935 // linear reverse scan
33936
33937 for ( var giveUpAt = i1 - 2; ; ) {
33938
33939 if ( t0 === undefined ) {
33940
33941 // before start
33942
33943 this._cachedIndex = 0;
33944 return this.beforeStart_( 0, t, t1 );
33945
33946 }
33947
33948 if ( i1 === giveUpAt ) break; // this loop
33949
33950 t1 = t0;
33951 t0 = pp[ -- i1 - 1 ];
33952
33953 if ( t >= t0 ) {
33954
33955 // we have arrived at the sought interval
33956 break seek;
33957
33958 }
33959
33960 }
33961
33962 // prepare binary search on the left side of the index
33963 right = i1;
33964 i1 = 0;
33965 break linear_scan;
33966
33967 }
33968
33969 // the interval is valid
33970
33971 break validate_interval;
33972
33973 } // linear scan
33974
33975 // binary search
33976
33977 while ( i1 < right ) {
33978
33979 var mid = ( i1 + right ) >>> 1;
33980
33981 if ( t < pp[ mid ] ) {
33982
33983 right = mid;
33984
33985 } else {
33986
33987 i1 = mid + 1;
33988
33989 }
33990
33991 }
33992
33993 t1 = pp[ i1 ];
33994 t0 = pp[ i1 - 1 ];
33995
33996 // check boundary cases, again
33997
33998 if ( t0 === undefined ) {
33999
34000 this._cachedIndex = 0;
34001 return this.beforeStart_( 0, t, t1 );
34002
34003 }
34004
34005 if ( t1 === undefined ) {
34006
34007 i1 = pp.length;
34008 this._cachedIndex = i1;
34009 return this.afterEnd_( i1 - 1, t0, t );
34010
34011 }
34012
34013 } // seek
34014
34015 this._cachedIndex = i1;
34016
34017 this.intervalChanged_( i1, t0, t1 );
34018
34019 } // validate_interval
34020
34021 return this.interpolate_( i1, t0, t, t1 );
34022
34023 },
34024
34025 settings: null, // optional, subclass-specific settings structure
34026 // Note: The indirection allows central control of many interpolants.
34027
34028 // --- Protected interface
34029
34030 DefaultSettings_: {},
34031
34032 getSettings_: function () {
34033
34034 return this.settings || this.DefaultSettings_;
34035
34036 },
34037
34038 copySampleValue_: function ( index ) {
34039
34040 // copies a sample value to the result buffer
34041
34042 var result = this.resultBuffer,
34043 values = this.sampleValues,
34044 stride = this.valueSize,
34045 offset = index * stride;
34046
34047 for ( var i = 0; i !== stride; ++ i ) {
34048
34049 result[ i ] = values[ offset + i ];
34050
34051 }
34052
34053 return result;
34054
34055 },
34056
34057 // Template methods for derived classes:
34058
34059 interpolate_: function ( /* i1, t0, t, t1 */ ) {
34060
34061 throw new Error( 'call to abstract method' );
34062 // implementations shall return this.resultBuffer
34063
34064 },
34065
34066 intervalChanged_: function ( /* i1, t0, t1 */ ) {
34067
34068 // empty
34069
34070 }
34071
34072} );
34073
34074//!\ DECLARE ALIAS AFTER assign prototype !
34075Object.assign( Interpolant.prototype, {
34076
34077 //( 0, t, t0 ), returns this.resultBuffer
34078 beforeStart_: Interpolant.prototype.copySampleValue_,
34079
34080 //( N-1, tN-1, t ), returns this.resultBuffer
34081 afterEnd_: Interpolant.prototype.copySampleValue_,
34082
34083} );
34084
34085/**
34086 * Spherical linear unit quaternion interpolant.
34087 *
34088 * @author tschw
34089 */
34090
34091function QuaternionLinearInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
34092
34093 Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );
34094
34095}
34096
34097QuaternionLinearInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {
34098
34099 constructor: QuaternionLinearInterpolant,
34100
34101 interpolate_: function ( i1, t0, t, t1 ) {
34102
34103 var result = this.resultBuffer,
34104 values = this.sampleValues,
34105 stride = this.valueSize,
34106
34107 offset = i1 * stride,
34108
34109 alpha = ( t - t0 ) / ( t1 - t0 );
34110
34111 for ( var end = offset + stride; offset !== end; offset += 4 ) {
34112
34113 Quaternion.slerpFlat( result, 0, values, offset - stride, values, offset, alpha );
34114
34115 }
34116
34117 return result;
34118
34119 }
34120
34121} );
34122
34123/**
34124 *
34125 * A Track of quaternion keyframe values.
34126 *
34127 * @author Ben Houston / http://clara.io/
34128 * @author David Sarno / http://lighthaus.us/
34129 * @author tschw
34130 */
34131
34132function QuaternionKeyframeTrack( name, times, values, interpolation ) {
34133
34134 KeyframeTrack.call( this, name, times, values, interpolation );
34135
34136}
34137
34138QuaternionKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
34139
34140 constructor: QuaternionKeyframeTrack,
34141
34142 ValueTypeName: 'quaternion',
34143
34144 // ValueBufferType is inherited
34145
34146 DefaultInterpolation: InterpolateLinear,
34147
34148 InterpolantFactoryMethodLinear: function ( result ) {
34149
34150 return new QuaternionLinearInterpolant( this.times, this.values, this.getValueSize(), result );
34151
34152 },
34153
34154 InterpolantFactoryMethodSmooth: undefined // not yet implemented
34155
34156} );
34157
34158/**
34159 *
34160 * A Track of keyframe values that represent color.
34161 *
34162 *
34163 * @author Ben Houston / http://clara.io/
34164 * @author David Sarno / http://lighthaus.us/
34165 * @author tschw
34166 */
34167
34168function ColorKeyframeTrack( name, times, values, interpolation ) {
34169
34170 KeyframeTrack.call( this, name, times, values, interpolation );
34171
34172}
34173
34174ColorKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
34175
34176 constructor: ColorKeyframeTrack,
34177
34178 ValueTypeName: 'color'
34179
34180 // ValueBufferType is inherited
34181
34182 // DefaultInterpolation is inherited
34183
34184 // Note: Very basic implementation and nothing special yet.
34185 // However, this is the place for color space parameterization.
34186
34187} );
34188
34189/**
34190 *
34191 * A Track of numeric keyframe values.
34192 *
34193 * @author Ben Houston / http://clara.io/
34194 * @author David Sarno / http://lighthaus.us/
34195 * @author tschw
34196 */
34197
34198function NumberKeyframeTrack( name, times, values, interpolation ) {
34199
34200 KeyframeTrack.call( this, name, times, values, interpolation );
34201
34202}
34203
34204NumberKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
34205
34206 constructor: NumberKeyframeTrack,
34207
34208 ValueTypeName: 'number'
34209
34210 // ValueBufferType is inherited
34211
34212 // DefaultInterpolation is inherited
34213
34214} );
34215
34216/**
34217 * Fast and simple cubic spline interpolant.
34218 *
34219 * It was derived from a Hermitian construction setting the first derivative
34220 * at each sample position to the linear slope between neighboring positions
34221 * over their parameter interval.
34222 *
34223 * @author tschw
34224 */
34225
34226function CubicInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
34227
34228 Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );
34229
34230 this._weightPrev = - 0;
34231 this._offsetPrev = - 0;
34232 this._weightNext = - 0;
34233 this._offsetNext = - 0;
34234
34235}
34236
34237CubicInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {
34238
34239 constructor: CubicInterpolant,
34240
34241 DefaultSettings_: {
34242
34243 endingStart: ZeroCurvatureEnding,
34244 endingEnd: ZeroCurvatureEnding
34245
34246 },
34247
34248 intervalChanged_: function ( i1, t0, t1 ) {
34249
34250 var pp = this.parameterPositions,
34251 iPrev = i1 - 2,
34252 iNext = i1 + 1,
34253
34254 tPrev = pp[ iPrev ],
34255 tNext = pp[ iNext ];
34256
34257 if ( tPrev === undefined ) {
34258
34259 switch ( this.getSettings_().endingStart ) {
34260
34261 case ZeroSlopeEnding:
34262
34263 // f'(t0) = 0
34264 iPrev = i1;
34265 tPrev = 2 * t0 - t1;
34266
34267 break;
34268
34269 case WrapAroundEnding:
34270
34271 // use the other end of the curve
34272 iPrev = pp.length - 2;
34273 tPrev = t0 + pp[ iPrev ] - pp[ iPrev + 1 ];
34274
34275 break;
34276
34277 default: // ZeroCurvatureEnding
34278
34279 // f''(t0) = 0 a.k.a. Natural Spline
34280 iPrev = i1;
34281 tPrev = t1;
34282
34283 }
34284
34285 }
34286
34287 if ( tNext === undefined ) {
34288
34289 switch ( this.getSettings_().endingEnd ) {
34290
34291 case ZeroSlopeEnding:
34292
34293 // f'(tN) = 0
34294 iNext = i1;
34295 tNext = 2 * t1 - t0;
34296
34297 break;
34298
34299 case WrapAroundEnding:
34300
34301 // use the other end of the curve
34302 iNext = 1;
34303 tNext = t1 + pp[ 1 ] - pp[ 0 ];
34304
34305 break;
34306
34307 default: // ZeroCurvatureEnding
34308
34309 // f''(tN) = 0, a.k.a. Natural Spline
34310 iNext = i1 - 1;
34311 tNext = t0;
34312
34313 }
34314
34315 }
34316
34317 var halfDt = ( t1 - t0 ) * 0.5,
34318 stride = this.valueSize;
34319
34320 this._weightPrev = halfDt / ( t0 - tPrev );
34321 this._weightNext = halfDt / ( tNext - t1 );
34322 this._offsetPrev = iPrev * stride;
34323 this._offsetNext = iNext * stride;
34324
34325 },
34326
34327 interpolate_: function ( i1, t0, t, t1 ) {
34328
34329 var result = this.resultBuffer,
34330 values = this.sampleValues,
34331 stride = this.valueSize,
34332
34333 o1 = i1 * stride, o0 = o1 - stride,
34334 oP = this._offsetPrev, oN = this._offsetNext,
34335 wP = this._weightPrev, wN = this._weightNext,
34336
34337 p = ( t - t0 ) / ( t1 - t0 ),
34338 pp = p * p,
34339 ppp = pp * p;
34340
34341 // evaluate polynomials
34342
34343 var sP = - wP * ppp + 2 * wP * pp - wP * p;
34344 var s0 = ( 1 + wP ) * ppp + ( - 1.5 - 2 * wP ) * pp + ( - 0.5 + wP ) * p + 1;
34345 var s1 = ( - 1 - wN ) * ppp + ( 1.5 + wN ) * pp + 0.5 * p;
34346 var sN = wN * ppp - wN * pp;
34347
34348 // combine data linearly
34349
34350 for ( var i = 0; i !== stride; ++ i ) {
34351
34352 result[ i ] =
34353 sP * values[ oP + i ] +
34354 s0 * values[ o0 + i ] +
34355 s1 * values[ o1 + i ] +
34356 sN * values[ oN + i ];
34357
34358 }
34359
34360 return result;
34361
34362 }
34363
34364} );
34365
34366/**
34367 * @author tschw
34368 */
34369
34370function LinearInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
34371
34372 Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );
34373
34374}
34375
34376LinearInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {
34377
34378 constructor: LinearInterpolant,
34379
34380 interpolate_: function ( i1, t0, t, t1 ) {
34381
34382 var result = this.resultBuffer,
34383 values = this.sampleValues,
34384 stride = this.valueSize,
34385
34386 offset1 = i1 * stride,
34387 offset0 = offset1 - stride,
34388
34389 weight1 = ( t - t0 ) / ( t1 - t0 ),
34390 weight0 = 1 - weight1;
34391
34392 for ( var i = 0; i !== stride; ++ i ) {
34393
34394 result[ i ] =
34395 values[ offset0 + i ] * weight0 +
34396 values[ offset1 + i ] * weight1;
34397
34398 }
34399
34400 return result;
34401
34402 }
34403
34404} );
34405
34406/**
34407 *
34408 * Interpolant that evaluates to the sample value at the position preceeding
34409 * the parameter.
34410 *
34411 * @author tschw
34412 */
34413
34414function DiscreteInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
34415
34416 Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );
34417
34418}
34419
34420DiscreteInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {
34421
34422 constructor: DiscreteInterpolant,
34423
34424 interpolate_: function ( i1 /*, t0, t, t1 */ ) {
34425
34426 return this.copySampleValue_( i1 - 1 );
34427
34428 }
34429
34430} );
34431
34432/**
34433 * @author tschw
34434 * @author Ben Houston / http://clara.io/
34435 * @author David Sarno / http://lighthaus.us/
34436 */
34437
34438var AnimationUtils = {
34439
34440 // same as Array.prototype.slice, but also works on typed arrays
34441 arraySlice: function ( array, from, to ) {
34442
34443 if ( AnimationUtils.isTypedArray( array ) ) {
34444
34445 // in ios9 array.subarray(from, undefined) will return empty array
34446 // but array.subarray(from) or array.subarray(from, len) is correct
34447 return new array.constructor( array.subarray( from, to !== undefined ? to : array.length ) );
34448
34449 }
34450
34451 return array.slice( from, to );
34452
34453 },
34454
34455 // converts an array to a specific type
34456 convertArray: function ( array, type, forceClone ) {
34457
34458 if ( ! array || // let 'undefined' and 'null' pass
34459 ! forceClone && array.constructor === type ) return array;
34460
34461 if ( typeof type.BYTES_PER_ELEMENT === 'number' ) {
34462
34463 return new type( array ); // create typed array
34464
34465 }
34466
34467 return Array.prototype.slice.call( array ); // create Array
34468
34469 },
34470
34471 isTypedArray: function ( object ) {
34472
34473 return ArrayBuffer.isView( object ) &&
34474 ! ( object instanceof DataView );
34475
34476 },
34477
34478 // returns an array by which times and values can be sorted
34479 getKeyframeOrder: function ( times ) {
34480
34481 function compareTime( i, j ) {
34482
34483 return times[ i ] - times[ j ];
34484
34485 }
34486
34487 var n = times.length;
34488 var result = new Array( n );
34489 for ( var i = 0; i !== n; ++ i ) result[ i ] = i;
34490
34491 result.sort( compareTime );
34492
34493 return result;
34494
34495 },
34496
34497 // uses the array previously returned by 'getKeyframeOrder' to sort data
34498 sortedArray: function ( values, stride, order ) {
34499
34500 var nValues = values.length;
34501 var result = new values.constructor( nValues );
34502
34503 for ( var i = 0, dstOffset = 0; dstOffset !== nValues; ++ i ) {
34504
34505 var srcOffset = order[ i ] * stride;
34506
34507 for ( var j = 0; j !== stride; ++ j ) {
34508
34509 result[ dstOffset ++ ] = values[ srcOffset + j ];
34510
34511 }
34512
34513 }
34514
34515 return result;
34516
34517 },
34518
34519 // function for parsing AOS keyframe formats
34520 flattenJSON: function ( jsonKeys, times, values, valuePropertyName ) {
34521
34522 var i = 1, key = jsonKeys[ 0 ];
34523
34524 while ( key !== undefined && key[ valuePropertyName ] === undefined ) {
34525
34526 key = jsonKeys[ i ++ ];
34527
34528 }
34529
34530 if ( key === undefined ) return; // no data
34531
34532 var value = key[ valuePropertyName ];
34533 if ( value === undefined ) return; // no data
34534
34535 if ( Array.isArray( value ) ) {
34536
34537 do {
34538
34539 value = key[ valuePropertyName ];
34540
34541 if ( value !== undefined ) {
34542
34543 times.push( key.time );
34544 values.push.apply( values, value ); // push all elements
34545
34546 }
34547
34548 key = jsonKeys[ i ++ ];
34549
34550 } while ( key !== undefined );
34551
34552 } else if ( value.toArray !== undefined ) {
34553
34554 // ...assume THREE.Math-ish
34555
34556 do {
34557
34558 value = key[ valuePropertyName ];
34559
34560 if ( value !== undefined ) {
34561
34562 times.push( key.time );
34563 value.toArray( values, values.length );
34564
34565 }
34566
34567 key = jsonKeys[ i ++ ];
34568
34569 } while ( key !== undefined );
34570
34571 } else {
34572
34573 // otherwise push as-is
34574
34575 do {
34576
34577 value = key[ valuePropertyName ];
34578
34579 if ( value !== undefined ) {
34580
34581 times.push( key.time );
34582 values.push( value );
34583
34584 }
34585
34586 key = jsonKeys[ i ++ ];
34587
34588 } while ( key !== undefined );
34589
34590 }
34591
34592 }
34593
34594};
34595
34596/**
34597 *
34598 * A timed sequence of keyframes for a specific property.
34599 *
34600 *
34601 * @author Ben Houston / http://clara.io/
34602 * @author David Sarno / http://lighthaus.us/
34603 * @author tschw
34604 */
34605
34606function KeyframeTrack( name, times, values, interpolation ) {
34607
34608 if ( name === undefined ) throw new Error( 'THREE.KeyframeTrack: track name is undefined' );
34609 if ( times === undefined || times.length === 0 ) throw new Error( 'THREE.KeyframeTrack: no keyframes in track named ' + name );
34610
34611 this.name = name;
34612
34613 this.times = AnimationUtils.convertArray( times, this.TimeBufferType );
34614 this.values = AnimationUtils.convertArray( values, this.ValueBufferType );
34615
34616 this.setInterpolation( interpolation || this.DefaultInterpolation );
34617
34618 this.validate();
34619 this.optimize();
34620
34621}
34622
34623// Static methods:
34624
34625Object.assign( KeyframeTrack, {
34626
34627 // Serialization (in static context, because of constructor invocation
34628 // and automatic invocation of .toJSON):
34629
34630 parse: function ( json ) {
34631
34632 if ( json.type === undefined ) {
34633
34634 throw new Error( 'THREE.KeyframeTrack: track type undefined, can not parse' );
34635
34636 }
34637
34638 var trackType = KeyframeTrack._getTrackTypeForValueTypeName( json.type );
34639
34640 if ( json.times === undefined ) {
34641
34642 var times = [], values = [];
34643
34644 AnimationUtils.flattenJSON( json.keys, times, values, 'value' );
34645
34646 json.times = times;
34647 json.values = values;
34648
34649 }
34650
34651 // derived classes can define a static parse method
34652 if ( trackType.parse !== undefined ) {
34653
34654 return trackType.parse( json );
34655
34656 } else {
34657
34658 // by default, we assume a constructor compatible with the base
34659 return new trackType( json.name, json.times, json.values, json.interpolation );
34660
34661 }
34662
34663 },
34664
34665 toJSON: function ( track ) {
34666
34667 var trackType = track.constructor;
34668
34669 var json;
34670
34671 // derived classes can define a static toJSON method
34672 if ( trackType.toJSON !== undefined ) {
34673
34674 json = trackType.toJSON( track );
34675
34676 } else {
34677
34678 // by default, we assume the data can be serialized as-is
34679 json = {
34680
34681 'name': track.name,
34682 'times': AnimationUtils.convertArray( track.times, Array ),
34683 'values': AnimationUtils.convertArray( track.values, Array )
34684
34685 };
34686
34687 var interpolation = track.getInterpolation();
34688
34689 if ( interpolation !== track.DefaultInterpolation ) {
34690
34691 json.interpolation = interpolation;
34692
34693 }
34694
34695 }
34696
34697 json.type = track.ValueTypeName; // mandatory
34698
34699 return json;
34700
34701 },
34702
34703 _getTrackTypeForValueTypeName: function ( typeName ) {
34704
34705 switch ( typeName.toLowerCase() ) {
34706
34707 case 'scalar':
34708 case 'double':
34709 case 'float':
34710 case 'number':
34711 case 'integer':
34712
34713 return NumberKeyframeTrack;
34714
34715 case 'vector':
34716 case 'vector2':
34717 case 'vector3':
34718 case 'vector4':
34719
34720 return VectorKeyframeTrack;
34721
34722 case 'color':
34723
34724 return ColorKeyframeTrack;
34725
34726 case 'quaternion':
34727
34728 return QuaternionKeyframeTrack;
34729
34730 case 'bool':
34731 case 'boolean':
34732
34733 return BooleanKeyframeTrack;
34734
34735 case 'string':
34736
34737 return StringKeyframeTrack;
34738
34739 }
34740
34741 throw new Error( 'THREE.KeyframeTrack: Unsupported typeName: ' + typeName );
34742
34743 }
34744
34745} );
34746
34747Object.assign( KeyframeTrack.prototype, {
34748
34749 constructor: KeyframeTrack,
34750
34751 TimeBufferType: Float32Array,
34752
34753 ValueBufferType: Float32Array,
34754
34755 DefaultInterpolation: InterpolateLinear,
34756
34757 InterpolantFactoryMethodDiscrete: function ( result ) {
34758
34759 return new DiscreteInterpolant( this.times, this.values, this.getValueSize(), result );
34760
34761 },
34762
34763 InterpolantFactoryMethodLinear: function ( result ) {
34764
34765 return new LinearInterpolant( this.times, this.values, this.getValueSize(), result );
34766
34767 },
34768
34769 InterpolantFactoryMethodSmooth: function ( result ) {
34770
34771 return new CubicInterpolant( this.times, this.values, this.getValueSize(), result );
34772
34773 },
34774
34775 setInterpolation: function ( interpolation ) {
34776
34777 var factoryMethod;
34778
34779 switch ( interpolation ) {
34780
34781 case InterpolateDiscrete:
34782
34783 factoryMethod = this.InterpolantFactoryMethodDiscrete;
34784
34785 break;
34786
34787 case InterpolateLinear:
34788
34789 factoryMethod = this.InterpolantFactoryMethodLinear;
34790
34791 break;
34792
34793 case InterpolateSmooth:
34794
34795 factoryMethod = this.InterpolantFactoryMethodSmooth;
34796
34797 break;
34798
34799 }
34800
34801 if ( factoryMethod === undefined ) {
34802
34803 var message = "unsupported interpolation for " +
34804 this.ValueTypeName + " keyframe track named " + this.name;
34805
34806 if ( this.createInterpolant === undefined ) {
34807
34808 // fall back to default, unless the default itself is messed up
34809 if ( interpolation !== this.DefaultInterpolation ) {
34810
34811 this.setInterpolation( this.DefaultInterpolation );
34812
34813 } else {
34814
34815 throw new Error( message ); // fatal, in this case
34816
34817 }
34818
34819 }
34820
34821 console.warn( 'THREE.KeyframeTrack:', message );
34822 return;
34823
34824 }
34825
34826 this.createInterpolant = factoryMethod;
34827
34828 },
34829
34830 getInterpolation: function () {
34831
34832 switch ( this.createInterpolant ) {
34833
34834 case this.InterpolantFactoryMethodDiscrete:
34835
34836 return InterpolateDiscrete;
34837
34838 case this.InterpolantFactoryMethodLinear:
34839
34840 return InterpolateLinear;
34841
34842 case this.InterpolantFactoryMethodSmooth:
34843
34844 return InterpolateSmooth;
34845
34846 }
34847
34848 },
34849
34850 getValueSize: function () {
34851
34852 return this.values.length / this.times.length;
34853
34854 },
34855
34856 // move all keyframes either forwards or backwards in time
34857 shift: function ( timeOffset ) {
34858
34859 if ( timeOffset !== 0.0 ) {
34860
34861 var times = this.times;
34862
34863 for ( var i = 0, n = times.length; i !== n; ++ i ) {
34864
34865 times[ i ] += timeOffset;
34866
34867 }
34868
34869 }
34870
34871 return this;
34872
34873 },
34874
34875 // scale all keyframe times by a factor (useful for frame <-> seconds conversions)
34876 scale: function ( timeScale ) {
34877
34878 if ( timeScale !== 1.0 ) {
34879
34880 var times = this.times;
34881
34882 for ( var i = 0, n = times.length; i !== n; ++ i ) {
34883
34884 times[ i ] *= timeScale;
34885
34886 }
34887
34888 }
34889
34890 return this;
34891
34892 },
34893
34894 // removes keyframes before and after animation without changing any values within the range [startTime, endTime].
34895 // IMPORTANT: We do not shift around keys to the start of the track time, because for interpolated keys this will change their values
34896 trim: function ( startTime, endTime ) {
34897
34898 var times = this.times,
34899 nKeys = times.length,
34900 from = 0,
34901 to = nKeys - 1;
34902
34903 while ( from !== nKeys && times[ from ] < startTime ) {
34904
34905 ++ from;
34906
34907 }
34908
34909 while ( to !== - 1 && times[ to ] > endTime ) {
34910
34911 -- to;
34912
34913 }
34914
34915 ++ to; // inclusive -> exclusive bound
34916
34917 if ( from !== 0 || to !== nKeys ) {
34918
34919 // empty tracks are forbidden, so keep at least one keyframe
34920 if ( from >= to ) to = Math.max( to, 1 ), from = to - 1;
34921
34922 var stride = this.getValueSize();
34923 this.times = AnimationUtils.arraySlice( times, from, to );
34924 this.values = AnimationUtils.arraySlice( this.values, from * stride, to * stride );
34925
34926 }
34927
34928 return this;
34929
34930 },
34931
34932 // ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable
34933 validate: function () {
34934
34935 var valid = true;
34936
34937 var valueSize = this.getValueSize();
34938 if ( valueSize - Math.floor( valueSize ) !== 0 ) {
34939
34940 console.error( 'THREE.KeyframeTrack: Invalid value size in track.', this );
34941 valid = false;
34942
34943 }
34944
34945 var times = this.times,
34946 values = this.values,
34947
34948 nKeys = times.length;
34949
34950 if ( nKeys === 0 ) {
34951
34952 console.error( 'THREE.KeyframeTrack: Track is empty.', this );
34953 valid = false;
34954
34955 }
34956
34957 var prevTime = null;
34958
34959 for ( var i = 0; i !== nKeys; i ++ ) {
34960
34961 var currTime = times[ i ];
34962
34963 if ( typeof currTime === 'number' && isNaN( currTime ) ) {
34964
34965 console.error( 'THREE.KeyframeTrack: Time is not a valid number.', this, i, currTime );
34966 valid = false;
34967 break;
34968
34969 }
34970
34971 if ( prevTime !== null && prevTime > currTime ) {
34972
34973 console.error( 'THREE.KeyframeTrack: Out of order keys.', this, i, currTime, prevTime );
34974 valid = false;
34975 break;
34976
34977 }
34978
34979 prevTime = currTime;
34980
34981 }
34982
34983 if ( values !== undefined ) {
34984
34985 if ( AnimationUtils.isTypedArray( values ) ) {
34986
34987 for ( var i = 0, n = values.length; i !== n; ++ i ) {
34988
34989 var value = values[ i ];
34990
34991 if ( isNaN( value ) ) {
34992
34993 console.error( 'THREE.KeyframeTrack: Value is not a valid number.', this, i, value );
34994 valid = false;
34995 break;
34996
34997 }
34998
34999 }
35000
35001 }
35002
35003 }
35004
35005 return valid;
35006
35007 },
35008
35009 // removes equivalent sequential keys as common in morph target sequences
35010 // (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0)
35011 optimize: function () {
35012
35013 var times = this.times,
35014 values = this.values,
35015 stride = this.getValueSize(),
35016
35017 smoothInterpolation = this.getInterpolation() === InterpolateSmooth,
35018
35019 writeIndex = 1,
35020 lastIndex = times.length - 1;
35021
35022 for ( var i = 1; i < lastIndex; ++ i ) {
35023
35024 var keep = false;
35025
35026 var time = times[ i ];
35027 var timeNext = times[ i + 1 ];
35028
35029 // remove adjacent keyframes scheduled at the same time
35030
35031 if ( time !== timeNext && ( i !== 1 || time !== time[ 0 ] ) ) {
35032
35033 if ( ! smoothInterpolation ) {
35034
35035 // remove unnecessary keyframes same as their neighbors
35036
35037 var offset = i * stride,
35038 offsetP = offset - stride,
35039 offsetN = offset + stride;
35040
35041 for ( var j = 0; j !== stride; ++ j ) {
35042
35043 var value = values[ offset + j ];
35044
35045 if ( value !== values[ offsetP + j ] ||
35046 value !== values[ offsetN + j ] ) {
35047
35048 keep = true;
35049 break;
35050
35051 }
35052
35053 }
35054
35055 } else {
35056
35057 keep = true;
35058
35059 }
35060
35061 }
35062
35063 // in-place compaction
35064
35065 if ( keep ) {
35066
35067 if ( i !== writeIndex ) {
35068
35069 times[ writeIndex ] = times[ i ];
35070
35071 var readOffset = i * stride,
35072 writeOffset = writeIndex * stride;
35073
35074 for ( var j = 0; j !== stride; ++ j ) {
35075
35076 values[ writeOffset + j ] = values[ readOffset + j ];
35077
35078 }
35079
35080 }
35081
35082 ++ writeIndex;
35083
35084 }
35085
35086 }
35087
35088 // flush last keyframe (compaction looks ahead)
35089
35090 if ( lastIndex > 0 ) {
35091
35092 times[ writeIndex ] = times[ lastIndex ];
35093
35094 for ( var readOffset = lastIndex * stride, writeOffset = writeIndex * stride, j = 0; j !== stride; ++ j ) {
35095
35096 values[ writeOffset + j ] = values[ readOffset + j ];
35097
35098 }
35099
35100 ++ writeIndex;
35101
35102 }
35103
35104 if ( writeIndex !== times.length ) {
35105
35106 this.times = AnimationUtils.arraySlice( times, 0, writeIndex );
35107 this.values = AnimationUtils.arraySlice( values, 0, writeIndex * stride );
35108
35109 }
35110
35111 return this;
35112
35113 }
35114
35115} );
35116
35117/**
35118 *
35119 * A Track of vectored keyframe values.
35120 *
35121 *
35122 * @author Ben Houston / http://clara.io/
35123 * @author David Sarno / http://lighthaus.us/
35124 * @author tschw
35125 */
35126
35127function VectorKeyframeTrack( name, times, values, interpolation ) {
35128
35129 KeyframeTrack.call( this, name, times, values, interpolation );
35130
35131}
35132
35133VectorKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
35134
35135 constructor: VectorKeyframeTrack,
35136
35137 ValueTypeName: 'vector'
35138
35139 // ValueBufferType is inherited
35140
35141 // DefaultInterpolation is inherited
35142
35143} );
35144
35145/**
35146 *
35147 * Reusable set of Tracks that represent an animation.
35148 *
35149 * @author Ben Houston / http://clara.io/
35150 * @author David Sarno / http://lighthaus.us/
35151 */
35152
35153function AnimationClip( name, duration, tracks ) {
35154
35155 this.name = name;
35156 this.tracks = tracks;
35157 this.duration = ( duration !== undefined ) ? duration : - 1;
35158
35159 this.uuid = _Math.generateUUID();
35160
35161 // this means it should figure out its duration by scanning the tracks
35162 if ( this.duration < 0 ) {
35163
35164 this.resetDuration();
35165
35166 }
35167
35168 this.optimize();
35169
35170}
35171
35172Object.assign( AnimationClip, {
35173
35174 parse: function ( json ) {
35175
35176 var tracks = [],
35177 jsonTracks = json.tracks,
35178 frameTime = 1.0 / ( json.fps || 1.0 );
35179
35180 for ( var i = 0, n = jsonTracks.length; i !== n; ++ i ) {
35181
35182 tracks.push( KeyframeTrack.parse( jsonTracks[ i ] ).scale( frameTime ) );
35183
35184 }
35185
35186 return new AnimationClip( json.name, json.duration, tracks );
35187
35188 },
35189
35190 toJSON: function ( clip ) {
35191
35192 var tracks = [],
35193 clipTracks = clip.tracks;
35194
35195 var json = {
35196
35197 'name': clip.name,
35198 'duration': clip.duration,
35199 'tracks': tracks
35200
35201 };
35202
35203 for ( var i = 0, n = clipTracks.length; i !== n; ++ i ) {
35204
35205 tracks.push( KeyframeTrack.toJSON( clipTracks[ i ] ) );
35206
35207 }
35208
35209 return json;
35210
35211 },
35212
35213 CreateFromMorphTargetSequence: function ( name, morphTargetSequence, fps, noLoop ) {
35214
35215 var numMorphTargets = morphTargetSequence.length;
35216 var tracks = [];
35217
35218 for ( var i = 0; i < numMorphTargets; i ++ ) {
35219
35220 var times = [];
35221 var values = [];
35222
35223 times.push(
35224 ( i + numMorphTargets - 1 ) % numMorphTargets,
35225 i,
35226 ( i + 1 ) % numMorphTargets );
35227
35228 values.push( 0, 1, 0 );
35229
35230 var order = AnimationUtils.getKeyframeOrder( times );
35231 times = AnimationUtils.sortedArray( times, 1, order );
35232 values = AnimationUtils.sortedArray( values, 1, order );
35233
35234 // if there is a key at the first frame, duplicate it as the
35235 // last frame as well for perfect loop.
35236 if ( ! noLoop && times[ 0 ] === 0 ) {
35237
35238 times.push( numMorphTargets );
35239 values.push( values[ 0 ] );
35240
35241 }
35242
35243 tracks.push(
35244 new NumberKeyframeTrack(
35245 '.morphTargetInfluences[' + morphTargetSequence[ i ].name + ']',
35246 times, values
35247 ).scale( 1.0 / fps ) );
35248
35249 }
35250
35251 return new AnimationClip( name, - 1, tracks );
35252
35253 },
35254
35255 findByName: function ( objectOrClipArray, name ) {
35256
35257 var clipArray = objectOrClipArray;
35258
35259 if ( ! Array.isArray( objectOrClipArray ) ) {
35260
35261 var o = objectOrClipArray;
35262 clipArray = o.geometry && o.geometry.animations || o.animations;
35263
35264 }
35265
35266 for ( var i = 0; i < clipArray.length; i ++ ) {
35267
35268 if ( clipArray[ i ].name === name ) {
35269
35270 return clipArray[ i ];
35271
35272 }
35273
35274 }
35275
35276 return null;
35277
35278 },
35279
35280 CreateClipsFromMorphTargetSequences: function ( morphTargets, fps, noLoop ) {
35281
35282 var animationToMorphTargets = {};
35283
35284 // tested with https://regex101.com/ on trick sequences
35285 // such flamingo_flyA_003, flamingo_run1_003, crdeath0059
35286 var pattern = /^([\w-]*?)([\d]+)$/;
35287
35288 // sort morph target names into animation groups based
35289 // patterns like Walk_001, Walk_002, Run_001, Run_002
35290 for ( var i = 0, il = morphTargets.length; i < il; i ++ ) {
35291
35292 var morphTarget = morphTargets[ i ];
35293 var parts = morphTarget.name.match( pattern );
35294
35295 if ( parts && parts.length > 1 ) {
35296
35297 var name = parts[ 1 ];
35298
35299 var animationMorphTargets = animationToMorphTargets[ name ];
35300 if ( ! animationMorphTargets ) {
35301
35302 animationToMorphTargets[ name ] = animationMorphTargets = [];
35303
35304 }
35305
35306 animationMorphTargets.push( morphTarget );
35307
35308 }
35309
35310 }
35311
35312 var clips = [];
35313
35314 for ( var name in animationToMorphTargets ) {
35315
35316 clips.push( AnimationClip.CreateFromMorphTargetSequence( name, animationToMorphTargets[ name ], fps, noLoop ) );
35317
35318 }
35319
35320 return clips;
35321
35322 },
35323
35324 // parse the animation.hierarchy format
35325 parseAnimation: function ( animation, bones ) {
35326
35327 if ( ! animation ) {
35328
35329 console.error( 'THREE.AnimationClip: No animation in JSONLoader data.' );
35330 return null;
35331
35332 }
35333
35334 var addNonemptyTrack = function ( trackType, trackName, animationKeys, propertyName, destTracks ) {
35335
35336 // only return track if there are actually keys.
35337 if ( animationKeys.length !== 0 ) {
35338
35339 var times = [];
35340 var values = [];
35341
35342 AnimationUtils.flattenJSON( animationKeys, times, values, propertyName );
35343
35344 // empty keys are filtered out, so check again
35345 if ( times.length !== 0 ) {
35346
35347 destTracks.push( new trackType( trackName, times, values ) );
35348
35349 }
35350
35351 }
35352
35353 };
35354
35355 var tracks = [];
35356
35357 var clipName = animation.name || 'default';
35358 // automatic length determination in AnimationClip.
35359 var duration = animation.length || - 1;
35360 var fps = animation.fps || 30;
35361
35362 var hierarchyTracks = animation.hierarchy || [];
35363
35364 for ( var h = 0; h < hierarchyTracks.length; h ++ ) {
35365
35366 var animationKeys = hierarchyTracks[ h ].keys;
35367
35368 // skip empty tracks
35369 if ( ! animationKeys || animationKeys.length === 0 ) continue;
35370
35371 // process morph targets
35372 if ( animationKeys[ 0 ].morphTargets ) {
35373
35374 // figure out all morph targets used in this track
35375 var morphTargetNames = {};
35376
35377 for ( var k = 0; k < animationKeys.length; k ++ ) {
35378
35379 if ( animationKeys[ k ].morphTargets ) {
35380
35381 for ( var m = 0; m < animationKeys[ k ].morphTargets.length; m ++ ) {
35382
35383 morphTargetNames[ animationKeys[ k ].morphTargets[ m ] ] = - 1;
35384
35385 }
35386
35387 }
35388
35389 }
35390
35391 // create a track for each morph target with all zero
35392 // morphTargetInfluences except for the keys in which
35393 // the morphTarget is named.
35394 for ( var morphTargetName in morphTargetNames ) {
35395
35396 var times = [];
35397 var values = [];
35398
35399 for ( var m = 0; m !== animationKeys[ k ].morphTargets.length; ++ m ) {
35400
35401 var animationKey = animationKeys[ k ];
35402
35403 times.push( animationKey.time );
35404 values.push( ( animationKey.morphTarget === morphTargetName ) ? 1 : 0 );
35405
35406 }
35407
35408 tracks.push( new NumberKeyframeTrack( '.morphTargetInfluence[' + morphTargetName + ']', times, values ) );
35409
35410 }
35411
35412 duration = morphTargetNames.length * ( fps || 1.0 );
35413
35414 } else {
35415
35416 // ...assume skeletal animation
35417
35418 var boneName = '.bones[' + bones[ h ].name + ']';
35419
35420 addNonemptyTrack(
35421 VectorKeyframeTrack, boneName + '.position',
35422 animationKeys, 'pos', tracks );
35423
35424 addNonemptyTrack(
35425 QuaternionKeyframeTrack, boneName + '.quaternion',
35426 animationKeys, 'rot', tracks );
35427
35428 addNonemptyTrack(
35429 VectorKeyframeTrack, boneName + '.scale',
35430 animationKeys, 'scl', tracks );
35431
35432 }
35433
35434 }
35435
35436 if ( tracks.length === 0 ) {
35437
35438 return null;
35439
35440 }
35441
35442 var clip = new AnimationClip( clipName, duration, tracks );
35443
35444 return clip;
35445
35446 }
35447
35448} );
35449
35450Object.assign( AnimationClip.prototype, {
35451
35452 resetDuration: function () {
35453
35454 var tracks = this.tracks, duration = 0;
35455
35456 for ( var i = 0, n = tracks.length; i !== n; ++ i ) {
35457
35458 var track = this.tracks[ i ];
35459
35460 duration = Math.max( duration, track.times[ track.times.length - 1 ] );
35461
35462 }
35463
35464 this.duration = duration;
35465
35466 },
35467
35468 trim: function () {
35469
35470 for ( var i = 0; i < this.tracks.length; i ++ ) {
35471
35472 this.tracks[ i ].trim( 0, this.duration );
35473
35474 }
35475
35476 return this;
35477
35478 },
35479
35480 optimize: function () {
35481
35482 for ( var i = 0; i < this.tracks.length; i ++ ) {
35483
35484 this.tracks[ i ].optimize();
35485
35486 }
35487
35488 return this;
35489
35490 }
35491
35492} );
35493
35494/**
35495 * @author mrdoob / http://mrdoob.com/
35496 */
35497
35498function MaterialLoader( manager ) {
35499
35500 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
35501 this.textures = {};
35502
35503}
35504
35505Object.assign( MaterialLoader.prototype, {
35506
35507 load: function ( url, onLoad, onProgress, onError ) {
35508
35509 var scope = this;
35510
35511 var loader = new FileLoader( scope.manager );
35512 loader.load( url, function ( text ) {
35513
35514 onLoad( scope.parse( JSON.parse( text ) ) );
35515
35516 }, onProgress, onError );
35517
35518 },
35519
35520 setTextures: function ( value ) {
35521
35522 this.textures = value;
35523
35524 },
35525
35526 parse: function ( json ) {
35527
35528 var textures = this.textures;
35529
35530 function getTexture( name ) {
35531
35532 if ( textures[ name ] === undefined ) {
35533
35534 console.warn( 'THREE.MaterialLoader: Undefined texture', name );
35535
35536 }
35537
35538 return textures[ name ];
35539
35540 }
35541
35542 var material = new Materials[ json.type ]();
35543
35544 if ( json.uuid !== undefined ) material.uuid = json.uuid;
35545 if ( json.name !== undefined ) material.name = json.name;
35546 if ( json.color !== undefined ) material.color.setHex( json.color );
35547 if ( json.roughness !== undefined ) material.roughness = json.roughness;
35548 if ( json.metalness !== undefined ) material.metalness = json.metalness;
35549 if ( json.emissive !== undefined ) material.emissive.setHex( json.emissive );
35550 if ( json.specular !== undefined ) material.specular.setHex( json.specular );
35551 if ( json.shininess !== undefined ) material.shininess = json.shininess;
35552 if ( json.clearCoat !== undefined ) material.clearCoat = json.clearCoat;
35553 if ( json.clearCoatRoughness !== undefined ) material.clearCoatRoughness = json.clearCoatRoughness;
35554 if ( json.uniforms !== undefined ) material.uniforms = json.uniforms;
35555 if ( json.vertexShader !== undefined ) material.vertexShader = json.vertexShader;
35556 if ( json.fragmentShader !== undefined ) material.fragmentShader = json.fragmentShader;
35557 if ( json.vertexColors !== undefined ) material.vertexColors = json.vertexColors;
35558 if ( json.fog !== undefined ) material.fog = json.fog;
35559 if ( json.flatShading !== undefined ) material.flatShading = json.flatShading;
35560 if ( json.blending !== undefined ) material.blending = json.blending;
35561 if ( json.side !== undefined ) material.side = json.side;
35562 if ( json.opacity !== undefined ) material.opacity = json.opacity;
35563 if ( json.transparent !== undefined ) material.transparent = json.transparent;
35564 if ( json.alphaTest !== undefined ) material.alphaTest = json.alphaTest;
35565 if ( json.depthTest !== undefined ) material.depthTest = json.depthTest;
35566 if ( json.depthWrite !== undefined ) material.depthWrite = json.depthWrite;
35567 if ( json.colorWrite !== undefined ) material.colorWrite = json.colorWrite;
35568 if ( json.wireframe !== undefined ) material.wireframe = json.wireframe;
35569 if ( json.wireframeLinewidth !== undefined ) material.wireframeLinewidth = json.wireframeLinewidth;
35570 if ( json.wireframeLinecap !== undefined ) material.wireframeLinecap = json.wireframeLinecap;
35571 if ( json.wireframeLinejoin !== undefined ) material.wireframeLinejoin = json.wireframeLinejoin;
35572
35573 if ( json.rotation !== undefined ) material.rotation = json.rotation;
35574
35575 if ( json.linewidth !== 1 ) material.linewidth = json.linewidth;
35576 if ( json.dashSize !== undefined ) material.dashSize = json.dashSize;
35577 if ( json.gapSize !== undefined ) material.gapSize = json.gapSize;
35578 if ( json.scale !== undefined ) material.scale = json.scale;
35579
35580 if ( json.polygonOffset !== undefined ) material.polygonOffset = json.polygonOffset;
35581 if ( json.polygonOffsetFactor !== undefined ) material.polygonOffsetFactor = json.polygonOffsetFactor;
35582 if ( json.polygonOffsetUnits !== undefined ) material.polygonOffsetUnits = json.polygonOffsetUnits;
35583
35584 if ( json.skinning !== undefined ) material.skinning = json.skinning;
35585 if ( json.morphTargets !== undefined ) material.morphTargets = json.morphTargets;
35586 if ( json.dithering !== undefined ) material.dithering = json.dithering;
35587
35588 if ( json.visible !== undefined ) material.visible = json.visible;
35589 if ( json.userData !== undefined ) material.userData = json.userData;
35590
35591 // Deprecated
35592
35593 if ( json.shading !== undefined ) material.flatShading = json.shading === 1; // THREE.FlatShading
35594
35595 // for PointsMaterial
35596
35597 if ( json.size !== undefined ) material.size = json.size;
35598 if ( json.sizeAttenuation !== undefined ) material.sizeAttenuation = json.sizeAttenuation;
35599
35600 // maps
35601
35602 if ( json.map !== undefined ) material.map = getTexture( json.map );
35603
35604 if ( json.alphaMap !== undefined ) {
35605
35606 material.alphaMap = getTexture( json.alphaMap );
35607 material.transparent = true;
35608
35609 }
35610
35611 if ( json.bumpMap !== undefined ) material.bumpMap = getTexture( json.bumpMap );
35612 if ( json.bumpScale !== undefined ) material.bumpScale = json.bumpScale;
35613
35614 if ( json.normalMap !== undefined ) material.normalMap = getTexture( json.normalMap );
35615 if ( json.normalScale !== undefined ) {
35616
35617 var normalScale = json.normalScale;
35618
35619 if ( Array.isArray( normalScale ) === false ) {
35620
35621 // Blender exporter used to export a scalar. See #7459
35622
35623 normalScale = [ normalScale, normalScale ];
35624
35625 }
35626
35627 material.normalScale = new Vector2().fromArray( normalScale );
35628
35629 }
35630
35631 if ( json.displacementMap !== undefined ) material.displacementMap = getTexture( json.displacementMap );
35632 if ( json.displacementScale !== undefined ) material.displacementScale = json.displacementScale;
35633 if ( json.displacementBias !== undefined ) material.displacementBias = json.displacementBias;
35634
35635 if ( json.roughnessMap !== undefined ) material.roughnessMap = getTexture( json.roughnessMap );
35636 if ( json.metalnessMap !== undefined ) material.metalnessMap = getTexture( json.metalnessMap );
35637
35638 if ( json.emissiveMap !== undefined ) material.emissiveMap = getTexture( json.emissiveMap );
35639 if ( json.emissiveIntensity !== undefined ) material.emissiveIntensity = json.emissiveIntensity;
35640
35641 if ( json.specularMap !== undefined ) material.specularMap = getTexture( json.specularMap );
35642
35643 if ( json.envMap !== undefined ) material.envMap = getTexture( json.envMap );
35644
35645 if ( json.reflectivity !== undefined ) material.reflectivity = json.reflectivity;
35646
35647 if ( json.lightMap !== undefined ) material.lightMap = getTexture( json.lightMap );
35648 if ( json.lightMapIntensity !== undefined ) material.lightMapIntensity = json.lightMapIntensity;
35649
35650 if ( json.aoMap !== undefined ) material.aoMap = getTexture( json.aoMap );
35651 if ( json.aoMapIntensity !== undefined ) material.aoMapIntensity = json.aoMapIntensity;
35652
35653 if ( json.gradientMap !== undefined ) material.gradientMap = getTexture( json.gradientMap );
35654
35655 return material;
35656
35657 }
35658
35659} );
35660
35661/**
35662 * @author mrdoob / http://mrdoob.com/
35663 */
35664
35665function BufferGeometryLoader( manager ) {
35666
35667 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
35668
35669}
35670
35671Object.assign( BufferGeometryLoader.prototype, {
35672
35673 load: function ( url, onLoad, onProgress, onError ) {
35674
35675 var scope = this;
35676
35677 var loader = new FileLoader( scope.manager );
35678 loader.load( url, function ( text ) {
35679
35680 onLoad( scope.parse( JSON.parse( text ) ) );
35681
35682 }, onProgress, onError );
35683
35684 },
35685
35686 parse: function ( json ) {
35687
35688 var geometry = new BufferGeometry();
35689
35690 var index = json.data.index;
35691
35692 if ( index !== undefined ) {
35693
35694 var typedArray = new TYPED_ARRAYS[ index.type ]( index.array );
35695 geometry.setIndex( new BufferAttribute( typedArray, 1 ) );
35696
35697 }
35698
35699 var attributes = json.data.attributes;
35700
35701 for ( var key in attributes ) {
35702
35703 var attribute = attributes[ key ];
35704 var typedArray = new TYPED_ARRAYS[ attribute.type ]( attribute.array );
35705
35706 geometry.addAttribute( key, new BufferAttribute( typedArray, attribute.itemSize, attribute.normalized ) );
35707
35708 }
35709
35710 var groups = json.data.groups || json.data.drawcalls || json.data.offsets;
35711
35712 if ( groups !== undefined ) {
35713
35714 for ( var i = 0, n = groups.length; i !== n; ++ i ) {
35715
35716 var group = groups[ i ];
35717
35718 geometry.addGroup( group.start, group.count, group.materialIndex );
35719
35720 }
35721
35722 }
35723
35724 var boundingSphere = json.data.boundingSphere;
35725
35726 if ( boundingSphere !== undefined ) {
35727
35728 var center = new Vector3();
35729
35730 if ( boundingSphere.center !== undefined ) {
35731
35732 center.fromArray( boundingSphere.center );
35733
35734 }
35735
35736 geometry.boundingSphere = new Sphere( center, boundingSphere.radius );
35737
35738 }
35739
35740 return geometry;
35741
35742 }
35743
35744} );
35745
35746var TYPED_ARRAYS = {
35747 Int8Array: Int8Array,
35748 Uint8Array: Uint8Array,
35749 // Workaround for IE11 pre KB2929437. See #11440
35750 Uint8ClampedArray: typeof Uint8ClampedArray !== 'undefined' ? Uint8ClampedArray : Uint8Array,
35751 Int16Array: Int16Array,
35752 Uint16Array: Uint16Array,
35753 Int32Array: Int32Array,
35754 Uint32Array: Uint32Array,
35755 Float32Array: Float32Array,
35756 Float64Array: Float64Array
35757};
35758
35759/**
35760 * @author alteredq / http://alteredqualia.com/
35761 */
35762
35763function Loader() {}
35764
35765Loader.Handlers = {
35766
35767 handlers: [],
35768
35769 add: function ( regex, loader ) {
35770
35771 this.handlers.push( regex, loader );
35772
35773 },
35774
35775 get: function ( file ) {
35776
35777 var handlers = this.handlers;
35778
35779 for ( var i = 0, l = handlers.length; i < l; i += 2 ) {
35780
35781 var regex = handlers[ i ];
35782 var loader = handlers[ i + 1 ];
35783
35784 if ( regex.test( file ) ) {
35785
35786 return loader;
35787
35788 }
35789
35790 }
35791
35792 return null;
35793
35794 }
35795
35796};
35797
35798Object.assign( Loader.prototype, {
35799
35800 crossOrigin: undefined,
35801
35802 onLoadStart: function () {},
35803
35804 onLoadProgress: function () {},
35805
35806 onLoadComplete: function () {},
35807
35808 initMaterials: function ( materials, texturePath, crossOrigin ) {
35809
35810 var array = [];
35811
35812 for ( var i = 0; i < materials.length; ++ i ) {
35813
35814 array[ i ] = this.createMaterial( materials[ i ], texturePath, crossOrigin );
35815
35816 }
35817
35818 return array;
35819
35820 },
35821
35822 createMaterial: ( function () {
35823
35824 var BlendingMode = {
35825 NoBlending: NoBlending,
35826 NormalBlending: NormalBlending,
35827 AdditiveBlending: AdditiveBlending,
35828 SubtractiveBlending: SubtractiveBlending,
35829 MultiplyBlending: MultiplyBlending,
35830 CustomBlending: CustomBlending
35831 };
35832
35833 var color = new Color();
35834 var textureLoader = new TextureLoader();
35835 var materialLoader = new MaterialLoader();
35836
35837 return function createMaterial( m, texturePath, crossOrigin ) {
35838
35839 // convert from old material format
35840
35841 var textures = {};
35842
35843 function loadTexture( path, repeat, offset, wrap, anisotropy ) {
35844
35845 var fullPath = texturePath + path;
35846 var loader = Loader.Handlers.get( fullPath );
35847
35848 var texture;
35849
35850 if ( loader !== null ) {
35851
35852 texture = loader.load( fullPath );
35853
35854 } else {
35855
35856 textureLoader.setCrossOrigin( crossOrigin );
35857 texture = textureLoader.load( fullPath );
35858
35859 }
35860
35861 if ( repeat !== undefined ) {
35862
35863 texture.repeat.fromArray( repeat );
35864
35865 if ( repeat[ 0 ] !== 1 ) texture.wrapS = RepeatWrapping;
35866 if ( repeat[ 1 ] !== 1 ) texture.wrapT = RepeatWrapping;
35867
35868 }
35869
35870 if ( offset !== undefined ) {
35871
35872 texture.offset.fromArray( offset );
35873
35874 }
35875
35876 if ( wrap !== undefined ) {
35877
35878 if ( wrap[ 0 ] === 'repeat' ) texture.wrapS = RepeatWrapping;
35879 if ( wrap[ 0 ] === 'mirror' ) texture.wrapS = MirroredRepeatWrapping;
35880
35881 if ( wrap[ 1 ] === 'repeat' ) texture.wrapT = RepeatWrapping;
35882 if ( wrap[ 1 ] === 'mirror' ) texture.wrapT = MirroredRepeatWrapping;
35883
35884 }
35885
35886 if ( anisotropy !== undefined ) {
35887
35888 texture.anisotropy = anisotropy;
35889
35890 }
35891
35892 var uuid = _Math.generateUUID();
35893
35894 textures[ uuid ] = texture;
35895
35896 return uuid;
35897
35898 }
35899
35900 //
35901
35902 var json = {
35903 uuid: _Math.generateUUID(),
35904 type: 'MeshLambertMaterial'
35905 };
35906
35907 for ( var name in m ) {
35908
35909 var value = m[ name ];
35910
35911 switch ( name ) {
35912
35913 case 'DbgColor':
35914 case 'DbgIndex':
35915 case 'opticalDensity':
35916 case 'illumination':
35917 break;
35918 case 'DbgName':
35919 json.name = value;
35920 break;
35921 case 'blending':
35922 json.blending = BlendingMode[ value ];
35923 break;
35924 case 'colorAmbient':
35925 case 'mapAmbient':
35926 console.warn( 'THREE.Loader.createMaterial:', name, 'is no longer supported.' );
35927 break;
35928 case 'colorDiffuse':
35929 json.color = color.fromArray( value ).getHex();
35930 break;
35931 case 'colorSpecular':
35932 json.specular = color.fromArray( value ).getHex();
35933 break;
35934 case 'colorEmissive':
35935 json.emissive = color.fromArray( value ).getHex();
35936 break;
35937 case 'specularCoef':
35938 json.shininess = value;
35939 break;
35940 case 'shading':
35941 if ( value.toLowerCase() === 'basic' ) json.type = 'MeshBasicMaterial';
35942 if ( value.toLowerCase() === 'phong' ) json.type = 'MeshPhongMaterial';
35943 if ( value.toLowerCase() === 'standard' ) json.type = 'MeshStandardMaterial';
35944 break;
35945 case 'mapDiffuse':
35946 json.map = loadTexture( value, m.mapDiffuseRepeat, m.mapDiffuseOffset, m.mapDiffuseWrap, m.mapDiffuseAnisotropy );
35947 break;
35948 case 'mapDiffuseRepeat':
35949 case 'mapDiffuseOffset':
35950 case 'mapDiffuseWrap':
35951 case 'mapDiffuseAnisotropy':
35952 break;
35953 case 'mapEmissive':
35954 json.emissiveMap = loadTexture( value, m.mapEmissiveRepeat, m.mapEmissiveOffset, m.mapEmissiveWrap, m.mapEmissiveAnisotropy );
35955 break;
35956 case 'mapEmissiveRepeat':
35957 case 'mapEmissiveOffset':
35958 case 'mapEmissiveWrap':
35959 case 'mapEmissiveAnisotropy':
35960 break;
35961 case 'mapLight':
35962 json.lightMap = loadTexture( value, m.mapLightRepeat, m.mapLightOffset, m.mapLightWrap, m.mapLightAnisotropy );
35963 break;
35964 case 'mapLightRepeat':
35965 case 'mapLightOffset':
35966 case 'mapLightWrap':
35967 case 'mapLightAnisotropy':
35968 break;
35969 case 'mapAO':
35970 json.aoMap = loadTexture( value, m.mapAORepeat, m.mapAOOffset, m.mapAOWrap, m.mapAOAnisotropy );
35971 break;
35972 case 'mapAORepeat':
35973 case 'mapAOOffset':
35974 case 'mapAOWrap':
35975 case 'mapAOAnisotropy':
35976 break;
35977 case 'mapBump':
35978 json.bumpMap = loadTexture( value, m.mapBumpRepeat, m.mapBumpOffset, m.mapBumpWrap, m.mapBumpAnisotropy );
35979 break;
35980 case 'mapBumpScale':
35981 json.bumpScale = value;
35982 break;
35983 case 'mapBumpRepeat':
35984 case 'mapBumpOffset':
35985 case 'mapBumpWrap':
35986 case 'mapBumpAnisotropy':
35987 break;
35988 case 'mapNormal':
35989 json.normalMap = loadTexture( value, m.mapNormalRepeat, m.mapNormalOffset, m.mapNormalWrap, m.mapNormalAnisotropy );
35990 break;
35991 case 'mapNormalFactor':
35992 json.normalScale = value;
35993 break;
35994 case 'mapNormalRepeat':
35995 case 'mapNormalOffset':
35996 case 'mapNormalWrap':
35997 case 'mapNormalAnisotropy':
35998 break;
35999 case 'mapSpecular':
36000 json.specularMap = loadTexture( value, m.mapSpecularRepeat, m.mapSpecularOffset, m.mapSpecularWrap, m.mapSpecularAnisotropy );
36001 break;
36002 case 'mapSpecularRepeat':
36003 case 'mapSpecularOffset':
36004 case 'mapSpecularWrap':
36005 case 'mapSpecularAnisotropy':
36006 break;
36007 case 'mapMetalness':
36008 json.metalnessMap = loadTexture( value, m.mapMetalnessRepeat, m.mapMetalnessOffset, m.mapMetalnessWrap, m.mapMetalnessAnisotropy );
36009 break;
36010 case 'mapMetalnessRepeat':
36011 case 'mapMetalnessOffset':
36012 case 'mapMetalnessWrap':
36013 case 'mapMetalnessAnisotropy':
36014 break;
36015 case 'mapRoughness':
36016 json.roughnessMap = loadTexture( value, m.mapRoughnessRepeat, m.mapRoughnessOffset, m.mapRoughnessWrap, m.mapRoughnessAnisotropy );
36017 break;
36018 case 'mapRoughnessRepeat':
36019 case 'mapRoughnessOffset':
36020 case 'mapRoughnessWrap':
36021 case 'mapRoughnessAnisotropy':
36022 break;
36023 case 'mapAlpha':
36024 json.alphaMap = loadTexture( value, m.mapAlphaRepeat, m.mapAlphaOffset, m.mapAlphaWrap, m.mapAlphaAnisotropy );
36025 break;
36026 case 'mapAlphaRepeat':
36027 case 'mapAlphaOffset':
36028 case 'mapAlphaWrap':
36029 case 'mapAlphaAnisotropy':
36030 break;
36031 case 'flipSided':
36032 json.side = BackSide;
36033 break;
36034 case 'doubleSided':
36035 json.side = DoubleSide;
36036 break;
36037 case 'transparency':
36038 console.warn( 'THREE.Loader.createMaterial: transparency has been renamed to opacity' );
36039 json.opacity = value;
36040 break;
36041 case 'depthTest':
36042 case 'depthWrite':
36043 case 'colorWrite':
36044 case 'opacity':
36045 case 'reflectivity':
36046 case 'transparent':
36047 case 'visible':
36048 case 'wireframe':
36049 json[ name ] = value;
36050 break;
36051 case 'vertexColors':
36052 if ( value === true ) json.vertexColors = VertexColors;
36053 if ( value === 'face' ) json.vertexColors = FaceColors;
36054 break;
36055 default:
36056 console.error( 'THREE.Loader.createMaterial: Unsupported', name, value );
36057 break;
36058
36059 }
36060
36061 }
36062
36063 if ( json.type === 'MeshBasicMaterial' ) delete json.emissive;
36064 if ( json.type !== 'MeshPhongMaterial' ) delete json.specular;
36065
36066 if ( json.opacity < 1 ) json.transparent = true;
36067
36068 materialLoader.setTextures( textures );
36069
36070 return materialLoader.parse( json );
36071
36072 };
36073
36074 } )()
36075
36076} );
36077
36078/**
36079 * @author Don McCurdy / https://www.donmccurdy.com
36080 */
36081
36082var LoaderUtils = {
36083
36084 decodeText: function ( array ) {
36085
36086 if ( typeof TextDecoder !== 'undefined' ) {
36087
36088 return new TextDecoder().decode( array );
36089
36090 }
36091
36092 // Avoid the String.fromCharCode.apply(null, array) shortcut, which
36093 // throws a "maximum call stack size exceeded" error for large arrays.
36094
36095 var s = '';
36096
36097 for ( var i = 0, il = array.length; i < il; i ++ ) {
36098
36099 // Implicitly assumes little-endian.
36100 s += String.fromCharCode( array[ i ] );
36101
36102 }
36103
36104 // Merges multi-byte utf-8 characters.
36105 return decodeURIComponent( escape( s ) );
36106
36107 },
36108
36109 extractUrlBase: function ( url ) {
36110
36111 var index = url.lastIndexOf( '/' );
36112
36113 if ( index === - 1 ) return './';
36114
36115 return url.substr( 0, index + 1 );
36116
36117 }
36118
36119};
36120
36121/**
36122 * @author mrdoob / http://mrdoob.com/
36123 * @author alteredq / http://alteredqualia.com/
36124 */
36125
36126function JSONLoader( manager ) {
36127
36128 if ( typeof manager === 'boolean' ) {
36129
36130 console.warn( 'THREE.JSONLoader: showStatus parameter has been removed from constructor.' );
36131 manager = undefined;
36132
36133 }
36134
36135 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
36136
36137 this.withCredentials = false;
36138
36139}
36140
36141Object.assign( JSONLoader.prototype, {
36142
36143 load: function ( url, onLoad, onProgress, onError ) {
36144
36145 var scope = this;
36146
36147 var texturePath = this.texturePath && ( typeof this.texturePath === 'string' ) ? this.texturePath : LoaderUtils.extractUrlBase( url );
36148
36149 var loader = new FileLoader( this.manager );
36150 loader.setWithCredentials( this.withCredentials );
36151 loader.load( url, function ( text ) {
36152
36153 var json = JSON.parse( text );
36154 var metadata = json.metadata;
36155
36156 if ( metadata !== undefined ) {
36157
36158 var type = metadata.type;
36159
36160 if ( type !== undefined ) {
36161
36162 if ( type.toLowerCase() === 'object' ) {
36163
36164 console.error( 'THREE.JSONLoader: ' + url + ' should be loaded with THREE.ObjectLoader instead.' );
36165 return;
36166
36167 }
36168
36169 }
36170
36171 }
36172
36173 var object = scope.parse( json, texturePath );
36174 onLoad( object.geometry, object.materials );
36175
36176 }, onProgress, onError );
36177
36178 },
36179
36180 setTexturePath: function ( value ) {
36181
36182 this.texturePath = value;
36183
36184 },
36185
36186 parse: ( function () {
36187
36188 function parseModel( json, geometry ) {
36189
36190 function isBitSet( value, position ) {
36191
36192 return value & ( 1 << position );
36193
36194 }
36195
36196 var i, j, fi,
36197
36198 offset, zLength,
36199
36200 colorIndex, normalIndex, uvIndex, materialIndex,
36201
36202 type,
36203 isQuad,
36204 hasMaterial,
36205 hasFaceVertexUv,
36206 hasFaceNormal, hasFaceVertexNormal,
36207 hasFaceColor, hasFaceVertexColor,
36208
36209 vertex, face, faceA, faceB, hex, normal,
36210
36211 uvLayer, uv, u, v,
36212
36213 faces = json.faces,
36214 vertices = json.vertices,
36215 normals = json.normals,
36216 colors = json.colors,
36217
36218 scale = json.scale,
36219
36220 nUvLayers = 0;
36221
36222
36223 if ( json.uvs !== undefined ) {
36224
36225 // disregard empty arrays
36226
36227 for ( i = 0; i < json.uvs.length; i ++ ) {
36228
36229 if ( json.uvs[ i ].length ) nUvLayers ++;
36230
36231 }
36232
36233 for ( i = 0; i < nUvLayers; i ++ ) {
36234
36235 geometry.faceVertexUvs[ i ] = [];
36236
36237 }
36238
36239 }
36240
36241 offset = 0;
36242 zLength = vertices.length;
36243
36244 while ( offset < zLength ) {
36245
36246 vertex = new Vector3();
36247
36248 vertex.x = vertices[ offset ++ ] * scale;
36249 vertex.y = vertices[ offset ++ ] * scale;
36250 vertex.z = vertices[ offset ++ ] * scale;
36251
36252 geometry.vertices.push( vertex );
36253
36254 }
36255
36256 offset = 0;
36257 zLength = faces.length;
36258
36259 while ( offset < zLength ) {
36260
36261 type = faces[ offset ++ ];
36262
36263 isQuad = isBitSet( type, 0 );
36264 hasMaterial = isBitSet( type, 1 );
36265 hasFaceVertexUv = isBitSet( type, 3 );
36266 hasFaceNormal = isBitSet( type, 4 );
36267 hasFaceVertexNormal = isBitSet( type, 5 );
36268 hasFaceColor = isBitSet( type, 6 );
36269 hasFaceVertexColor = isBitSet( type, 7 );
36270
36271 // console.log("type", type, "bits", isQuad, hasMaterial, hasFaceVertexUv, hasFaceNormal, hasFaceVertexNormal, hasFaceColor, hasFaceVertexColor);
36272
36273 if ( isQuad ) {
36274
36275 faceA = new Face3();
36276 faceA.a = faces[ offset ];
36277 faceA.b = faces[ offset + 1 ];
36278 faceA.c = faces[ offset + 3 ];
36279
36280 faceB = new Face3();
36281 faceB.a = faces[ offset + 1 ];
36282 faceB.b = faces[ offset + 2 ];
36283 faceB.c = faces[ offset + 3 ];
36284
36285 offset += 4;
36286
36287 if ( hasMaterial ) {
36288
36289 materialIndex = faces[ offset ++ ];
36290 faceA.materialIndex = materialIndex;
36291 faceB.materialIndex = materialIndex;
36292
36293 }
36294
36295 // to get face <=> uv index correspondence
36296
36297 fi = geometry.faces.length;
36298
36299 if ( hasFaceVertexUv ) {
36300
36301 for ( i = 0; i < nUvLayers; i ++ ) {
36302
36303 uvLayer = json.uvs[ i ];
36304
36305 geometry.faceVertexUvs[ i ][ fi ] = [];
36306 geometry.faceVertexUvs[ i ][ fi + 1 ] = [];
36307
36308 for ( j = 0; j < 4; j ++ ) {
36309
36310 uvIndex = faces[ offset ++ ];
36311
36312 u = uvLayer[ uvIndex * 2 ];
36313 v = uvLayer[ uvIndex * 2 + 1 ];
36314
36315 uv = new Vector2( u, v );
36316
36317 if ( j !== 2 ) geometry.faceVertexUvs[ i ][ fi ].push( uv );
36318 if ( j !== 0 ) geometry.faceVertexUvs[ i ][ fi + 1 ].push( uv );
36319
36320 }
36321
36322 }
36323
36324 }
36325
36326 if ( hasFaceNormal ) {
36327
36328 normalIndex = faces[ offset ++ ] * 3;
36329
36330 faceA.normal.set(
36331 normals[ normalIndex ++ ],
36332 normals[ normalIndex ++ ],
36333 normals[ normalIndex ]
36334 );
36335
36336 faceB.normal.copy( faceA.normal );
36337
36338 }
36339
36340 if ( hasFaceVertexNormal ) {
36341
36342 for ( i = 0; i < 4; i ++ ) {
36343
36344 normalIndex = faces[ offset ++ ] * 3;
36345
36346 normal = new Vector3(
36347 normals[ normalIndex ++ ],
36348 normals[ normalIndex ++ ],
36349 normals[ normalIndex ]
36350 );
36351
36352
36353 if ( i !== 2 ) faceA.vertexNormals.push( normal );
36354 if ( i !== 0 ) faceB.vertexNormals.push( normal );
36355
36356 }
36357
36358 }
36359
36360
36361 if ( hasFaceColor ) {
36362
36363 colorIndex = faces[ offset ++ ];
36364 hex = colors[ colorIndex ];
36365
36366 faceA.color.setHex( hex );
36367 faceB.color.setHex( hex );
36368
36369 }
36370
36371
36372 if ( hasFaceVertexColor ) {
36373
36374 for ( i = 0; i < 4; i ++ ) {
36375
36376 colorIndex = faces[ offset ++ ];
36377 hex = colors[ colorIndex ];
36378
36379 if ( i !== 2 ) faceA.vertexColors.push( new Color( hex ) );
36380 if ( i !== 0 ) faceB.vertexColors.push( new Color( hex ) );
36381
36382 }
36383
36384 }
36385
36386 geometry.faces.push( faceA );
36387 geometry.faces.push( faceB );
36388
36389 } else {
36390
36391 face = new Face3();
36392 face.a = faces[ offset ++ ];
36393 face.b = faces[ offset ++ ];
36394 face.c = faces[ offset ++ ];
36395
36396 if ( hasMaterial ) {
36397
36398 materialIndex = faces[ offset ++ ];
36399 face.materialIndex = materialIndex;
36400
36401 }
36402
36403 // to get face <=> uv index correspondence
36404
36405 fi = geometry.faces.length;
36406
36407 if ( hasFaceVertexUv ) {
36408
36409 for ( i = 0; i < nUvLayers; i ++ ) {
36410
36411 uvLayer = json.uvs[ i ];
36412
36413 geometry.faceVertexUvs[ i ][ fi ] = [];
36414
36415 for ( j = 0; j < 3; j ++ ) {
36416
36417 uvIndex = faces[ offset ++ ];
36418
36419 u = uvLayer[ uvIndex * 2 ];
36420 v = uvLayer[ uvIndex * 2 + 1 ];
36421
36422 uv = new Vector2( u, v );
36423
36424 geometry.faceVertexUvs[ i ][ fi ].push( uv );
36425
36426 }
36427
36428 }
36429
36430 }
36431
36432 if ( hasFaceNormal ) {
36433
36434 normalIndex = faces[ offset ++ ] * 3;
36435
36436 face.normal.set(
36437 normals[ normalIndex ++ ],
36438 normals[ normalIndex ++ ],
36439 normals[ normalIndex ]
36440 );
36441
36442 }
36443
36444 if ( hasFaceVertexNormal ) {
36445
36446 for ( i = 0; i < 3; i ++ ) {
36447
36448 normalIndex = faces[ offset ++ ] * 3;
36449
36450 normal = new Vector3(
36451 normals[ normalIndex ++ ],
36452 normals[ normalIndex ++ ],
36453 normals[ normalIndex ]
36454 );
36455
36456 face.vertexNormals.push( normal );
36457
36458 }
36459
36460 }
36461
36462
36463 if ( hasFaceColor ) {
36464
36465 colorIndex = faces[ offset ++ ];
36466 face.color.setHex( colors[ colorIndex ] );
36467
36468 }
36469
36470
36471 if ( hasFaceVertexColor ) {
36472
36473 for ( i = 0; i < 3; i ++ ) {
36474
36475 colorIndex = faces[ offset ++ ];
36476 face.vertexColors.push( new Color( colors[ colorIndex ] ) );
36477
36478 }
36479
36480 }
36481
36482 geometry.faces.push( face );
36483
36484 }
36485
36486 }
36487
36488 }
36489
36490 function parseSkin( json, geometry ) {
36491
36492 var influencesPerVertex = ( json.influencesPerVertex !== undefined ) ? json.influencesPerVertex : 2;
36493
36494 if ( json.skinWeights ) {
36495
36496 for ( var i = 0, l = json.skinWeights.length; i < l; i += influencesPerVertex ) {
36497
36498 var x = json.skinWeights[ i ];
36499 var y = ( influencesPerVertex > 1 ) ? json.skinWeights[ i + 1 ] : 0;
36500 var z = ( influencesPerVertex > 2 ) ? json.skinWeights[ i + 2 ] : 0;
36501 var w = ( influencesPerVertex > 3 ) ? json.skinWeights[ i + 3 ] : 0;
36502
36503 geometry.skinWeights.push( new Vector4( x, y, z, w ) );
36504
36505 }
36506
36507 }
36508
36509 if ( json.skinIndices ) {
36510
36511 for ( var i = 0, l = json.skinIndices.length; i < l; i += influencesPerVertex ) {
36512
36513 var a = json.skinIndices[ i ];
36514 var b = ( influencesPerVertex > 1 ) ? json.skinIndices[ i + 1 ] : 0;
36515 var c = ( influencesPerVertex > 2 ) ? json.skinIndices[ i + 2 ] : 0;
36516 var d = ( influencesPerVertex > 3 ) ? json.skinIndices[ i + 3 ] : 0;
36517
36518 geometry.skinIndices.push( new Vector4( a, b, c, d ) );
36519
36520 }
36521
36522 }
36523
36524 geometry.bones = json.bones;
36525
36526 if ( geometry.bones && geometry.bones.length > 0 && ( geometry.skinWeights.length !== geometry.skinIndices.length || geometry.skinIndices.length !== geometry.vertices.length ) ) {
36527
36528 console.warn( 'When skinning, number of vertices (' + geometry.vertices.length + '), skinIndices (' +
36529 geometry.skinIndices.length + '), and skinWeights (' + geometry.skinWeights.length + ') should match.' );
36530
36531 }
36532
36533 }
36534
36535 function parseMorphing( json, geometry ) {
36536
36537 var scale = json.scale;
36538
36539 if ( json.morphTargets !== undefined ) {
36540
36541 for ( var i = 0, l = json.morphTargets.length; i < l; i ++ ) {
36542
36543 geometry.morphTargets[ i ] = {};
36544 geometry.morphTargets[ i ].name = json.morphTargets[ i ].name;
36545 geometry.morphTargets[ i ].vertices = [];
36546
36547 var dstVertices = geometry.morphTargets[ i ].vertices;
36548 var srcVertices = json.morphTargets[ i ].vertices;
36549
36550 for ( var v = 0, vl = srcVertices.length; v < vl; v += 3 ) {
36551
36552 var vertex = new Vector3();
36553 vertex.x = srcVertices[ v ] * scale;
36554 vertex.y = srcVertices[ v + 1 ] * scale;
36555 vertex.z = srcVertices[ v + 2 ] * scale;
36556
36557 dstVertices.push( vertex );
36558
36559 }
36560
36561 }
36562
36563 }
36564
36565 if ( json.morphColors !== undefined && json.morphColors.length > 0 ) {
36566
36567 console.warn( 'THREE.JSONLoader: "morphColors" no longer supported. Using them as face colors.' );
36568
36569 var faces = geometry.faces;
36570 var morphColors = json.morphColors[ 0 ].colors;
36571
36572 for ( var i = 0, l = faces.length; i < l; i ++ ) {
36573
36574 faces[ i ].color.fromArray( morphColors, i * 3 );
36575
36576 }
36577
36578 }
36579
36580 }
36581
36582 function parseAnimations( json, geometry ) {
36583
36584 var outputAnimations = [];
36585
36586 // parse old style Bone/Hierarchy animations
36587 var animations = [];
36588
36589 if ( json.animation !== undefined ) {
36590
36591 animations.push( json.animation );
36592
36593 }
36594
36595 if ( json.animations !== undefined ) {
36596
36597 if ( json.animations.length ) {
36598
36599 animations = animations.concat( json.animations );
36600
36601 } else {
36602
36603 animations.push( json.animations );
36604
36605 }
36606
36607 }
36608
36609 for ( var i = 0; i < animations.length; i ++ ) {
36610
36611 var clip = AnimationClip.parseAnimation( animations[ i ], geometry.bones );
36612 if ( clip ) outputAnimations.push( clip );
36613
36614 }
36615
36616 // parse implicit morph animations
36617 if ( geometry.morphTargets ) {
36618
36619 // TODO: Figure out what an appropraite FPS is for morph target animations -- defaulting to 10, but really it is completely arbitrary.
36620 var morphAnimationClips = AnimationClip.CreateClipsFromMorphTargetSequences( geometry.morphTargets, 10 );
36621 outputAnimations = outputAnimations.concat( morphAnimationClips );
36622
36623 }
36624
36625 if ( outputAnimations.length > 0 ) geometry.animations = outputAnimations;
36626
36627 }
36628
36629 return function parse( json, texturePath ) {
36630
36631 if ( json.data !== undefined ) {
36632
36633 // Geometry 4.0 spec
36634 json = json.data;
36635
36636 }
36637
36638 if ( json.scale !== undefined ) {
36639
36640 json.scale = 1.0 / json.scale;
36641
36642 } else {
36643
36644 json.scale = 1.0;
36645
36646 }
36647
36648 var geometry = new Geometry();
36649
36650 parseModel( json, geometry );
36651 parseSkin( json, geometry );
36652 parseMorphing( json, geometry );
36653 parseAnimations( json, geometry );
36654
36655 geometry.computeFaceNormals();
36656 geometry.computeBoundingSphere();
36657
36658 if ( json.materials === undefined || json.materials.length === 0 ) {
36659
36660 return { geometry: geometry };
36661
36662 } else {
36663
36664 var materials = Loader.prototype.initMaterials( json.materials, texturePath, this.crossOrigin );
36665
36666 return { geometry: geometry, materials: materials };
36667
36668 }
36669
36670 };
36671
36672 } )()
36673
36674} );
36675
36676/**
36677 * @author mrdoob / http://mrdoob.com/
36678 */
36679
36680function ObjectLoader( manager ) {
36681
36682 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
36683 this.texturePath = '';
36684
36685}
36686
36687Object.assign( ObjectLoader.prototype, {
36688
36689 load: function ( url, onLoad, onProgress, onError ) {
36690
36691 if ( this.texturePath === '' ) {
36692
36693 this.texturePath = url.substring( 0, url.lastIndexOf( '/' ) + 1 );
36694
36695 }
36696
36697 var scope = this;
36698
36699 var loader = new FileLoader( scope.manager );
36700 loader.load( url, function ( text ) {
36701
36702 var json = null;
36703
36704 try {
36705
36706 json = JSON.parse( text );
36707
36708 } catch ( error ) {
36709
36710 if ( onError !== undefined ) onError( error );
36711
36712 console.error( 'THREE:ObjectLoader: Can\'t parse ' + url + '.', error.message );
36713
36714 return;
36715
36716 }
36717
36718 var metadata = json.metadata;
36719
36720 if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) {
36721
36722 console.error( 'THREE.ObjectLoader: Can\'t load ' + url + '. Use THREE.JSONLoader instead.' );
36723 return;
36724
36725 }
36726
36727 scope.parse( json, onLoad );
36728
36729 }, onProgress, onError );
36730
36731 },
36732
36733 setTexturePath: function ( value ) {
36734
36735 this.texturePath = value;
36736
36737 },
36738
36739 setCrossOrigin: function ( value ) {
36740
36741 this.crossOrigin = value;
36742
36743 },
36744
36745 parse: function ( json, onLoad ) {
36746
36747 var shapes = this.parseShape( json.shapes );
36748 var geometries = this.parseGeometries( json.geometries, shapes );
36749
36750 var images = this.parseImages( json.images, function () {
36751
36752 if ( onLoad !== undefined ) onLoad( object );
36753
36754 } );
36755
36756 var textures = this.parseTextures( json.textures, images );
36757 var materials = this.parseMaterials( json.materials, textures );
36758
36759 var object = this.parseObject( json.object, geometries, materials );
36760
36761 if ( json.animations ) {
36762
36763 object.animations = this.parseAnimations( json.animations );
36764
36765 }
36766
36767 if ( json.images === undefined || json.images.length === 0 ) {
36768
36769 if ( onLoad !== undefined ) onLoad( object );
36770
36771 }
36772
36773 return object;
36774
36775 },
36776
36777 parseShape: function ( json ) {
36778
36779 var shapes = {};
36780
36781 if ( json !== undefined ) {
36782
36783 for ( var i = 0, l = json.length; i < l; i ++ ) {
36784
36785 var shape = new Shape().fromJSON( json[ i ] );
36786
36787 shapes[ shape.uuid ] = shape;
36788
36789 }
36790
36791 }
36792
36793 return shapes;
36794
36795 },
36796
36797 parseGeometries: function ( json, shapes ) {
36798
36799 var geometries = {};
36800
36801 if ( json !== undefined ) {
36802
36803 var geometryLoader = new JSONLoader();
36804 var bufferGeometryLoader = new BufferGeometryLoader();
36805
36806 for ( var i = 0, l = json.length; i < l; i ++ ) {
36807
36808 var geometry;
36809 var data = json[ i ];
36810
36811 switch ( data.type ) {
36812
36813 case 'PlaneGeometry':
36814 case 'PlaneBufferGeometry':
36815
36816 geometry = new Geometries[ data.type ](
36817 data.width,
36818 data.height,
36819 data.widthSegments,
36820 data.heightSegments
36821 );
36822
36823 break;
36824
36825 case 'BoxGeometry':
36826 case 'BoxBufferGeometry':
36827 case 'CubeGeometry': // backwards compatible
36828
36829 geometry = new Geometries[ data.type ](
36830 data.width,
36831 data.height,
36832 data.depth,
36833 data.widthSegments,
36834 data.heightSegments,
36835 data.depthSegments
36836 );
36837
36838 break;
36839
36840 case 'CircleGeometry':
36841 case 'CircleBufferGeometry':
36842
36843 geometry = new Geometries[ data.type ](
36844 data.radius,
36845 data.segments,
36846 data.thetaStart,
36847 data.thetaLength
36848 );
36849
36850 break;
36851
36852 case 'CylinderGeometry':
36853 case 'CylinderBufferGeometry':
36854
36855 geometry = new Geometries[ data.type ](
36856 data.radiusTop,
36857 data.radiusBottom,
36858 data.height,
36859 data.radialSegments,
36860 data.heightSegments,
36861 data.openEnded,
36862 data.thetaStart,
36863 data.thetaLength
36864 );
36865
36866 break;
36867
36868 case 'ConeGeometry':
36869 case 'ConeBufferGeometry':
36870
36871 geometry = new Geometries[ data.type ](
36872 data.radius,
36873 data.height,
36874 data.radialSegments,
36875 data.heightSegments,
36876 data.openEnded,
36877 data.thetaStart,
36878 data.thetaLength
36879 );
36880
36881 break;
36882
36883 case 'SphereGeometry':
36884 case 'SphereBufferGeometry':
36885
36886 geometry = new Geometries[ data.type ](
36887 data.radius,
36888 data.widthSegments,
36889 data.heightSegments,
36890 data.phiStart,
36891 data.phiLength,
36892 data.thetaStart,
36893 data.thetaLength
36894 );
36895
36896 break;
36897
36898 case 'DodecahedronGeometry':
36899 case 'DodecahedronBufferGeometry':
36900 case 'IcosahedronGeometry':
36901 case 'IcosahedronBufferGeometry':
36902 case 'OctahedronGeometry':
36903 case 'OctahedronBufferGeometry':
36904 case 'TetrahedronGeometry':
36905 case 'TetrahedronBufferGeometry':
36906
36907 geometry = new Geometries[ data.type ](
36908 data.radius,
36909 data.detail
36910 );
36911
36912 break;
36913
36914 case 'RingGeometry':
36915 case 'RingBufferGeometry':
36916
36917 geometry = new Geometries[ data.type ](
36918 data.innerRadius,
36919 data.outerRadius,
36920 data.thetaSegments,
36921 data.phiSegments,
36922 data.thetaStart,
36923 data.thetaLength
36924 );
36925
36926 break;
36927
36928 case 'TorusGeometry':
36929 case 'TorusBufferGeometry':
36930
36931 geometry = new Geometries[ data.type ](
36932 data.radius,
36933 data.tube,
36934 data.radialSegments,
36935 data.tubularSegments,
36936 data.arc
36937 );
36938
36939 break;
36940
36941 case 'TorusKnotGeometry':
36942 case 'TorusKnotBufferGeometry':
36943
36944 geometry = new Geometries[ data.type ](
36945 data.radius,
36946 data.tube,
36947 data.tubularSegments,
36948 data.radialSegments,
36949 data.p,
36950 data.q
36951 );
36952
36953 break;
36954
36955 case 'LatheGeometry':
36956 case 'LatheBufferGeometry':
36957
36958 geometry = new Geometries[ data.type ](
36959 data.points,
36960 data.segments,
36961 data.phiStart,
36962 data.phiLength
36963 );
36964
36965 break;
36966
36967 case 'PolyhedronGeometry':
36968 case 'PolyhedronBufferGeometry':
36969
36970 geometry = new Geometries[ data.type ](
36971 data.vertices,
36972 data.indices,
36973 data.radius,
36974 data.details
36975 );
36976
36977 break;
36978
36979 case 'ShapeGeometry':
36980 case 'ShapeBufferGeometry':
36981
36982 var geometryShapes = [];
36983
36984 for ( var j = 0, jl = data.shapes.length; j < jl; j ++ ) {
36985
36986 var shape = shapes[ data.shapes[ j ] ];
36987
36988 geometryShapes.push( shape );
36989
36990 }
36991
36992 geometry = new Geometries[ data.type ](
36993 geometryShapes,
36994 data.curveSegments
36995 );
36996
36997 break;
36998
36999 case 'BufferGeometry':
37000
37001 geometry = bufferGeometryLoader.parse( data );
37002
37003 break;
37004
37005 case 'Geometry':
37006
37007 geometry = geometryLoader.parse( data, this.texturePath ).geometry;
37008
37009 break;
37010
37011 default:
37012
37013 console.warn( 'THREE.ObjectLoader: Unsupported geometry type "' + data.type + '"' );
37014
37015 continue;
37016
37017 }
37018
37019 geometry.uuid = data.uuid;
37020
37021 if ( data.name !== undefined ) geometry.name = data.name;
37022
37023 geometries[ data.uuid ] = geometry;
37024
37025 }
37026
37027 }
37028
37029 return geometries;
37030
37031 },
37032
37033 parseMaterials: function ( json, textures ) {
37034
37035 var materials = {};
37036
37037 if ( json !== undefined ) {
37038
37039 var loader = new MaterialLoader();
37040 loader.setTextures( textures );
37041
37042 for ( var i = 0, l = json.length; i < l; i ++ ) {
37043
37044 var data = json[ i ];
37045
37046 if ( data.type === 'MultiMaterial' ) {
37047
37048 // Deprecated
37049
37050 var array = [];
37051
37052 for ( var j = 0; j < data.materials.length; j ++ ) {
37053
37054 array.push( loader.parse( data.materials[ j ] ) );
37055
37056 }
37057
37058 materials[ data.uuid ] = array;
37059
37060 } else {
37061
37062 materials[ data.uuid ] = loader.parse( data );
37063
37064 }
37065
37066 }
37067
37068 }
37069
37070 return materials;
37071
37072 },
37073
37074 parseAnimations: function ( json ) {
37075
37076 var animations = [];
37077
37078 for ( var i = 0; i < json.length; i ++ ) {
37079
37080 var clip = AnimationClip.parse( json[ i ] );
37081
37082 animations.push( clip );
37083
37084 }
37085
37086 return animations;
37087
37088 },
37089
37090 parseImages: function ( json, onLoad ) {
37091
37092 var scope = this;
37093 var images = {};
37094
37095 function loadImage( url ) {
37096
37097 scope.manager.itemStart( url );
37098
37099 return loader.load( url, function () {
37100
37101 scope.manager.itemEnd( url );
37102
37103 }, undefined, function () {
37104
37105 scope.manager.itemEnd( url );
37106 scope.manager.itemError( url );
37107
37108 } );
37109
37110 }
37111
37112 if ( json !== undefined && json.length > 0 ) {
37113
37114 var manager = new LoadingManager( onLoad );
37115
37116 var loader = new ImageLoader( manager );
37117 loader.setCrossOrigin( this.crossOrigin );
37118
37119 for ( var i = 0, l = json.length; i < l; i ++ ) {
37120
37121 var image = json[ i ];
37122 var path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( image.url ) ? image.url : scope.texturePath + image.url;
37123
37124 images[ image.uuid ] = loadImage( path );
37125
37126 }
37127
37128 }
37129
37130 return images;
37131
37132 },
37133
37134 parseTextures: function ( json, images ) {
37135
37136 function parseConstant( value, type ) {
37137
37138 if ( typeof value === 'number' ) return value;
37139
37140 console.warn( 'THREE.ObjectLoader.parseTexture: Constant should be in numeric form.', value );
37141
37142 return type[ value ];
37143
37144 }
37145
37146 var textures = {};
37147
37148 if ( json !== undefined ) {
37149
37150 for ( var i = 0, l = json.length; i < l; i ++ ) {
37151
37152 var data = json[ i ];
37153
37154 if ( data.image === undefined ) {
37155
37156 console.warn( 'THREE.ObjectLoader: No "image" specified for', data.uuid );
37157
37158 }
37159
37160 if ( images[ data.image ] === undefined ) {
37161
37162 console.warn( 'THREE.ObjectLoader: Undefined image', data.image );
37163
37164 }
37165
37166 var texture = new Texture( images[ data.image ] );
37167 texture.needsUpdate = true;
37168
37169 texture.uuid = data.uuid;
37170
37171 if ( data.name !== undefined ) texture.name = data.name;
37172
37173 if ( data.mapping !== undefined ) texture.mapping = parseConstant( data.mapping, TEXTURE_MAPPING );
37174
37175 if ( data.offset !== undefined ) texture.offset.fromArray( data.offset );
37176 if ( data.repeat !== undefined ) texture.repeat.fromArray( data.repeat );
37177 if ( data.center !== undefined ) texture.center.fromArray( data.center );
37178 if ( data.rotation !== undefined ) texture.rotation = data.rotation;
37179
37180 if ( data.wrap !== undefined ) {
37181
37182 texture.wrapS = parseConstant( data.wrap[ 0 ], TEXTURE_WRAPPING );
37183 texture.wrapT = parseConstant( data.wrap[ 1 ], TEXTURE_WRAPPING );
37184
37185 }
37186
37187 if ( data.format !== undefined ) texture.format = data.format;
37188
37189 if ( data.minFilter !== undefined ) texture.minFilter = parseConstant( data.minFilter, TEXTURE_FILTER );
37190 if ( data.magFilter !== undefined ) texture.magFilter = parseConstant( data.magFilter, TEXTURE_FILTER );
37191 if ( data.anisotropy !== undefined ) texture.anisotropy = data.anisotropy;
37192
37193 if ( data.flipY !== undefined ) texture.flipY = data.flipY;
37194
37195 textures[ data.uuid ] = texture;
37196
37197 }
37198
37199 }
37200
37201 return textures;
37202
37203 },
37204
37205 parseObject: function ( data, geometries, materials ) {
37206
37207 var object;
37208
37209 function getGeometry( name ) {
37210
37211 if ( geometries[ name ] === undefined ) {
37212
37213 console.warn( 'THREE.ObjectLoader: Undefined geometry', name );
37214
37215 }
37216
37217 return geometries[ name ];
37218
37219 }
37220
37221 function getMaterial( name ) {
37222
37223 if ( name === undefined ) return undefined;
37224
37225 if ( Array.isArray( name ) ) {
37226
37227 var array = [];
37228
37229 for ( var i = 0, l = name.length; i < l; i ++ ) {
37230
37231 var uuid = name[ i ];
37232
37233 if ( materials[ uuid ] === undefined ) {
37234
37235 console.warn( 'THREE.ObjectLoader: Undefined material', uuid );
37236
37237 }
37238
37239 array.push( materials[ uuid ] );
37240
37241 }
37242
37243 return array;
37244
37245 }
37246
37247 if ( materials[ name ] === undefined ) {
37248
37249 console.warn( 'THREE.ObjectLoader: Undefined material', name );
37250
37251 }
37252
37253 return materials[ name ];
37254
37255 }
37256
37257 switch ( data.type ) {
37258
37259 case 'Scene':
37260
37261 object = new Scene();
37262
37263 if ( data.background !== undefined ) {
37264
37265 if ( Number.isInteger( data.background ) ) {
37266
37267 object.background = new Color( data.background );
37268
37269 }
37270
37271 }
37272
37273 if ( data.fog !== undefined ) {
37274
37275 if ( data.fog.type === 'Fog' ) {
37276
37277 object.fog = new Fog( data.fog.color, data.fog.near, data.fog.far );
37278
37279 } else if ( data.fog.type === 'FogExp2' ) {
37280
37281 object.fog = new FogExp2( data.fog.color, data.fog.density );
37282
37283 }
37284
37285 }
37286
37287 break;
37288
37289 case 'PerspectiveCamera':
37290
37291 object = new PerspectiveCamera( data.fov, data.aspect, data.near, data.far );
37292
37293 if ( data.focus !== undefined ) object.focus = data.focus;
37294 if ( data.zoom !== undefined ) object.zoom = data.zoom;
37295 if ( data.filmGauge !== undefined ) object.filmGauge = data.filmGauge;
37296 if ( data.filmOffset !== undefined ) object.filmOffset = data.filmOffset;
37297 if ( data.view !== undefined ) object.view = Object.assign( {}, data.view );
37298
37299 break;
37300
37301 case 'OrthographicCamera':
37302
37303 object = new OrthographicCamera( data.left, data.right, data.top, data.bottom, data.near, data.far );
37304
37305 if ( data.zoom !== undefined ) object.zoom = data.zoom;
37306 if ( data.view !== undefined ) object.view = Object.assign( {}, data.view );
37307
37308 break;
37309
37310 case 'AmbientLight':
37311
37312 object = new AmbientLight( data.color, data.intensity );
37313
37314 break;
37315
37316 case 'DirectionalLight':
37317
37318 object = new DirectionalLight( data.color, data.intensity );
37319
37320 break;
37321
37322 case 'PointLight':
37323
37324 object = new PointLight( data.color, data.intensity, data.distance, data.decay );
37325
37326 break;
37327
37328 case 'RectAreaLight':
37329
37330 object = new RectAreaLight( data.color, data.intensity, data.width, data.height );
37331
37332 break;
37333
37334 case 'SpotLight':
37335
37336 object = new SpotLight( data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay );
37337
37338 break;
37339
37340 case 'HemisphereLight':
37341
37342 object = new HemisphereLight( data.color, data.groundColor, data.intensity );
37343
37344 break;
37345
37346 case 'SkinnedMesh':
37347
37348 console.warn( 'THREE.ObjectLoader.parseObject() does not support SkinnedMesh yet.' );
37349
37350 case 'Mesh':
37351
37352 var geometry = getGeometry( data.geometry );
37353 var material = getMaterial( data.material );
37354
37355 if ( geometry.bones && geometry.bones.length > 0 ) {
37356
37357 object = new SkinnedMesh( geometry, material );
37358
37359 } else {
37360
37361 object = new Mesh( geometry, material );
37362
37363 }
37364
37365 break;
37366
37367 case 'LOD':
37368
37369 object = new LOD();
37370
37371 break;
37372
37373 case 'Line':
37374
37375 object = new Line( getGeometry( data.geometry ), getMaterial( data.material ), data.mode );
37376
37377 break;
37378
37379 case 'LineLoop':
37380
37381 object = new LineLoop( getGeometry( data.geometry ), getMaterial( data.material ) );
37382
37383 break;
37384
37385 case 'LineSegments':
37386
37387 object = new LineSegments( getGeometry( data.geometry ), getMaterial( data.material ) );
37388
37389 break;
37390
37391 case 'PointCloud':
37392 case 'Points':
37393
37394 object = new Points( getGeometry( data.geometry ), getMaterial( data.material ) );
37395
37396 break;
37397
37398 case 'Sprite':
37399
37400 object = new Sprite( getMaterial( data.material ) );
37401
37402 break;
37403
37404 case 'Group':
37405
37406 object = new Group();
37407
37408 break;
37409
37410 default:
37411
37412 object = new Object3D();
37413
37414 }
37415
37416 object.uuid = data.uuid;
37417
37418 if ( data.name !== undefined ) object.name = data.name;
37419
37420 if ( data.matrix !== undefined ) {
37421
37422 object.matrix.fromArray( data.matrix );
37423
37424 if ( data.matrixAutoUpdate !== undefined ) object.matrixAutoUpdate = data.matrixAutoUpdate;
37425 if ( object.matrixAutoUpdate ) object.matrix.decompose( object.position, object.quaternion, object.scale );
37426
37427 } else {
37428
37429 if ( data.position !== undefined ) object.position.fromArray( data.position );
37430 if ( data.rotation !== undefined ) object.rotation.fromArray( data.rotation );
37431 if ( data.quaternion !== undefined ) object.quaternion.fromArray( data.quaternion );
37432 if ( data.scale !== undefined ) object.scale.fromArray( data.scale );
37433
37434 }
37435
37436 if ( data.castShadow !== undefined ) object.castShadow = data.castShadow;
37437 if ( data.receiveShadow !== undefined ) object.receiveShadow = data.receiveShadow;
37438
37439 if ( data.shadow ) {
37440
37441 if ( data.shadow.bias !== undefined ) object.shadow.bias = data.shadow.bias;
37442 if ( data.shadow.radius !== undefined ) object.shadow.radius = data.shadow.radius;
37443 if ( data.shadow.mapSize !== undefined ) object.shadow.mapSize.fromArray( data.shadow.mapSize );
37444 if ( data.shadow.camera !== undefined ) object.shadow.camera = this.parseObject( data.shadow.camera );
37445
37446 }
37447
37448 if ( data.visible !== undefined ) object.visible = data.visible;
37449 if ( data.frustumCulled !== undefined ) object.frustumCulled = data.frustumCulled;
37450 if ( data.renderOrder !== undefined ) object.renderOrder = data.renderOrder;
37451 if ( data.userData !== undefined ) object.userData = data.userData;
37452
37453 if ( data.children !== undefined ) {
37454
37455 var children = data.children;
37456
37457 for ( var i = 0; i < children.length; i ++ ) {
37458
37459 object.add( this.parseObject( children[ i ], geometries, materials ) );
37460
37461 }
37462
37463 }
37464
37465 if ( data.type === 'LOD' ) {
37466
37467 var levels = data.levels;
37468
37469 for ( var l = 0; l < levels.length; l ++ ) {
37470
37471 var level = levels[ l ];
37472 var child = object.getObjectByProperty( 'uuid', level.object );
37473
37474 if ( child !== undefined ) {
37475
37476 object.addLevel( child, level.distance );
37477
37478 }
37479
37480 }
37481
37482 }
37483
37484 return object;
37485
37486 }
37487
37488} );
37489
37490var TEXTURE_MAPPING = {
37491 UVMapping: UVMapping,
37492 CubeReflectionMapping: CubeReflectionMapping,
37493 CubeRefractionMapping: CubeRefractionMapping,
37494 EquirectangularReflectionMapping: EquirectangularReflectionMapping,
37495 EquirectangularRefractionMapping: EquirectangularRefractionMapping,
37496 SphericalReflectionMapping: SphericalReflectionMapping,
37497 CubeUVReflectionMapping: CubeUVReflectionMapping,
37498 CubeUVRefractionMapping: CubeUVRefractionMapping
37499};
37500
37501var TEXTURE_WRAPPING = {
37502 RepeatWrapping: RepeatWrapping,
37503 ClampToEdgeWrapping: ClampToEdgeWrapping,
37504 MirroredRepeatWrapping: MirroredRepeatWrapping
37505};
37506
37507var TEXTURE_FILTER = {
37508 NearestFilter: NearestFilter,
37509 NearestMipMapNearestFilter: NearestMipMapNearestFilter,
37510 NearestMipMapLinearFilter: NearestMipMapLinearFilter,
37511 LinearFilter: LinearFilter,
37512 LinearMipMapNearestFilter: LinearMipMapNearestFilter,
37513 LinearMipMapLinearFilter: LinearMipMapLinearFilter
37514};
37515
37516/**
37517 * @author thespite / http://clicktorelease.com/
37518 */
37519
37520function ImageBitmapLoader( manager ) {
37521
37522 if ( typeof createImageBitmap === 'undefined' ) {
37523
37524 console.warn( 'THREE.ImageBitmapLoader: createImageBitmap() not supported.' );
37525
37526 }
37527
37528 if ( typeof fetch === 'undefined' ) {
37529
37530 console.warn( 'THREE.ImageBitmapLoader: fetch() not supported.' );
37531
37532 }
37533
37534 this.manager = manager !== undefined ? manager : DefaultLoadingManager;
37535 this.options = undefined;
37536
37537}
37538
37539ImageBitmapLoader.prototype = {
37540
37541 constructor: ImageBitmapLoader,
37542
37543 setOptions: function setOptions( options ) {
37544
37545 this.options = options;
37546
37547 return this;
37548
37549 },
37550
37551 load: function load( url, onLoad, onProgress, onError ) {
37552
37553 if ( url === undefined ) url = '';
37554
37555 if ( this.path !== undefined ) url = this.path + url;
37556
37557 var scope = this;
37558
37559 var cached = Cache.get( url );
37560
37561 if ( cached !== undefined ) {
37562
37563 scope.manager.itemStart( url );
37564
37565 setTimeout( function () {
37566
37567 if ( onLoad ) onLoad( cached );
37568
37569 scope.manager.itemEnd( url );
37570
37571 }, 0 );
37572
37573 return cached;
37574
37575 }
37576
37577 fetch( url ).then( function ( res ) {
37578
37579 return res.blob();
37580
37581 } ).then( function ( blob ) {
37582
37583 return createImageBitmap( blob, scope.options );
37584
37585 } ).then( function ( imageBitmap ) {
37586
37587 Cache.add( url, imageBitmap );
37588
37589 if ( onLoad ) onLoad( imageBitmap );
37590
37591 scope.manager.itemEnd( url );
37592
37593 } ).catch( function ( e ) {
37594
37595 if ( onError ) onError( e );
37596
37597 scope.manager.itemEnd( url );
37598 scope.manager.itemError( url );
37599
37600 } );
37601
37602 },
37603
37604 setCrossOrigin: function ( /* value */ ) {
37605
37606 return this;
37607
37608 },
37609
37610 setPath: function ( value ) {
37611
37612 this.path = value;
37613 return this;
37614
37615 }
37616
37617};
37618
37619/**
37620 * @author zz85 / http://www.lab4games.net/zz85/blog
37621 * minimal class for proxing functions to Path. Replaces old "extractSubpaths()"
37622 **/
37623
37624function ShapePath() {
37625
37626 this.type = 'ShapePath';
37627
37628 this.color = new Color();
37629
37630 this.subPaths = [];
37631 this.currentPath = null;
37632
37633}
37634
37635Object.assign( ShapePath.prototype, {
37636
37637 moveTo: function ( x, y ) {
37638
37639 this.currentPath = new Path();
37640 this.subPaths.push( this.currentPath );
37641 this.currentPath.moveTo( x, y );
37642
37643 },
37644
37645 lineTo: function ( x, y ) {
37646
37647 this.currentPath.lineTo( x, y );
37648
37649 },
37650
37651 quadraticCurveTo: function ( aCPx, aCPy, aX, aY ) {
37652
37653 this.currentPath.quadraticCurveTo( aCPx, aCPy, aX, aY );
37654
37655 },
37656
37657 bezierCurveTo: function ( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) {
37658
37659 this.currentPath.bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY );
37660
37661 },
37662
37663 splineThru: function ( pts ) {
37664
37665 this.currentPath.splineThru( pts );
37666
37667 },
37668
37669 toShapes: function ( isCCW, noHoles ) {
37670
37671 function toShapesNoHoles( inSubpaths ) {
37672
37673 var shapes = [];
37674
37675 for ( var i = 0, l = inSubpaths.length; i < l; i ++ ) {
37676
37677 var tmpPath = inSubpaths[ i ];
37678
37679 var tmpShape = new Shape();
37680 tmpShape.curves = tmpPath.curves;
37681
37682 shapes.push( tmpShape );
37683
37684 }
37685
37686 return shapes;
37687
37688 }
37689
37690 function isPointInsidePolygon( inPt, inPolygon ) {
37691
37692 var polyLen = inPolygon.length;
37693
37694 // inPt on polygon contour => immediate success or
37695 // toggling of inside/outside at every single! intersection point of an edge
37696 // with the horizontal line through inPt, left of inPt
37697 // not counting lowerY endpoints of edges and whole edges on that line
37698 var inside = false;
37699 for ( var p = polyLen - 1, q = 0; q < polyLen; p = q ++ ) {
37700
37701 var edgeLowPt = inPolygon[ p ];
37702 var edgeHighPt = inPolygon[ q ];
37703
37704 var edgeDx = edgeHighPt.x - edgeLowPt.x;
37705 var edgeDy = edgeHighPt.y - edgeLowPt.y;
37706
37707 if ( Math.abs( edgeDy ) > Number.EPSILON ) {
37708
37709 // not parallel
37710 if ( edgeDy < 0 ) {
37711
37712 edgeLowPt = inPolygon[ q ]; edgeDx = - edgeDx;
37713 edgeHighPt = inPolygon[ p ]; edgeDy = - edgeDy;
37714
37715 }
37716 if ( ( inPt.y < edgeLowPt.y ) || ( inPt.y > edgeHighPt.y ) ) continue;
37717
37718 if ( inPt.y === edgeLowPt.y ) {
37719
37720 if ( inPt.x === edgeLowPt.x ) return true; // inPt is on contour ?
37721 // continue; // no intersection or edgeLowPt => doesn't count !!!
37722
37723 } else {
37724
37725 var perpEdge = edgeDy * ( inPt.x - edgeLowPt.x ) - edgeDx * ( inPt.y - edgeLowPt.y );
37726 if ( perpEdge === 0 ) return true; // inPt is on contour ?
37727 if ( perpEdge < 0 ) continue;
37728 inside = ! inside; // true intersection left of inPt
37729
37730 }
37731
37732 } else {
37733
37734 // parallel or collinear
37735 if ( inPt.y !== edgeLowPt.y ) continue; // parallel
37736 // edge lies on the same horizontal line as inPt
37737 if ( ( ( edgeHighPt.x <= inPt.x ) && ( inPt.x <= edgeLowPt.x ) ) ||
37738 ( ( edgeLowPt.x <= inPt.x ) && ( inPt.x <= edgeHighPt.x ) ) ) return true; // inPt: Point on contour !
37739 // continue;
37740
37741 }
37742
37743 }
37744
37745 return inside;
37746
37747 }
37748
37749 var isClockWise = ShapeUtils.isClockWise;
37750
37751 var subPaths = this.subPaths;
37752 if ( subPaths.length === 0 ) return [];
37753
37754 if ( noHoles === true ) return toShapesNoHoles( subPaths );
37755
37756
37757 var solid, tmpPath, tmpShape, shapes = [];
37758
37759 if ( subPaths.length === 1 ) {
37760
37761 tmpPath = subPaths[ 0 ];
37762 tmpShape = new Shape();
37763 tmpShape.curves = tmpPath.curves;
37764 shapes.push( tmpShape );
37765 return shapes;
37766
37767 }
37768
37769 var holesFirst = ! isClockWise( subPaths[ 0 ].getPoints() );
37770 holesFirst = isCCW ? ! holesFirst : holesFirst;
37771
37772 // console.log("Holes first", holesFirst);
37773
37774 var betterShapeHoles = [];
37775 var newShapes = [];
37776 var newShapeHoles = [];
37777 var mainIdx = 0;
37778 var tmpPoints;
37779
37780 newShapes[ mainIdx ] = undefined;
37781 newShapeHoles[ mainIdx ] = [];
37782
37783 for ( var i = 0, l = subPaths.length; i < l; i ++ ) {
37784
37785 tmpPath = subPaths[ i ];
37786 tmpPoints = tmpPath.getPoints();
37787 solid = isClockWise( tmpPoints );
37788 solid = isCCW ? ! solid : solid;
37789
37790 if ( solid ) {
37791
37792 if ( ( ! holesFirst ) && ( newShapes[ mainIdx ] ) ) mainIdx ++;
37793
37794 newShapes[ mainIdx ] = { s: new Shape(), p: tmpPoints };
37795 newShapes[ mainIdx ].s.curves = tmpPath.curves;
37796
37797 if ( holesFirst ) mainIdx ++;
37798 newShapeHoles[ mainIdx ] = [];
37799
37800 //console.log('cw', i);
37801
37802 } else {
37803
37804 newShapeHoles[ mainIdx ].push( { h: tmpPath, p: tmpPoints[ 0 ] } );
37805
37806 //console.log('ccw', i);
37807
37808 }
37809
37810 }
37811
37812 // only Holes? -> probably all Shapes with wrong orientation
37813 if ( ! newShapes[ 0 ] ) return toShapesNoHoles( subPaths );
37814
37815
37816 if ( newShapes.length > 1 ) {
37817
37818 var ambiguous = false;
37819 var toChange = [];
37820
37821 for ( var sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
37822
37823 betterShapeHoles[ sIdx ] = [];
37824
37825 }
37826
37827 for ( var sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
37828
37829 var sho = newShapeHoles[ sIdx ];
37830
37831 for ( var hIdx = 0; hIdx < sho.length; hIdx ++ ) {
37832
37833 var ho = sho[ hIdx ];
37834 var hole_unassigned = true;
37835
37836 for ( var s2Idx = 0; s2Idx < newShapes.length; s2Idx ++ ) {
37837
37838 if ( isPointInsidePolygon( ho.p, newShapes[ s2Idx ].p ) ) {
37839
37840 if ( sIdx !== s2Idx ) toChange.push( { froms: sIdx, tos: s2Idx, hole: hIdx } );
37841 if ( hole_unassigned ) {
37842
37843 hole_unassigned = false;
37844 betterShapeHoles[ s2Idx ].push( ho );
37845
37846 } else {
37847
37848 ambiguous = true;
37849
37850 }
37851
37852 }
37853
37854 }
37855 if ( hole_unassigned ) {
37856
37857 betterShapeHoles[ sIdx ].push( ho );
37858
37859 }
37860
37861 }
37862
37863 }
37864 // console.log("ambiguous: ", ambiguous);
37865 if ( toChange.length > 0 ) {
37866
37867 // console.log("to change: ", toChange);
37868 if ( ! ambiguous ) newShapeHoles = betterShapeHoles;
37869
37870 }
37871
37872 }
37873
37874 var tmpHoles;
37875
37876 for ( var i = 0, il = newShapes.length; i < il; i ++ ) {
37877
37878 tmpShape = newShapes[ i ].s;
37879 shapes.push( tmpShape );
37880 tmpHoles = newShapeHoles[ i ];
37881
37882 for ( var j = 0, jl = tmpHoles.length; j < jl; j ++ ) {
37883
37884 tmpShape.holes.push( tmpHoles[ j ].h );
37885
37886 }
37887
37888 }
37889
37890 //console.log("shape", shapes);
37891
37892 return shapes;
37893
37894 }
37895
37896} );
37897
37898/**
37899 * @author zz85 / http://www.lab4games.net/zz85/blog
37900 * @author mrdoob / http://mrdoob.com/
37901 */
37902
37903function Font( data ) {
37904
37905 this.type = 'Font';
37906
37907 this.data = data;
37908
37909}
37910
37911Object.assign( Font.prototype, {
37912
37913 isFont: true,
37914
37915 generateShapes: function ( text, size, divisions ) {
37916
37917 if ( size === undefined ) size = 100;
37918 if ( divisions === undefined ) divisions = 4;
37919
37920 var shapes = [];
37921 var paths = createPaths( text, size, divisions, this.data );
37922
37923 for ( var p = 0, pl = paths.length; p < pl; p ++ ) {
37924
37925 Array.prototype.push.apply( shapes, paths[ p ].toShapes() );
37926
37927 }
37928
37929 return shapes;
37930
37931 }
37932
37933} );
37934
37935function createPaths( text, size, divisions, data ) {
37936
37937 var chars = String( text ).split( '' );
37938 var scale = size / data.resolution;
37939 var line_height = ( data.boundingBox.yMax - data.boundingBox.yMin + data.underlineThickness ) * scale;
37940
37941 var paths = [];
37942
37943 var offsetX = 0, offsetY = 0;
37944
37945 for ( var i = 0; i < chars.length; i ++ ) {
37946
37947 var char = chars[ i ];
37948
37949 if ( char === '\n' ) {
37950
37951 offsetX = 0;
37952 offsetY -= line_height;
37953
37954 } else {
37955
37956 var ret = createPath( char, divisions, scale, offsetX, offsetY, data );
37957 offsetX += ret.offsetX;
37958 paths.push( ret.path );
37959
37960 }
37961
37962 }
37963
37964 return paths;
37965
37966}
37967
37968function createPath( char, divisions, scale, offsetX, offsetY, data ) {
37969
37970 var glyph = data.glyphs[ char ] || data.glyphs[ '?' ];
37971
37972 if ( ! glyph ) return;
37973
37974 var path = new ShapePath();
37975
37976 var x, y, cpx, cpy, cpx1, cpy1, cpx2, cpy2;
37977
37978 if ( glyph.o ) {
37979
37980 var outline = glyph._cachedOutline || ( glyph._cachedOutline = glyph.o.split( ' ' ) );
37981
37982 for ( var i = 0, l = outline.length; i < l; ) {
37983
37984 var action = outline[ i ++ ];
37985
37986 switch ( action ) {
37987
37988 case 'm': // moveTo
37989
37990 x = outline[ i ++ ] * scale + offsetX;
37991 y = outline[ i ++ ] * scale + offsetY;
37992
37993 path.moveTo( x, y );
37994
37995 break;
37996
37997 case 'l': // lineTo
37998
37999 x = outline[ i ++ ] * scale + offsetX;
38000 y = outline[ i ++ ] * scale + offsetY;
38001
38002 path.lineTo( x, y );
38003
38004 break;
38005
38006 case 'q': // quadraticCurveTo
38007
38008 cpx = outline[ i ++ ] * scale + offsetX;
38009 cpy = outline[ i ++ ] * scale + offsetY;
38010 cpx1 = outline[ i ++ ] * scale + offsetX;
38011 cpy1 = outline[ i ++ ] * scale + offsetY;
38012
38013 path.quadraticCurveTo( cpx1, cpy1, cpx, cpy );
38014
38015 break;
38016
38017 case 'b': // bezierCurveTo
38018
38019 cpx = outline[ i ++ ] * scale + offsetX;
38020 cpy = outline[ i ++ ] * scale + offsetY;
38021 cpx1 = outline[ i ++ ] * scale + offsetX;
38022 cpy1 = outline[ i ++ ] * scale + offsetY;
38023 cpx2 = outline[ i ++ ] * scale + offsetX;
38024 cpy2 = outline[ i ++ ] * scale + offsetY;
38025
38026 path.bezierCurveTo( cpx1, cpy1, cpx2, cpy2, cpx, cpy );
38027
38028 break;
38029
38030 }
38031
38032 }
38033
38034 }
38035
38036 return { offsetX: glyph.ha * scale, path: path };
38037
38038}
38039
38040/**
38041 * @author mrdoob / http://mrdoob.com/
38042 */
38043
38044function FontLoader( manager ) {
38045
38046 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
38047
38048}
38049
38050Object.assign( FontLoader.prototype, {
38051
38052 load: function ( url, onLoad, onProgress, onError ) {
38053
38054 var scope = this;
38055
38056 var loader = new FileLoader( this.manager );
38057 loader.setPath( this.path );
38058 loader.load( url, function ( text ) {
38059
38060 var json;
38061
38062 try {
38063
38064 json = JSON.parse( text );
38065
38066 } catch ( e ) {
38067
38068 console.warn( 'THREE.FontLoader: typeface.js support is being deprecated. Use typeface.json instead.' );
38069 json = JSON.parse( text.substring( 65, text.length - 2 ) );
38070
38071 }
38072
38073 var font = scope.parse( json );
38074
38075 if ( onLoad ) onLoad( font );
38076
38077 }, onProgress, onError );
38078
38079 },
38080
38081 parse: function ( json ) {
38082
38083 return new Font( json );
38084
38085 },
38086
38087 setPath: function ( value ) {
38088
38089 this.path = value;
38090 return this;
38091
38092 }
38093
38094} );
38095
38096/**
38097 * @author mrdoob / http://mrdoob.com/
38098 */
38099
38100var context;
38101
38102var AudioContext = {
38103
38104 getContext: function () {
38105
38106 if ( context === undefined ) {
38107
38108 context = new ( window.AudioContext || window.webkitAudioContext )();
38109
38110 }
38111
38112 return context;
38113
38114 },
38115
38116 setContext: function ( value ) {
38117
38118 context = value;
38119
38120 }
38121
38122};
38123
38124/**
38125 * @author Reece Aaron Lecrivain / http://reecenotes.com/
38126 */
38127
38128function AudioLoader( manager ) {
38129
38130 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
38131
38132}
38133
38134Object.assign( AudioLoader.prototype, {
38135
38136 load: function ( url, onLoad, onProgress, onError ) {
38137
38138 var loader = new FileLoader( this.manager );
38139 loader.setResponseType( 'arraybuffer' );
38140 loader.load( url, function ( buffer ) {
38141
38142 var context = AudioContext.getContext();
38143
38144 context.decodeAudioData( buffer, function ( audioBuffer ) {
38145
38146 onLoad( audioBuffer );
38147
38148 } );
38149
38150 }, onProgress, onError );
38151
38152 }
38153
38154} );
38155
38156/**
38157 * @author mrdoob / http://mrdoob.com/
38158 */
38159
38160function StereoCamera() {
38161
38162 this.type = 'StereoCamera';
38163
38164 this.aspect = 1;
38165
38166 this.eyeSep = 0.064;
38167
38168 this.cameraL = new PerspectiveCamera();
38169 this.cameraL.layers.enable( 1 );
38170 this.cameraL.matrixAutoUpdate = false;
38171
38172 this.cameraR = new PerspectiveCamera();
38173 this.cameraR.layers.enable( 2 );
38174 this.cameraR.matrixAutoUpdate = false;
38175
38176}
38177
38178Object.assign( StereoCamera.prototype, {
38179
38180 update: ( function () {
38181
38182 var instance, focus, fov, aspect, near, far, zoom, eyeSep;
38183
38184 var eyeRight = new Matrix4();
38185 var eyeLeft = new Matrix4();
38186
38187 return function update( camera ) {
38188
38189 var needsUpdate = instance !== this || focus !== camera.focus || fov !== camera.fov ||
38190 aspect !== camera.aspect * this.aspect || near !== camera.near ||
38191 far !== camera.far || zoom !== camera.zoom || eyeSep !== this.eyeSep;
38192
38193 if ( needsUpdate ) {
38194
38195 instance = this;
38196 focus = camera.focus;
38197 fov = camera.fov;
38198 aspect = camera.aspect * this.aspect;
38199 near = camera.near;
38200 far = camera.far;
38201 zoom = camera.zoom;
38202
38203 // Off-axis stereoscopic effect based on
38204 // http://paulbourke.net/stereographics/stereorender/
38205
38206 var projectionMatrix = camera.projectionMatrix.clone();
38207 eyeSep = this.eyeSep / 2;
38208 var eyeSepOnProjection = eyeSep * near / focus;
38209 var ymax = ( near * Math.tan( _Math.DEG2RAD * fov * 0.5 ) ) / zoom;
38210 var xmin, xmax;
38211
38212 // translate xOffset
38213
38214 eyeLeft.elements[ 12 ] = - eyeSep;
38215 eyeRight.elements[ 12 ] = eyeSep;
38216
38217 // for left eye
38218
38219 xmin = - ymax * aspect + eyeSepOnProjection;
38220 xmax = ymax * aspect + eyeSepOnProjection;
38221
38222 projectionMatrix.elements[ 0 ] = 2 * near / ( xmax - xmin );
38223 projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
38224
38225 this.cameraL.projectionMatrix.copy( projectionMatrix );
38226
38227 // for right eye
38228
38229 xmin = - ymax * aspect - eyeSepOnProjection;
38230 xmax = ymax * aspect - eyeSepOnProjection;
38231
38232 projectionMatrix.elements[ 0 ] = 2 * near / ( xmax - xmin );
38233 projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
38234
38235 this.cameraR.projectionMatrix.copy( projectionMatrix );
38236
38237 }
38238
38239 this.cameraL.matrixWorld.copy( camera.matrixWorld ).multiply( eyeLeft );
38240 this.cameraR.matrixWorld.copy( camera.matrixWorld ).multiply( eyeRight );
38241
38242 };
38243
38244 } )()
38245
38246} );
38247
38248/**
38249 * Camera for rendering cube maps
38250 * - renders scene into axis-aligned cube
38251 *
38252 * @author alteredq / http://alteredqualia.com/
38253 */
38254
38255function CubeCamera( near, far, cubeResolution ) {
38256
38257 Object3D.call( this );
38258
38259 this.type = 'CubeCamera';
38260
38261 var fov = 90, aspect = 1;
38262
38263 var cameraPX = new PerspectiveCamera( fov, aspect, near, far );
38264 cameraPX.up.set( 0, - 1, 0 );
38265 cameraPX.lookAt( new Vector3( 1, 0, 0 ) );
38266 this.add( cameraPX );
38267
38268 var cameraNX = new PerspectiveCamera( fov, aspect, near, far );
38269 cameraNX.up.set( 0, - 1, 0 );
38270 cameraNX.lookAt( new Vector3( - 1, 0, 0 ) );
38271 this.add( cameraNX );
38272
38273 var cameraPY = new PerspectiveCamera( fov, aspect, near, far );
38274 cameraPY.up.set( 0, 0, 1 );
38275 cameraPY.lookAt( new Vector3( 0, 1, 0 ) );
38276 this.add( cameraPY );
38277
38278 var cameraNY = new PerspectiveCamera( fov, aspect, near, far );
38279 cameraNY.up.set( 0, 0, - 1 );
38280 cameraNY.lookAt( new Vector3( 0, - 1, 0 ) );
38281 this.add( cameraNY );
38282
38283 var cameraPZ = new PerspectiveCamera( fov, aspect, near, far );
38284 cameraPZ.up.set( 0, - 1, 0 );
38285 cameraPZ.lookAt( new Vector3( 0, 0, 1 ) );
38286 this.add( cameraPZ );
38287
38288 var cameraNZ = new PerspectiveCamera( fov, aspect, near, far );
38289 cameraNZ.up.set( 0, - 1, 0 );
38290 cameraNZ.lookAt( new Vector3( 0, 0, - 1 ) );
38291 this.add( cameraNZ );
38292
38293 var options = { format: RGBFormat, magFilter: LinearFilter, minFilter: LinearFilter };
38294
38295 this.renderTarget = new WebGLRenderTargetCube( cubeResolution, cubeResolution, options );
38296 this.renderTarget.texture.name = "CubeCamera";
38297
38298 this.update = function ( renderer, scene ) {
38299
38300 if ( this.parent === null ) this.updateMatrixWorld();
38301
38302 var renderTarget = this.renderTarget;
38303 var generateMipmaps = renderTarget.texture.generateMipmaps;
38304
38305 renderTarget.texture.generateMipmaps = false;
38306
38307 renderTarget.activeCubeFace = 0;
38308 renderer.render( scene, cameraPX, renderTarget );
38309
38310 renderTarget.activeCubeFace = 1;
38311 renderer.render( scene, cameraNX, renderTarget );
38312
38313 renderTarget.activeCubeFace = 2;
38314 renderer.render( scene, cameraPY, renderTarget );
38315
38316 renderTarget.activeCubeFace = 3;
38317 renderer.render( scene, cameraNY, renderTarget );
38318
38319 renderTarget.activeCubeFace = 4;
38320 renderer.render( scene, cameraPZ, renderTarget );
38321
38322 renderTarget.texture.generateMipmaps = generateMipmaps;
38323
38324 renderTarget.activeCubeFace = 5;
38325 renderer.render( scene, cameraNZ, renderTarget );
38326
38327 renderer.setRenderTarget( null );
38328
38329 };
38330
38331 this.clear = function ( renderer, color, depth, stencil ) {
38332
38333 var renderTarget = this.renderTarget;
38334
38335 for ( var i = 0; i < 6; i ++ ) {
38336
38337 renderTarget.activeCubeFace = i;
38338 renderer.setRenderTarget( renderTarget );
38339
38340 renderer.clear( color, depth, stencil );
38341
38342 }
38343
38344 renderer.setRenderTarget( null );
38345
38346 };
38347
38348}
38349
38350CubeCamera.prototype = Object.create( Object3D.prototype );
38351CubeCamera.prototype.constructor = CubeCamera;
38352
38353/**
38354 * @author mrdoob / http://mrdoob.com/
38355 */
38356
38357function AudioListener() {
38358
38359 Object3D.call( this );
38360
38361 this.type = 'AudioListener';
38362
38363 this.context = AudioContext.getContext();
38364
38365 this.gain = this.context.createGain();
38366 this.gain.connect( this.context.destination );
38367
38368 this.filter = null;
38369
38370}
38371
38372AudioListener.prototype = Object.assign( Object.create( Object3D.prototype ), {
38373
38374 constructor: AudioListener,
38375
38376 getInput: function () {
38377
38378 return this.gain;
38379
38380 },
38381
38382 removeFilter: function ( ) {
38383
38384 if ( this.filter !== null ) {
38385
38386 this.gain.disconnect( this.filter );
38387 this.filter.disconnect( this.context.destination );
38388 this.gain.connect( this.context.destination );
38389 this.filter = null;
38390
38391 }
38392
38393 },
38394
38395 getFilter: function () {
38396
38397 return this.filter;
38398
38399 },
38400
38401 setFilter: function ( value ) {
38402
38403 if ( this.filter !== null ) {
38404
38405 this.gain.disconnect( this.filter );
38406 this.filter.disconnect( this.context.destination );
38407
38408 } else {
38409
38410 this.gain.disconnect( this.context.destination );
38411
38412 }
38413
38414 this.filter = value;
38415 this.gain.connect( this.filter );
38416 this.filter.connect( this.context.destination );
38417
38418 },
38419
38420 getMasterVolume: function () {
38421
38422 return this.gain.gain.value;
38423
38424 },
38425
38426 setMasterVolume: function ( value ) {
38427
38428 this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 );
38429
38430 },
38431
38432 updateMatrixWorld: ( function () {
38433
38434 var position = new Vector3();
38435 var quaternion = new Quaternion();
38436 var scale = new Vector3();
38437
38438 var orientation = new Vector3();
38439
38440 return function updateMatrixWorld( force ) {
38441
38442 Object3D.prototype.updateMatrixWorld.call( this, force );
38443
38444 var listener = this.context.listener;
38445 var up = this.up;
38446
38447 this.matrixWorld.decompose( position, quaternion, scale );
38448
38449 orientation.set( 0, 0, - 1 ).applyQuaternion( quaternion );
38450
38451 if ( listener.positionX ) {
38452
38453 listener.positionX.setValueAtTime( position.x, this.context.currentTime );
38454 listener.positionY.setValueAtTime( position.y, this.context.currentTime );
38455 listener.positionZ.setValueAtTime( position.z, this.context.currentTime );
38456 listener.forwardX.setValueAtTime( orientation.x, this.context.currentTime );
38457 listener.forwardY.setValueAtTime( orientation.y, this.context.currentTime );
38458 listener.forwardZ.setValueAtTime( orientation.z, this.context.currentTime );
38459 listener.upX.setValueAtTime( up.x, this.context.currentTime );
38460 listener.upY.setValueAtTime( up.y, this.context.currentTime );
38461 listener.upZ.setValueAtTime( up.z, this.context.currentTime );
38462
38463 } else {
38464
38465 listener.setPosition( position.x, position.y, position.z );
38466 listener.setOrientation( orientation.x, orientation.y, orientation.z, up.x, up.y, up.z );
38467
38468 }
38469
38470 };
38471
38472 } )()
38473
38474} );
38475
38476/**
38477 * @author mrdoob / http://mrdoob.com/
38478 * @author Reece Aaron Lecrivain / http://reecenotes.com/
38479 */
38480
38481function Audio( listener ) {
38482
38483 Object3D.call( this );
38484
38485 this.type = 'Audio';
38486
38487 this.context = listener.context;
38488
38489 this.gain = this.context.createGain();
38490 this.gain.connect( listener.getInput() );
38491
38492 this.autoplay = false;
38493
38494 this.buffer = null;
38495 this.loop = false;
38496 this.startTime = 0;
38497 this.offset = 0;
38498 this.playbackRate = 1;
38499 this.isPlaying = false;
38500 this.hasPlaybackControl = true;
38501 this.sourceType = 'empty';
38502
38503 this.filters = [];
38504
38505}
38506
38507Audio.prototype = Object.assign( Object.create( Object3D.prototype ), {
38508
38509 constructor: Audio,
38510
38511 getOutput: function () {
38512
38513 return this.gain;
38514
38515 },
38516
38517 setNodeSource: function ( audioNode ) {
38518
38519 this.hasPlaybackControl = false;
38520 this.sourceType = 'audioNode';
38521 this.source = audioNode;
38522 this.connect();
38523
38524 return this;
38525
38526 },
38527
38528 setBuffer: function ( audioBuffer ) {
38529
38530 this.buffer = audioBuffer;
38531 this.sourceType = 'buffer';
38532
38533 if ( this.autoplay ) this.play();
38534
38535 return this;
38536
38537 },
38538
38539 play: function () {
38540
38541 if ( this.isPlaying === true ) {
38542
38543 console.warn( 'THREE.Audio: Audio is already playing.' );
38544 return;
38545
38546 }
38547
38548 if ( this.hasPlaybackControl === false ) {
38549
38550 console.warn( 'THREE.Audio: this Audio has no playback control.' );
38551 return;
38552
38553 }
38554
38555 var source = this.context.createBufferSource();
38556
38557 source.buffer = this.buffer;
38558 source.loop = this.loop;
38559 source.onended = this.onEnded.bind( this );
38560 source.playbackRate.setValueAtTime( this.playbackRate, this.startTime );
38561 this.startTime = this.context.currentTime;
38562 source.start( this.startTime, this.offset );
38563
38564 this.isPlaying = true;
38565
38566 this.source = source;
38567
38568 return this.connect();
38569
38570 },
38571
38572 pause: function () {
38573
38574 if ( this.hasPlaybackControl === false ) {
38575
38576 console.warn( 'THREE.Audio: this Audio has no playback control.' );
38577 return;
38578
38579 }
38580
38581 if ( this.isPlaying === true ) {
38582
38583 this.source.stop();
38584 this.offset += ( this.context.currentTime - this.startTime ) * this.playbackRate;
38585 this.isPlaying = false;
38586
38587 }
38588
38589 return this;
38590
38591 },
38592
38593 stop: function () {
38594
38595 if ( this.hasPlaybackControl === false ) {
38596
38597 console.warn( 'THREE.Audio: this Audio has no playback control.' );
38598 return;
38599
38600 }
38601
38602 this.source.stop();
38603 this.offset = 0;
38604 this.isPlaying = false;
38605
38606 return this;
38607
38608 },
38609
38610 connect: function () {
38611
38612 if ( this.filters.length > 0 ) {
38613
38614 this.source.connect( this.filters[ 0 ] );
38615
38616 for ( var i = 1, l = this.filters.length; i < l; i ++ ) {
38617
38618 this.filters[ i - 1 ].connect( this.filters[ i ] );
38619
38620 }
38621
38622 this.filters[ this.filters.length - 1 ].connect( this.getOutput() );
38623
38624 } else {
38625
38626 this.source.connect( this.getOutput() );
38627
38628 }
38629
38630 return this;
38631
38632 },
38633
38634 disconnect: function () {
38635
38636 if ( this.filters.length > 0 ) {
38637
38638 this.source.disconnect( this.filters[ 0 ] );
38639
38640 for ( var i = 1, l = this.filters.length; i < l; i ++ ) {
38641
38642 this.filters[ i - 1 ].disconnect( this.filters[ i ] );
38643
38644 }
38645
38646 this.filters[ this.filters.length - 1 ].disconnect( this.getOutput() );
38647
38648 } else {
38649
38650 this.source.disconnect( this.getOutput() );
38651
38652 }
38653
38654 return this;
38655
38656 },
38657
38658 getFilters: function () {
38659
38660 return this.filters;
38661
38662 },
38663
38664 setFilters: function ( value ) {
38665
38666 if ( ! value ) value = [];
38667
38668 if ( this.isPlaying === true ) {
38669
38670 this.disconnect();
38671 this.filters = value;
38672 this.connect();
38673
38674 } else {
38675
38676 this.filters = value;
38677
38678 }
38679
38680 return this;
38681
38682 },
38683
38684 getFilter: function () {
38685
38686 return this.getFilters()[ 0 ];
38687
38688 },
38689
38690 setFilter: function ( filter ) {
38691
38692 return this.setFilters( filter ? [ filter ] : [] );
38693
38694 },
38695
38696 setPlaybackRate: function ( value ) {
38697
38698 if ( this.hasPlaybackControl === false ) {
38699
38700 console.warn( 'THREE.Audio: this Audio has no playback control.' );
38701 return;
38702
38703 }
38704
38705 this.playbackRate = value;
38706
38707 if ( this.isPlaying === true ) {
38708
38709 this.source.playbackRate.setValueAtTime( this.playbackRate, this.context.currentTime );
38710
38711 }
38712
38713 return this;
38714
38715 },
38716
38717 getPlaybackRate: function () {
38718
38719 return this.playbackRate;
38720
38721 },
38722
38723 onEnded: function () {
38724
38725 this.isPlaying = false;
38726
38727 },
38728
38729 getLoop: function () {
38730
38731 if ( this.hasPlaybackControl === false ) {
38732
38733 console.warn( 'THREE.Audio: this Audio has no playback control.' );
38734 return false;
38735
38736 }
38737
38738 return this.loop;
38739
38740 },
38741
38742 setLoop: function ( value ) {
38743
38744 if ( this.hasPlaybackControl === false ) {
38745
38746 console.warn( 'THREE.Audio: this Audio has no playback control.' );
38747 return;
38748
38749 }
38750
38751 this.loop = value;
38752
38753 if ( this.isPlaying === true ) {
38754
38755 this.source.loop = this.loop;
38756
38757 }
38758
38759 return this;
38760
38761 },
38762
38763 getVolume: function () {
38764
38765 return this.gain.gain.value;
38766
38767 },
38768
38769 setVolume: function ( value ) {
38770
38771 this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 );
38772
38773 return this;
38774
38775 }
38776
38777} );
38778
38779/**
38780 * @author mrdoob / http://mrdoob.com/
38781 */
38782
38783function PositionalAudio( listener ) {
38784
38785 Audio.call( this, listener );
38786
38787 this.panner = this.context.createPanner();
38788 this.panner.connect( this.gain );
38789
38790}
38791
38792PositionalAudio.prototype = Object.assign( Object.create( Audio.prototype ), {
38793
38794 constructor: PositionalAudio,
38795
38796 getOutput: function () {
38797
38798 return this.panner;
38799
38800 },
38801
38802 getRefDistance: function () {
38803
38804 return this.panner.refDistance;
38805
38806 },
38807
38808 setRefDistance: function ( value ) {
38809
38810 this.panner.refDistance = value;
38811
38812 },
38813
38814 getRolloffFactor: function () {
38815
38816 return this.panner.rolloffFactor;
38817
38818 },
38819
38820 setRolloffFactor: function ( value ) {
38821
38822 this.panner.rolloffFactor = value;
38823
38824 },
38825
38826 getDistanceModel: function () {
38827
38828 return this.panner.distanceModel;
38829
38830 },
38831
38832 setDistanceModel: function ( value ) {
38833
38834 this.panner.distanceModel = value;
38835
38836 },
38837
38838 getMaxDistance: function () {
38839
38840 return this.panner.maxDistance;
38841
38842 },
38843
38844 setMaxDistance: function ( value ) {
38845
38846 this.panner.maxDistance = value;
38847
38848 },
38849
38850 updateMatrixWorld: ( function () {
38851
38852 var position = new Vector3();
38853
38854 return function updateMatrixWorld( force ) {
38855
38856 Object3D.prototype.updateMatrixWorld.call( this, force );
38857
38858 position.setFromMatrixPosition( this.matrixWorld );
38859
38860 this.panner.setPosition( position.x, position.y, position.z );
38861
38862 };
38863
38864 } )()
38865
38866
38867} );
38868
38869/**
38870 * @author mrdoob / http://mrdoob.com/
38871 */
38872
38873function AudioAnalyser( audio, fftSize ) {
38874
38875 this.analyser = audio.context.createAnalyser();
38876 this.analyser.fftSize = fftSize !== undefined ? fftSize : 2048;
38877
38878 this.data = new Uint8Array( this.analyser.frequencyBinCount );
38879
38880 audio.getOutput().connect( this.analyser );
38881
38882}
38883
38884Object.assign( AudioAnalyser.prototype, {
38885
38886 getFrequencyData: function () {
38887
38888 this.analyser.getByteFrequencyData( this.data );
38889
38890 return this.data;
38891
38892 },
38893
38894 getAverageFrequency: function () {
38895
38896 var value = 0, data = this.getFrequencyData();
38897
38898 for ( var i = 0; i < data.length; i ++ ) {
38899
38900 value += data[ i ];
38901
38902 }
38903
38904 return value / data.length;
38905
38906 }
38907
38908} );
38909
38910/**
38911 *
38912 * Buffered scene graph property that allows weighted accumulation.
38913 *
38914 *
38915 * @author Ben Houston / http://clara.io/
38916 * @author David Sarno / http://lighthaus.us/
38917 * @author tschw
38918 */
38919
38920function PropertyMixer( binding, typeName, valueSize ) {
38921
38922 this.binding = binding;
38923 this.valueSize = valueSize;
38924
38925 var bufferType = Float64Array,
38926 mixFunction;
38927
38928 switch ( typeName ) {
38929
38930 case 'quaternion':
38931 mixFunction = this._slerp;
38932 break;
38933
38934 case 'string':
38935 case 'bool':
38936 bufferType = Array;
38937 mixFunction = this._select;
38938 break;
38939
38940 default:
38941 mixFunction = this._lerp;
38942
38943 }
38944
38945 this.buffer = new bufferType( valueSize * 4 );
38946 // layout: [ incoming | accu0 | accu1 | orig ]
38947 //
38948 // interpolators can use .buffer as their .result
38949 // the data then goes to 'incoming'
38950 //
38951 // 'accu0' and 'accu1' are used frame-interleaved for
38952 // the cumulative result and are compared to detect
38953 // changes
38954 //
38955 // 'orig' stores the original state of the property
38956
38957 this._mixBufferRegion = mixFunction;
38958
38959 this.cumulativeWeight = 0;
38960
38961 this.useCount = 0;
38962 this.referenceCount = 0;
38963
38964}
38965
38966Object.assign( PropertyMixer.prototype, {
38967
38968 // accumulate data in the 'incoming' region into 'accu<i>'
38969 accumulate: function ( accuIndex, weight ) {
38970
38971 // note: happily accumulating nothing when weight = 0, the caller knows
38972 // the weight and shouldn't have made the call in the first place
38973
38974 var buffer = this.buffer,
38975 stride = this.valueSize,
38976 offset = accuIndex * stride + stride,
38977
38978 currentWeight = this.cumulativeWeight;
38979
38980 if ( currentWeight === 0 ) {
38981
38982 // accuN := incoming * weight
38983
38984 for ( var i = 0; i !== stride; ++ i ) {
38985
38986 buffer[ offset + i ] = buffer[ i ];
38987
38988 }
38989
38990 currentWeight = weight;
38991
38992 } else {
38993
38994 // accuN := accuN + incoming * weight
38995
38996 currentWeight += weight;
38997 var mix = weight / currentWeight;
38998 this._mixBufferRegion( buffer, offset, 0, mix, stride );
38999
39000 }
39001
39002 this.cumulativeWeight = currentWeight;
39003
39004 },
39005
39006 // apply the state of 'accu<i>' to the binding when accus differ
39007 apply: function ( accuIndex ) {
39008
39009 var stride = this.valueSize,
39010 buffer = this.buffer,
39011 offset = accuIndex * stride + stride,
39012
39013 weight = this.cumulativeWeight,
39014
39015 binding = this.binding;
39016
39017 this.cumulativeWeight = 0;
39018
39019 if ( weight < 1 ) {
39020
39021 // accuN := accuN + original * ( 1 - cumulativeWeight )
39022
39023 var originalValueOffset = stride * 3;
39024
39025 this._mixBufferRegion(
39026 buffer, offset, originalValueOffset, 1 - weight, stride );
39027
39028 }
39029
39030 for ( var i = stride, e = stride + stride; i !== e; ++ i ) {
39031
39032 if ( buffer[ i ] !== buffer[ i + stride ] ) {
39033
39034 // value has changed -> update scene graph
39035
39036 binding.setValue( buffer, offset );
39037 break;
39038
39039 }
39040
39041 }
39042
39043 },
39044
39045 // remember the state of the bound property and copy it to both accus
39046 saveOriginalState: function () {
39047
39048 var binding = this.binding;
39049
39050 var buffer = this.buffer,
39051 stride = this.valueSize,
39052
39053 originalValueOffset = stride * 3;
39054
39055 binding.getValue( buffer, originalValueOffset );
39056
39057 // accu[0..1] := orig -- initially detect changes against the original
39058 for ( var i = stride, e = originalValueOffset; i !== e; ++ i ) {
39059
39060 buffer[ i ] = buffer[ originalValueOffset + ( i % stride ) ];
39061
39062 }
39063
39064 this.cumulativeWeight = 0;
39065
39066 },
39067
39068 // apply the state previously taken via 'saveOriginalState' to the binding
39069 restoreOriginalState: function () {
39070
39071 var originalValueOffset = this.valueSize * 3;
39072 this.binding.setValue( this.buffer, originalValueOffset );
39073
39074 },
39075
39076
39077 // mix functions
39078
39079 _select: function ( buffer, dstOffset, srcOffset, t, stride ) {
39080
39081 if ( t >= 0.5 ) {
39082
39083 for ( var i = 0; i !== stride; ++ i ) {
39084
39085 buffer[ dstOffset + i ] = buffer[ srcOffset + i ];
39086
39087 }
39088
39089 }
39090
39091 },
39092
39093 _slerp: function ( buffer, dstOffset, srcOffset, t ) {
39094
39095 Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, srcOffset, t );
39096
39097 },
39098
39099 _lerp: function ( buffer, dstOffset, srcOffset, t, stride ) {
39100
39101 var s = 1 - t;
39102
39103 for ( var i = 0; i !== stride; ++ i ) {
39104
39105 var j = dstOffset + i;
39106
39107 buffer[ j ] = buffer[ j ] * s + buffer[ srcOffset + i ] * t;
39108
39109 }
39110
39111 }
39112
39113} );
39114
39115/**
39116 *
39117 * A reference to a real property in the scene graph.
39118 *
39119 *
39120 * @author Ben Houston / http://clara.io/
39121 * @author David Sarno / http://lighthaus.us/
39122 * @author tschw
39123 */
39124
39125// Characters [].:/ are reserved for track binding syntax.
39126var RESERVED_CHARS_RE = '\\[\\]\\.:\\/';
39127
39128function Composite( targetGroup, path, optionalParsedPath ) {
39129
39130 var parsedPath = optionalParsedPath || PropertyBinding.parseTrackName( path );
39131
39132 this._targetGroup = targetGroup;
39133 this._bindings = targetGroup.subscribe_( path, parsedPath );
39134
39135}
39136
39137Object.assign( Composite.prototype, {
39138
39139 getValue: function ( array, offset ) {
39140
39141 this.bind(); // bind all binding
39142
39143 var firstValidIndex = this._targetGroup.nCachedObjects_,
39144 binding = this._bindings[ firstValidIndex ];
39145
39146 // and only call .getValue on the first
39147 if ( binding !== undefined ) binding.getValue( array, offset );
39148
39149 },
39150
39151 setValue: function ( array, offset ) {
39152
39153 var bindings = this._bindings;
39154
39155 for ( var i = this._targetGroup.nCachedObjects_,
39156 n = bindings.length; i !== n; ++ i ) {
39157
39158 bindings[ i ].setValue( array, offset );
39159
39160 }
39161
39162 },
39163
39164 bind: function () {
39165
39166 var bindings = this._bindings;
39167
39168 for ( var i = this._targetGroup.nCachedObjects_,
39169 n = bindings.length; i !== n; ++ i ) {
39170
39171 bindings[ i ].bind();
39172
39173 }
39174
39175 },
39176
39177 unbind: function () {
39178
39179 var bindings = this._bindings;
39180
39181 for ( var i = this._targetGroup.nCachedObjects_,
39182 n = bindings.length; i !== n; ++ i ) {
39183
39184 bindings[ i ].unbind();
39185
39186 }
39187
39188 }
39189
39190} );
39191
39192
39193function PropertyBinding( rootNode, path, parsedPath ) {
39194
39195 this.path = path;
39196 this.parsedPath = parsedPath || PropertyBinding.parseTrackName( path );
39197
39198 this.node = PropertyBinding.findNode( rootNode, this.parsedPath.nodeName ) || rootNode;
39199
39200 this.rootNode = rootNode;
39201
39202}
39203
39204Object.assign( PropertyBinding, {
39205
39206 Composite: Composite,
39207
39208 create: function ( root, path, parsedPath ) {
39209
39210 if ( ! ( root && root.isAnimationObjectGroup ) ) {
39211
39212 return new PropertyBinding( root, path, parsedPath );
39213
39214 } else {
39215
39216 return new PropertyBinding.Composite( root, path, parsedPath );
39217
39218 }
39219
39220 },
39221
39222 /**
39223 * Replaces spaces with underscores and removes unsupported characters from
39224 * node names, to ensure compatibility with parseTrackName().
39225 *
39226 * @param {string} name Node name to be sanitized.
39227 * @return {string}
39228 */
39229 sanitizeNodeName: ( function () {
39230
39231 var reservedRe = new RegExp( '[' + RESERVED_CHARS_RE + ']', 'g' );
39232
39233 return function sanitizeNodeName( name ) {
39234
39235 return name.replace( /\s/g, '_' ).replace( reservedRe, '' );
39236
39237 };
39238
39239 }() ),
39240
39241 parseTrackName: function () {
39242
39243 // Attempts to allow node names from any language. ES5's `\w` regexp matches
39244 // only latin characters, and the unicode \p{L} is not yet supported. So
39245 // instead, we exclude reserved characters and match everything else.
39246 var wordChar = '[^' + RESERVED_CHARS_RE + ']';
39247 var wordCharOrDot = '[^' + RESERVED_CHARS_RE.replace( '\\.', '' ) + ']';
39248
39249 // Parent directories, delimited by '/' or ':'. Currently unused, but must
39250 // be matched to parse the rest of the track name.
39251 var directoryRe = /((?:WC+[\/:])*)/.source.replace( 'WC', wordChar );
39252
39253 // Target node. May contain word characters (a-zA-Z0-9_) and '.' or '-'.
39254 var nodeRe = /(WCOD+)?/.source.replace( 'WCOD', wordCharOrDot );
39255
39256 // Object on target node, and accessor. May not contain reserved
39257 // characters. Accessor may contain any character except closing bracket.
39258 var objectRe = /(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace( 'WC', wordChar );
39259
39260 // Property and accessor. May not contain reserved characters. Accessor may
39261 // contain any non-bracket characters.
39262 var propertyRe = /\.(WC+)(?:\[(.+)\])?/.source.replace( 'WC', wordChar );
39263
39264 var trackRe = new RegExp( ''
39265 + '^'
39266 + directoryRe
39267 + nodeRe
39268 + objectRe
39269 + propertyRe
39270 + '$'
39271 );
39272
39273 var supportedObjectNames = [ 'material', 'materials', 'bones' ];
39274
39275 return function parseTrackName( trackName ) {
39276
39277 var matches = trackRe.exec( trackName );
39278
39279 if ( ! matches ) {
39280
39281 throw new Error( 'PropertyBinding: Cannot parse trackName: ' + trackName );
39282
39283 }
39284
39285 var results = {
39286 // directoryName: matches[ 1 ], // (tschw) currently unused
39287 nodeName: matches[ 2 ],
39288 objectName: matches[ 3 ],
39289 objectIndex: matches[ 4 ],
39290 propertyName: matches[ 5 ], // required
39291 propertyIndex: matches[ 6 ]
39292 };
39293
39294 var lastDot = results.nodeName && results.nodeName.lastIndexOf( '.' );
39295
39296 if ( lastDot !== undefined && lastDot !== - 1 ) {
39297
39298 var objectName = results.nodeName.substring( lastDot + 1 );
39299
39300 // Object names must be checked against a whitelist. Otherwise, there
39301 // is no way to parse 'foo.bar.baz': 'baz' must be a property, but
39302 // 'bar' could be the objectName, or part of a nodeName (which can
39303 // include '.' characters).
39304 if ( supportedObjectNames.indexOf( objectName ) !== - 1 ) {
39305
39306 results.nodeName = results.nodeName.substring( 0, lastDot );
39307 results.objectName = objectName;
39308
39309 }
39310
39311 }
39312
39313 if ( results.propertyName === null || results.propertyName.length === 0 ) {
39314
39315 throw new Error( 'PropertyBinding: can not parse propertyName from trackName: ' + trackName );
39316
39317 }
39318
39319 return results;
39320
39321 };
39322
39323 }(),
39324
39325 findNode: function ( root, nodeName ) {
39326
39327 if ( ! nodeName || nodeName === "" || nodeName === "root" || nodeName === "." || nodeName === - 1 || nodeName === root.name || nodeName === root.uuid ) {
39328
39329 return root;
39330
39331 }
39332
39333 // search into skeleton bones.
39334 if ( root.skeleton ) {
39335
39336 var bone = root.skeleton.getBoneByName( nodeName );
39337
39338 if ( bone !== undefined ) {
39339
39340 return bone;
39341
39342 }
39343
39344 }
39345
39346 // search into node subtree.
39347 if ( root.children ) {
39348
39349 var searchNodeSubtree = function ( children ) {
39350
39351 for ( var i = 0; i < children.length; i ++ ) {
39352
39353 var childNode = children[ i ];
39354
39355 if ( childNode.name === nodeName || childNode.uuid === nodeName ) {
39356
39357 return childNode;
39358
39359 }
39360
39361 var result = searchNodeSubtree( childNode.children );
39362
39363 if ( result ) return result;
39364
39365 }
39366
39367 return null;
39368
39369 };
39370
39371 var subTreeNode = searchNodeSubtree( root.children );
39372
39373 if ( subTreeNode ) {
39374
39375 return subTreeNode;
39376
39377 }
39378
39379 }
39380
39381 return null;
39382
39383 }
39384
39385} );
39386
39387Object.assign( PropertyBinding.prototype, { // prototype, continued
39388
39389 // these are used to "bind" a nonexistent property
39390 _getValue_unavailable: function () {},
39391 _setValue_unavailable: function () {},
39392
39393 BindingType: {
39394 Direct: 0,
39395 EntireArray: 1,
39396 ArrayElement: 2,
39397 HasFromToArray: 3
39398 },
39399
39400 Versioning: {
39401 None: 0,
39402 NeedsUpdate: 1,
39403 MatrixWorldNeedsUpdate: 2
39404 },
39405
39406 GetterByBindingType: [
39407
39408 function getValue_direct( buffer, offset ) {
39409
39410 buffer[ offset ] = this.node[ this.propertyName ];
39411
39412 },
39413
39414 function getValue_array( buffer, offset ) {
39415
39416 var source = this.resolvedProperty;
39417
39418 for ( var i = 0, n = source.length; i !== n; ++ i ) {
39419
39420 buffer[ offset ++ ] = source[ i ];
39421
39422 }
39423
39424 },
39425
39426 function getValue_arrayElement( buffer, offset ) {
39427
39428 buffer[ offset ] = this.resolvedProperty[ this.propertyIndex ];
39429
39430 },
39431
39432 function getValue_toArray( buffer, offset ) {
39433
39434 this.resolvedProperty.toArray( buffer, offset );
39435
39436 }
39437
39438 ],
39439
39440 SetterByBindingTypeAndVersioning: [
39441
39442 [
39443 // Direct
39444
39445 function setValue_direct( buffer, offset ) {
39446
39447 this.targetObject[ this.propertyName ] = buffer[ offset ];
39448
39449 },
39450
39451 function setValue_direct_setNeedsUpdate( buffer, offset ) {
39452
39453 this.targetObject[ this.propertyName ] = buffer[ offset ];
39454 this.targetObject.needsUpdate = true;
39455
39456 },
39457
39458 function setValue_direct_setMatrixWorldNeedsUpdate( buffer, offset ) {
39459
39460 this.targetObject[ this.propertyName ] = buffer[ offset ];
39461 this.targetObject.matrixWorldNeedsUpdate = true;
39462
39463 }
39464
39465 ], [
39466
39467 // EntireArray
39468
39469 function setValue_array( buffer, offset ) {
39470
39471 var dest = this.resolvedProperty;
39472
39473 for ( var i = 0, n = dest.length; i !== n; ++ i ) {
39474
39475 dest[ i ] = buffer[ offset ++ ];
39476
39477 }
39478
39479 },
39480
39481 function setValue_array_setNeedsUpdate( buffer, offset ) {
39482
39483 var dest = this.resolvedProperty;
39484
39485 for ( var i = 0, n = dest.length; i !== n; ++ i ) {
39486
39487 dest[ i ] = buffer[ offset ++ ];
39488
39489 }
39490
39491 this.targetObject.needsUpdate = true;
39492
39493 },
39494
39495 function setValue_array_setMatrixWorldNeedsUpdate( buffer, offset ) {
39496
39497 var dest = this.resolvedProperty;
39498
39499 for ( var i = 0, n = dest.length; i !== n; ++ i ) {
39500
39501 dest[ i ] = buffer[ offset ++ ];
39502
39503 }
39504
39505 this.targetObject.matrixWorldNeedsUpdate = true;
39506
39507 }
39508
39509 ], [
39510
39511 // ArrayElement
39512
39513 function setValue_arrayElement( buffer, offset ) {
39514
39515 this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
39516
39517 },
39518
39519 function setValue_arrayElement_setNeedsUpdate( buffer, offset ) {
39520
39521 this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
39522 this.targetObject.needsUpdate = true;
39523
39524 },
39525
39526 function setValue_arrayElement_setMatrixWorldNeedsUpdate( buffer, offset ) {
39527
39528 this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
39529 this.targetObject.matrixWorldNeedsUpdate = true;
39530
39531 }
39532
39533 ], [
39534
39535 // HasToFromArray
39536
39537 function setValue_fromArray( buffer, offset ) {
39538
39539 this.resolvedProperty.fromArray( buffer, offset );
39540
39541 },
39542
39543 function setValue_fromArray_setNeedsUpdate( buffer, offset ) {
39544
39545 this.resolvedProperty.fromArray( buffer, offset );
39546 this.targetObject.needsUpdate = true;
39547
39548 },
39549
39550 function setValue_fromArray_setMatrixWorldNeedsUpdate( buffer, offset ) {
39551
39552 this.resolvedProperty.fromArray( buffer, offset );
39553 this.targetObject.matrixWorldNeedsUpdate = true;
39554
39555 }
39556
39557 ]
39558
39559 ],
39560
39561 getValue: function getValue_unbound( targetArray, offset ) {
39562
39563 this.bind();
39564 this.getValue( targetArray, offset );
39565
39566 // Note: This class uses a State pattern on a per-method basis:
39567 // 'bind' sets 'this.getValue' / 'setValue' and shadows the
39568 // prototype version of these methods with one that represents
39569 // the bound state. When the property is not found, the methods
39570 // become no-ops.
39571
39572 },
39573
39574 setValue: function getValue_unbound( sourceArray, offset ) {
39575
39576 this.bind();
39577 this.setValue( sourceArray, offset );
39578
39579 },
39580
39581 // create getter / setter pair for a property in the scene graph
39582 bind: function () {
39583
39584 var targetObject = this.node,
39585 parsedPath = this.parsedPath,
39586
39587 objectName = parsedPath.objectName,
39588 propertyName = parsedPath.propertyName,
39589 propertyIndex = parsedPath.propertyIndex;
39590
39591 if ( ! targetObject ) {
39592
39593 targetObject = PropertyBinding.findNode( this.rootNode, parsedPath.nodeName ) || this.rootNode;
39594
39595 this.node = targetObject;
39596
39597 }
39598
39599 // set fail state so we can just 'return' on error
39600 this.getValue = this._getValue_unavailable;
39601 this.setValue = this._setValue_unavailable;
39602
39603 // ensure there is a value node
39604 if ( ! targetObject ) {
39605
39606 console.error( 'THREE.PropertyBinding: Trying to update node for track: ' + this.path + ' but it wasn\'t found.' );
39607 return;
39608
39609 }
39610
39611 if ( objectName ) {
39612
39613 var objectIndex = parsedPath.objectIndex;
39614
39615 // special cases were we need to reach deeper into the hierarchy to get the face materials....
39616 switch ( objectName ) {
39617
39618 case 'materials':
39619
39620 if ( ! targetObject.material ) {
39621
39622 console.error( 'THREE.PropertyBinding: Can not bind to material as node does not have a material.', this );
39623 return;
39624
39625 }
39626
39627 if ( ! targetObject.material.materials ) {
39628
39629 console.error( 'THREE.PropertyBinding: Can not bind to material.materials as node.material does not have a materials array.', this );
39630 return;
39631
39632 }
39633
39634 targetObject = targetObject.material.materials;
39635
39636 break;
39637
39638 case 'bones':
39639
39640 if ( ! targetObject.skeleton ) {
39641
39642 console.error( 'THREE.PropertyBinding: Can not bind to bones as node does not have a skeleton.', this );
39643 return;
39644
39645 }
39646
39647 // potential future optimization: skip this if propertyIndex is already an integer
39648 // and convert the integer string to a true integer.
39649
39650 targetObject = targetObject.skeleton.bones;
39651
39652 // support resolving morphTarget names into indices.
39653 for ( var i = 0; i < targetObject.length; i ++ ) {
39654
39655 if ( targetObject[ i ].name === objectIndex ) {
39656
39657 objectIndex = i;
39658 break;
39659
39660 }
39661
39662 }
39663
39664 break;
39665
39666 default:
39667
39668 if ( targetObject[ objectName ] === undefined ) {
39669
39670 console.error( 'THREE.PropertyBinding: Can not bind to objectName of node undefined.', this );
39671 return;
39672
39673 }
39674
39675 targetObject = targetObject[ objectName ];
39676
39677 }
39678
39679
39680 if ( objectIndex !== undefined ) {
39681
39682 if ( targetObject[ objectIndex ] === undefined ) {
39683
39684 console.error( 'THREE.PropertyBinding: Trying to bind to objectIndex of objectName, but is undefined.', this, targetObject );
39685 return;
39686
39687 }
39688
39689 targetObject = targetObject[ objectIndex ];
39690
39691 }
39692
39693 }
39694
39695 // resolve property
39696 var nodeProperty = targetObject[ propertyName ];
39697
39698 if ( nodeProperty === undefined ) {
39699
39700 var nodeName = parsedPath.nodeName;
39701
39702 console.error( 'THREE.PropertyBinding: Trying to update property for track: ' + nodeName +
39703 '.' + propertyName + ' but it wasn\'t found.', targetObject );
39704 return;
39705
39706 }
39707
39708 // determine versioning scheme
39709 var versioning = this.Versioning.None;
39710
39711 if ( targetObject.needsUpdate !== undefined ) { // material
39712
39713 versioning = this.Versioning.NeedsUpdate;
39714 this.targetObject = targetObject;
39715
39716 } else if ( targetObject.matrixWorldNeedsUpdate !== undefined ) { // node transform
39717
39718 versioning = this.Versioning.MatrixWorldNeedsUpdate;
39719 this.targetObject = targetObject;
39720
39721 }
39722
39723 // determine how the property gets bound
39724 var bindingType = this.BindingType.Direct;
39725
39726 if ( propertyIndex !== undefined ) {
39727
39728 // access a sub element of the property array (only primitives are supported right now)
39729
39730 if ( propertyName === "morphTargetInfluences" ) {
39731
39732 // potential optimization, skip this if propertyIndex is already an integer, and convert the integer string to a true integer.
39733
39734 // support resolving morphTarget names into indices.
39735 if ( ! targetObject.geometry ) {
39736
39737 console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.', this );
39738 return;
39739
39740 }
39741
39742 if ( targetObject.geometry.isBufferGeometry ) {
39743
39744 if ( ! targetObject.geometry.morphAttributes ) {
39745
39746 console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphAttributes.', this );
39747 return;
39748
39749 }
39750
39751 for ( var i = 0; i < this.node.geometry.morphAttributes.position.length; i ++ ) {
39752
39753 if ( targetObject.geometry.morphAttributes.position[ i ].name === propertyIndex ) {
39754
39755 propertyIndex = i;
39756 break;
39757
39758 }
39759
39760 }
39761
39762
39763 } else {
39764
39765 if ( ! targetObject.geometry.morphTargets ) {
39766
39767 console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphTargets.', this );
39768 return;
39769
39770 }
39771
39772 for ( var i = 0; i < this.node.geometry.morphTargets.length; i ++ ) {
39773
39774 if ( targetObject.geometry.morphTargets[ i ].name === propertyIndex ) {
39775
39776 propertyIndex = i;
39777 break;
39778
39779 }
39780
39781 }
39782
39783 }
39784
39785 }
39786
39787 bindingType = this.BindingType.ArrayElement;
39788
39789 this.resolvedProperty = nodeProperty;
39790 this.propertyIndex = propertyIndex;
39791
39792 } else if ( nodeProperty.fromArray !== undefined && nodeProperty.toArray !== undefined ) {
39793
39794 // must use copy for Object3D.Euler/Quaternion
39795
39796 bindingType = this.BindingType.HasFromToArray;
39797
39798 this.resolvedProperty = nodeProperty;
39799
39800 } else if ( Array.isArray( nodeProperty ) ) {
39801
39802 bindingType = this.BindingType.EntireArray;
39803
39804 this.resolvedProperty = nodeProperty;
39805
39806 } else {
39807
39808 this.propertyName = propertyName;
39809
39810 }
39811
39812 // select getter / setter
39813 this.getValue = this.GetterByBindingType[ bindingType ];
39814 this.setValue = this.SetterByBindingTypeAndVersioning[ bindingType ][ versioning ];
39815
39816 },
39817
39818 unbind: function () {
39819
39820 this.node = null;
39821
39822 // back to the prototype version of getValue / setValue
39823 // note: avoiding to mutate the shape of 'this' via 'delete'
39824 this.getValue = this._getValue_unbound;
39825 this.setValue = this._setValue_unbound;
39826
39827 }
39828
39829} );
39830
39831//!\ DECLARE ALIAS AFTER assign prototype !
39832Object.assign( PropertyBinding.prototype, {
39833
39834 // initial state of these methods that calls 'bind'
39835 _getValue_unbound: PropertyBinding.prototype.getValue,
39836 _setValue_unbound: PropertyBinding.prototype.setValue,
39837
39838} );
39839
39840/**
39841 *
39842 * A group of objects that receives a shared animation state.
39843 *
39844 * Usage:
39845 *
39846 * - Add objects you would otherwise pass as 'root' to the
39847 * constructor or the .clipAction method of AnimationMixer.
39848 *
39849 * - Instead pass this object as 'root'.
39850 *
39851 * - You can also add and remove objects later when the mixer
39852 * is running.
39853 *
39854 * Note:
39855 *
39856 * Objects of this class appear as one object to the mixer,
39857 * so cache control of the individual objects must be done
39858 * on the group.
39859 *
39860 * Limitation:
39861 *
39862 * - The animated properties must be compatible among the
39863 * all objects in the group.
39864 *
39865 * - A single property can either be controlled through a
39866 * target group or directly, but not both.
39867 *
39868 * @author tschw
39869 */
39870
39871function AnimationObjectGroup() {
39872
39873 this.uuid = _Math.generateUUID();
39874
39875 // cached objects followed by the active ones
39876 this._objects = Array.prototype.slice.call( arguments );
39877
39878 this.nCachedObjects_ = 0; // threshold
39879 // note: read by PropertyBinding.Composite
39880
39881 var indices = {};
39882 this._indicesByUUID = indices; // for bookkeeping
39883
39884 for ( var i = 0, n = arguments.length; i !== n; ++ i ) {
39885
39886 indices[ arguments[ i ].uuid ] = i;
39887
39888 }
39889
39890 this._paths = []; // inside: string
39891 this._parsedPaths = []; // inside: { we don't care, here }
39892 this._bindings = []; // inside: Array< PropertyBinding >
39893 this._bindingsIndicesByPath = {}; // inside: indices in these arrays
39894
39895 var scope = this;
39896
39897 this.stats = {
39898
39899 objects: {
39900 get total() {
39901
39902 return scope._objects.length;
39903
39904 },
39905 get inUse() {
39906
39907 return this.total - scope.nCachedObjects_;
39908
39909 }
39910 },
39911 get bindingsPerObject() {
39912
39913 return scope._bindings.length;
39914
39915 }
39916
39917 };
39918
39919}
39920
39921Object.assign( AnimationObjectGroup.prototype, {
39922
39923 isAnimationObjectGroup: true,
39924
39925 add: function () {
39926
39927 var objects = this._objects,
39928 nObjects = objects.length,
39929 nCachedObjects = this.nCachedObjects_,
39930 indicesByUUID = this._indicesByUUID,
39931 paths = this._paths,
39932 parsedPaths = this._parsedPaths,
39933 bindings = this._bindings,
39934 nBindings = bindings.length,
39935 knownObject = undefined;
39936
39937 for ( var i = 0, n = arguments.length; i !== n; ++ i ) {
39938
39939 var object = arguments[ i ],
39940 uuid = object.uuid,
39941 index = indicesByUUID[ uuid ];
39942
39943 if ( index === undefined ) {
39944
39945 // unknown object -> add it to the ACTIVE region
39946
39947 index = nObjects ++;
39948 indicesByUUID[ uuid ] = index;
39949 objects.push( object );
39950
39951 // accounting is done, now do the same for all bindings
39952
39953 for ( var j = 0, m = nBindings; j !== m; ++ j ) {
39954
39955 bindings[ j ].push( new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ) );
39956
39957 }
39958
39959 } else if ( index < nCachedObjects ) {
39960
39961 knownObject = objects[ index ];
39962
39963 // move existing object to the ACTIVE region
39964
39965 var firstActiveIndex = -- nCachedObjects,
39966 lastCachedObject = objects[ firstActiveIndex ];
39967
39968 indicesByUUID[ lastCachedObject.uuid ] = index;
39969 objects[ index ] = lastCachedObject;
39970
39971 indicesByUUID[ uuid ] = firstActiveIndex;
39972 objects[ firstActiveIndex ] = object;
39973
39974 // accounting is done, now do the same for all bindings
39975
39976 for ( var j = 0, m = nBindings; j !== m; ++ j ) {
39977
39978 var bindingsForPath = bindings[ j ],
39979 lastCached = bindingsForPath[ firstActiveIndex ],
39980 binding = bindingsForPath[ index ];
39981
39982 bindingsForPath[ index ] = lastCached;
39983
39984 if ( binding === undefined ) {
39985
39986 // since we do not bother to create new bindings
39987 // for objects that are cached, the binding may
39988 // or may not exist
39989
39990 binding = new PropertyBinding( object, paths[ j ], parsedPaths[ j ] );
39991
39992 }
39993
39994 bindingsForPath[ firstActiveIndex ] = binding;
39995
39996 }
39997
39998 } else if ( objects[ index ] !== knownObject ) {
39999
40000 console.error( 'THREE.AnimationObjectGroup: Different objects with the same UUID ' +
40001 'detected. Clean the caches or recreate your infrastructure when reloading scenes.' );
40002
40003 } // else the object is already where we want it to be
40004
40005 } // for arguments
40006
40007 this.nCachedObjects_ = nCachedObjects;
40008
40009 },
40010
40011 remove: function () {
40012
40013 var objects = this._objects,
40014 nCachedObjects = this.nCachedObjects_,
40015 indicesByUUID = this._indicesByUUID,
40016 bindings = this._bindings,
40017 nBindings = bindings.length;
40018
40019 for ( var i = 0, n = arguments.length; i !== n; ++ i ) {
40020
40021 var object = arguments[ i ],
40022 uuid = object.uuid,
40023 index = indicesByUUID[ uuid ];
40024
40025 if ( index !== undefined && index >= nCachedObjects ) {
40026
40027 // move existing object into the CACHED region
40028
40029 var lastCachedIndex = nCachedObjects ++,
40030 firstActiveObject = objects[ lastCachedIndex ];
40031
40032 indicesByUUID[ firstActiveObject.uuid ] = index;
40033 objects[ index ] = firstActiveObject;
40034
40035 indicesByUUID[ uuid ] = lastCachedIndex;
40036 objects[ lastCachedIndex ] = object;
40037
40038 // accounting is done, now do the same for all bindings
40039
40040 for ( var j = 0, m = nBindings; j !== m; ++ j ) {
40041
40042 var bindingsForPath = bindings[ j ],
40043 firstActive = bindingsForPath[ lastCachedIndex ],
40044 binding = bindingsForPath[ index ];
40045
40046 bindingsForPath[ index ] = firstActive;
40047 bindingsForPath[ lastCachedIndex ] = binding;
40048
40049 }
40050
40051 }
40052
40053 } // for arguments
40054
40055 this.nCachedObjects_ = nCachedObjects;
40056
40057 },
40058
40059 // remove & forget
40060 uncache: function () {
40061
40062 var objects = this._objects,
40063 nObjects = objects.length,
40064 nCachedObjects = this.nCachedObjects_,
40065 indicesByUUID = this._indicesByUUID,
40066 bindings = this._bindings,
40067 nBindings = bindings.length;
40068
40069 for ( var i = 0, n = arguments.length; i !== n; ++ i ) {
40070
40071 var object = arguments[ i ],
40072 uuid = object.uuid,
40073 index = indicesByUUID[ uuid ];
40074
40075 if ( index !== undefined ) {
40076
40077 delete indicesByUUID[ uuid ];
40078
40079 if ( index < nCachedObjects ) {
40080
40081 // object is cached, shrink the CACHED region
40082
40083 var firstActiveIndex = -- nCachedObjects,
40084 lastCachedObject = objects[ firstActiveIndex ],
40085 lastIndex = -- nObjects,
40086 lastObject = objects[ lastIndex ];
40087
40088 // last cached object takes this object's place
40089 indicesByUUID[ lastCachedObject.uuid ] = index;
40090 objects[ index ] = lastCachedObject;
40091
40092 // last object goes to the activated slot and pop
40093 indicesByUUID[ lastObject.uuid ] = firstActiveIndex;
40094 objects[ firstActiveIndex ] = lastObject;
40095 objects.pop();
40096
40097 // accounting is done, now do the same for all bindings
40098
40099 for ( var j = 0, m = nBindings; j !== m; ++ j ) {
40100
40101 var bindingsForPath = bindings[ j ],
40102 lastCached = bindingsForPath[ firstActiveIndex ],
40103 last = bindingsForPath[ lastIndex ];
40104
40105 bindingsForPath[ index ] = lastCached;
40106 bindingsForPath[ firstActiveIndex ] = last;
40107 bindingsForPath.pop();
40108
40109 }
40110
40111 } else {
40112
40113 // object is active, just swap with the last and pop
40114
40115 var lastIndex = -- nObjects,
40116 lastObject = objects[ lastIndex ];
40117
40118 indicesByUUID[ lastObject.uuid ] = index;
40119 objects[ index ] = lastObject;
40120 objects.pop();
40121
40122 // accounting is done, now do the same for all bindings
40123
40124 for ( var j = 0, m = nBindings; j !== m; ++ j ) {
40125
40126 var bindingsForPath = bindings[ j ];
40127
40128 bindingsForPath[ index ] = bindingsForPath[ lastIndex ];
40129 bindingsForPath.pop();
40130
40131 }
40132
40133 } // cached or active
40134
40135 } // if object is known
40136
40137 } // for arguments
40138
40139 this.nCachedObjects_ = nCachedObjects;
40140
40141 },
40142
40143 // Internal interface used by befriended PropertyBinding.Composite:
40144
40145 subscribe_: function ( path, parsedPath ) {
40146
40147 // returns an array of bindings for the given path that is changed
40148 // according to the contained objects in the group
40149
40150 var indicesByPath = this._bindingsIndicesByPath,
40151 index = indicesByPath[ path ],
40152 bindings = this._bindings;
40153
40154 if ( index !== undefined ) return bindings[ index ];
40155
40156 var paths = this._paths,
40157 parsedPaths = this._parsedPaths,
40158 objects = this._objects,
40159 nObjects = objects.length,
40160 nCachedObjects = this.nCachedObjects_,
40161 bindingsForPath = new Array( nObjects );
40162
40163 index = bindings.length;
40164
40165 indicesByPath[ path ] = index;
40166
40167 paths.push( path );
40168 parsedPaths.push( parsedPath );
40169 bindings.push( bindingsForPath );
40170
40171 for ( var i = nCachedObjects, n = objects.length; i !== n; ++ i ) {
40172
40173 var object = objects[ i ];
40174 bindingsForPath[ i ] = new PropertyBinding( object, path, parsedPath );
40175
40176 }
40177
40178 return bindingsForPath;
40179
40180 },
40181
40182 unsubscribe_: function ( path ) {
40183
40184 // tells the group to forget about a property path and no longer
40185 // update the array previously obtained with 'subscribe_'
40186
40187 var indicesByPath = this._bindingsIndicesByPath,
40188 index = indicesByPath[ path ];
40189
40190 if ( index !== undefined ) {
40191
40192 var paths = this._paths,
40193 parsedPaths = this._parsedPaths,
40194 bindings = this._bindings,
40195 lastBindingsIndex = bindings.length - 1,
40196 lastBindings = bindings[ lastBindingsIndex ],
40197 lastBindingsPath = path[ lastBindingsIndex ];
40198
40199 indicesByPath[ lastBindingsPath ] = index;
40200
40201 bindings[ index ] = lastBindings;
40202 bindings.pop();
40203
40204 parsedPaths[ index ] = parsedPaths[ lastBindingsIndex ];
40205 parsedPaths.pop();
40206
40207 paths[ index ] = paths[ lastBindingsIndex ];
40208 paths.pop();
40209
40210 }
40211
40212 }
40213
40214} );
40215
40216/**
40217 *
40218 * Action provided by AnimationMixer for scheduling clip playback on specific
40219 * objects.
40220 *
40221 * @author Ben Houston / http://clara.io/
40222 * @author David Sarno / http://lighthaus.us/
40223 * @author tschw
40224 *
40225 */
40226
40227function AnimationAction( mixer, clip, localRoot ) {
40228
40229 this._mixer = mixer;
40230 this._clip = clip;
40231 this._localRoot = localRoot || null;
40232
40233 var tracks = clip.tracks,
40234 nTracks = tracks.length,
40235 interpolants = new Array( nTracks );
40236
40237 var interpolantSettings = {
40238 endingStart: ZeroCurvatureEnding,
40239 endingEnd: ZeroCurvatureEnding
40240 };
40241
40242 for ( var i = 0; i !== nTracks; ++ i ) {
40243
40244 var interpolant = tracks[ i ].createInterpolant( null );
40245 interpolants[ i ] = interpolant;
40246 interpolant.settings = interpolantSettings;
40247
40248 }
40249
40250 this._interpolantSettings = interpolantSettings;
40251
40252 this._interpolants = interpolants; // bound by the mixer
40253
40254 // inside: PropertyMixer (managed by the mixer)
40255 this._propertyBindings = new Array( nTracks );
40256
40257 this._cacheIndex = null; // for the memory manager
40258 this._byClipCacheIndex = null; // for the memory manager
40259
40260 this._timeScaleInterpolant = null;
40261 this._weightInterpolant = null;
40262
40263 this.loop = LoopRepeat;
40264 this._loopCount = - 1;
40265
40266 // global mixer time when the action is to be started
40267 // it's set back to 'null' upon start of the action
40268 this._startTime = null;
40269
40270 // scaled local time of the action
40271 // gets clamped or wrapped to 0..clip.duration according to loop
40272 this.time = 0;
40273
40274 this.timeScale = 1;
40275 this._effectiveTimeScale = 1;
40276
40277 this.weight = 1;
40278 this._effectiveWeight = 1;
40279
40280 this.repetitions = Infinity; // no. of repetitions when looping
40281
40282 this.paused = false; // true -> zero effective time scale
40283 this.enabled = true; // false -> zero effective weight
40284
40285 this.clampWhenFinished = false; // keep feeding the last frame?
40286
40287 this.zeroSlopeAtStart = true; // for smooth interpolation w/o separate
40288 this.zeroSlopeAtEnd = true; // clips for start, loop and end
40289
40290}
40291
40292Object.assign( AnimationAction.prototype, {
40293
40294 // State & Scheduling
40295
40296 play: function () {
40297
40298 this._mixer._activateAction( this );
40299
40300 return this;
40301
40302 },
40303
40304 stop: function () {
40305
40306 this._mixer._deactivateAction( this );
40307
40308 return this.reset();
40309
40310 },
40311
40312 reset: function () {
40313
40314 this.paused = false;
40315 this.enabled = true;
40316
40317 this.time = 0; // restart clip
40318 this._loopCount = - 1; // forget previous loops
40319 this._startTime = null; // forget scheduling
40320
40321 return this.stopFading().stopWarping();
40322
40323 },
40324
40325 isRunning: function () {
40326
40327 return this.enabled && ! this.paused && this.timeScale !== 0 &&
40328 this._startTime === null && this._mixer._isActiveAction( this );
40329
40330 },
40331
40332 // return true when play has been called
40333 isScheduled: function () {
40334
40335 return this._mixer._isActiveAction( this );
40336
40337 },
40338
40339 startAt: function ( time ) {
40340
40341 this._startTime = time;
40342
40343 return this;
40344
40345 },
40346
40347 setLoop: function ( mode, repetitions ) {
40348
40349 this.loop = mode;
40350 this.repetitions = repetitions;
40351
40352 return this;
40353
40354 },
40355
40356 // Weight
40357
40358 // set the weight stopping any scheduled fading
40359 // although .enabled = false yields an effective weight of zero, this
40360 // method does *not* change .enabled, because it would be confusing
40361 setEffectiveWeight: function ( weight ) {
40362
40363 this.weight = weight;
40364
40365 // note: same logic as when updated at runtime
40366 this._effectiveWeight = this.enabled ? weight : 0;
40367
40368 return this.stopFading();
40369
40370 },
40371
40372 // return the weight considering fading and .enabled
40373 getEffectiveWeight: function () {
40374
40375 return this._effectiveWeight;
40376
40377 },
40378
40379 fadeIn: function ( duration ) {
40380
40381 return this._scheduleFading( duration, 0, 1 );
40382
40383 },
40384
40385 fadeOut: function ( duration ) {
40386
40387 return this._scheduleFading( duration, 1, 0 );
40388
40389 },
40390
40391 crossFadeFrom: function ( fadeOutAction, duration, warp ) {
40392
40393 fadeOutAction.fadeOut( duration );
40394 this.fadeIn( duration );
40395
40396 if ( warp ) {
40397
40398 var fadeInDuration = this._clip.duration,
40399 fadeOutDuration = fadeOutAction._clip.duration,
40400
40401 startEndRatio = fadeOutDuration / fadeInDuration,
40402 endStartRatio = fadeInDuration / fadeOutDuration;
40403
40404 fadeOutAction.warp( 1.0, startEndRatio, duration );
40405 this.warp( endStartRatio, 1.0, duration );
40406
40407 }
40408
40409 return this;
40410
40411 },
40412
40413 crossFadeTo: function ( fadeInAction, duration, warp ) {
40414
40415 return fadeInAction.crossFadeFrom( this, duration, warp );
40416
40417 },
40418
40419 stopFading: function () {
40420
40421 var weightInterpolant = this._weightInterpolant;
40422
40423 if ( weightInterpolant !== null ) {
40424
40425 this._weightInterpolant = null;
40426 this._mixer._takeBackControlInterpolant( weightInterpolant );
40427
40428 }
40429
40430 return this;
40431
40432 },
40433
40434 // Time Scale Control
40435
40436 // set the time scale stopping any scheduled warping
40437 // although .paused = true yields an effective time scale of zero, this
40438 // method does *not* change .paused, because it would be confusing
40439 setEffectiveTimeScale: function ( timeScale ) {
40440
40441 this.timeScale = timeScale;
40442 this._effectiveTimeScale = this.paused ? 0 : timeScale;
40443
40444 return this.stopWarping();
40445
40446 },
40447
40448 // return the time scale considering warping and .paused
40449 getEffectiveTimeScale: function () {
40450
40451 return this._effectiveTimeScale;
40452
40453 },
40454
40455 setDuration: function ( duration ) {
40456
40457 this.timeScale = this._clip.duration / duration;
40458
40459 return this.stopWarping();
40460
40461 },
40462
40463 syncWith: function ( action ) {
40464
40465 this.time = action.time;
40466 this.timeScale = action.timeScale;
40467
40468 return this.stopWarping();
40469
40470 },
40471
40472 halt: function ( duration ) {
40473
40474 return this.warp( this._effectiveTimeScale, 0, duration );
40475
40476 },
40477
40478 warp: function ( startTimeScale, endTimeScale, duration ) {
40479
40480 var mixer = this._mixer, now = mixer.time,
40481 interpolant = this._timeScaleInterpolant,
40482
40483 timeScale = this.timeScale;
40484
40485 if ( interpolant === null ) {
40486
40487 interpolant = mixer._lendControlInterpolant();
40488 this._timeScaleInterpolant = interpolant;
40489
40490 }
40491
40492 var times = interpolant.parameterPositions,
40493 values = interpolant.sampleValues;
40494
40495 times[ 0 ] = now;
40496 times[ 1 ] = now + duration;
40497
40498 values[ 0 ] = startTimeScale / timeScale;
40499 values[ 1 ] = endTimeScale / timeScale;
40500
40501 return this;
40502
40503 },
40504
40505 stopWarping: function () {
40506
40507 var timeScaleInterpolant = this._timeScaleInterpolant;
40508
40509 if ( timeScaleInterpolant !== null ) {
40510
40511 this._timeScaleInterpolant = null;
40512 this._mixer._takeBackControlInterpolant( timeScaleInterpolant );
40513
40514 }
40515
40516 return this;
40517
40518 },
40519
40520 // Object Accessors
40521
40522 getMixer: function () {
40523
40524 return this._mixer;
40525
40526 },
40527
40528 getClip: function () {
40529
40530 return this._clip;
40531
40532 },
40533
40534 getRoot: function () {
40535
40536 return this._localRoot || this._mixer._root;
40537
40538 },
40539
40540 // Interna
40541
40542 _update: function ( time, deltaTime, timeDirection, accuIndex ) {
40543
40544 // called by the mixer
40545
40546 if ( ! this.enabled ) {
40547
40548 // call ._updateWeight() to update ._effectiveWeight
40549
40550 this._updateWeight( time );
40551 return;
40552
40553 }
40554
40555 var startTime = this._startTime;
40556
40557 if ( startTime !== null ) {
40558
40559 // check for scheduled start of action
40560
40561 var timeRunning = ( time - startTime ) * timeDirection;
40562 if ( timeRunning < 0 || timeDirection === 0 ) {
40563
40564 return; // yet to come / don't decide when delta = 0
40565
40566 }
40567
40568 // start
40569
40570 this._startTime = null; // unschedule
40571 deltaTime = timeDirection * timeRunning;
40572
40573 }
40574
40575 // apply time scale and advance time
40576
40577 deltaTime *= this._updateTimeScale( time );
40578 var clipTime = this._updateTime( deltaTime );
40579
40580 // note: _updateTime may disable the action resulting in
40581 // an effective weight of 0
40582
40583 var weight = this._updateWeight( time );
40584
40585 if ( weight > 0 ) {
40586
40587 var interpolants = this._interpolants;
40588 var propertyMixers = this._propertyBindings;
40589
40590 for ( var j = 0, m = interpolants.length; j !== m; ++ j ) {
40591
40592 interpolants[ j ].evaluate( clipTime );
40593 propertyMixers[ j ].accumulate( accuIndex, weight );
40594
40595 }
40596
40597 }
40598
40599 },
40600
40601 _updateWeight: function ( time ) {
40602
40603 var weight = 0;
40604
40605 if ( this.enabled ) {
40606
40607 weight = this.weight;
40608 var interpolant = this._weightInterpolant;
40609
40610 if ( interpolant !== null ) {
40611
40612 var interpolantValue = interpolant.evaluate( time )[ 0 ];
40613
40614 weight *= interpolantValue;
40615
40616 if ( time > interpolant.parameterPositions[ 1 ] ) {
40617
40618 this.stopFading();
40619
40620 if ( interpolantValue === 0 ) {
40621
40622 // faded out, disable
40623 this.enabled = false;
40624
40625 }
40626
40627 }
40628
40629 }
40630
40631 }
40632
40633 this._effectiveWeight = weight;
40634 return weight;
40635
40636 },
40637
40638 _updateTimeScale: function ( time ) {
40639
40640 var timeScale = 0;
40641
40642 if ( ! this.paused ) {
40643
40644 timeScale = this.timeScale;
40645
40646 var interpolant = this._timeScaleInterpolant;
40647
40648 if ( interpolant !== null ) {
40649
40650 var interpolantValue = interpolant.evaluate( time )[ 0 ];
40651
40652 timeScale *= interpolantValue;
40653
40654 if ( time > interpolant.parameterPositions[ 1 ] ) {
40655
40656 this.stopWarping();
40657
40658 if ( timeScale === 0 ) {
40659
40660 // motion has halted, pause
40661 this.paused = true;
40662
40663 } else {
40664
40665 // warp done - apply final time scale
40666 this.timeScale = timeScale;
40667
40668 }
40669
40670 }
40671
40672 }
40673
40674 }
40675
40676 this._effectiveTimeScale = timeScale;
40677 return timeScale;
40678
40679 },
40680
40681 _updateTime: function ( deltaTime ) {
40682
40683 var time = this.time + deltaTime;
40684
40685 if ( deltaTime === 0 ) return time;
40686
40687 var duration = this._clip.duration,
40688
40689 loop = this.loop,
40690 loopCount = this._loopCount;
40691
40692 if ( loop === LoopOnce ) {
40693
40694 if ( loopCount === - 1 ) {
40695
40696 // just started
40697
40698 this._loopCount = 0;
40699 this._setEndings( true, true, false );
40700
40701 }
40702
40703 handle_stop: {
40704
40705 if ( time >= duration ) {
40706
40707 time = duration;
40708
40709 } else if ( time < 0 ) {
40710
40711 time = 0;
40712
40713 } else break handle_stop;
40714
40715 if ( this.clampWhenFinished ) this.paused = true;
40716 else this.enabled = false;
40717
40718 this._mixer.dispatchEvent( {
40719 type: 'finished', action: this,
40720 direction: deltaTime < 0 ? - 1 : 1
40721 } );
40722
40723 }
40724
40725 } else { // repetitive Repeat or PingPong
40726
40727 var pingPong = ( loop === LoopPingPong );
40728
40729 if ( loopCount === - 1 ) {
40730
40731 // just started
40732
40733 if ( deltaTime >= 0 ) {
40734
40735 loopCount = 0;
40736
40737 this._setEndings( true, this.repetitions === 0, pingPong );
40738
40739 } else {
40740
40741 // when looping in reverse direction, the initial
40742 // transition through zero counts as a repetition,
40743 // so leave loopCount at -1
40744
40745 this._setEndings( this.repetitions === 0, true, pingPong );
40746
40747 }
40748
40749 }
40750
40751 if ( time >= duration || time < 0 ) {
40752
40753 // wrap around
40754
40755 var loopDelta = Math.floor( time / duration ); // signed
40756 time -= duration * loopDelta;
40757
40758 loopCount += Math.abs( loopDelta );
40759
40760 var pending = this.repetitions - loopCount;
40761
40762 if ( pending <= 0 ) {
40763
40764 // have to stop (switch state, clamp time, fire event)
40765
40766 if ( this.clampWhenFinished ) this.paused = true;
40767 else this.enabled = false;
40768
40769 time = deltaTime > 0 ? duration : 0;
40770
40771 this._mixer.dispatchEvent( {
40772 type: 'finished', action: this,
40773 direction: deltaTime > 0 ? 1 : - 1
40774 } );
40775
40776 } else {
40777
40778 // keep running
40779
40780 if ( pending === 1 ) {
40781
40782 // entering the last round
40783
40784 var atStart = deltaTime < 0;
40785 this._setEndings( atStart, ! atStart, pingPong );
40786
40787 } else {
40788
40789 this._setEndings( false, false, pingPong );
40790
40791 }
40792
40793 this._loopCount = loopCount;
40794
40795 this._mixer.dispatchEvent( {
40796 type: 'loop', action: this, loopDelta: loopDelta
40797 } );
40798
40799 }
40800
40801 }
40802
40803 if ( pingPong && ( loopCount & 1 ) === 1 ) {
40804
40805 // invert time for the "pong round"
40806
40807 this.time = time;
40808 return duration - time;
40809
40810 }
40811
40812 }
40813
40814 this.time = time;
40815 return time;
40816
40817 },
40818
40819 _setEndings: function ( atStart, atEnd, pingPong ) {
40820
40821 var settings = this._interpolantSettings;
40822
40823 if ( pingPong ) {
40824
40825 settings.endingStart = ZeroSlopeEnding;
40826 settings.endingEnd = ZeroSlopeEnding;
40827
40828 } else {
40829
40830 // assuming for LoopOnce atStart == atEnd == true
40831
40832 if ( atStart ) {
40833
40834 settings.endingStart = this.zeroSlopeAtStart ? ZeroSlopeEnding : ZeroCurvatureEnding;
40835
40836 } else {
40837
40838 settings.endingStart = WrapAroundEnding;
40839
40840 }
40841
40842 if ( atEnd ) {
40843
40844 settings.endingEnd = this.zeroSlopeAtEnd ? ZeroSlopeEnding : ZeroCurvatureEnding;
40845
40846 } else {
40847
40848 settings.endingEnd = WrapAroundEnding;
40849
40850 }
40851
40852 }
40853
40854 },
40855
40856 _scheduleFading: function ( duration, weightNow, weightThen ) {
40857
40858 var mixer = this._mixer, now = mixer.time,
40859 interpolant = this._weightInterpolant;
40860
40861 if ( interpolant === null ) {
40862
40863 interpolant = mixer._lendControlInterpolant();
40864 this._weightInterpolant = interpolant;
40865
40866 }
40867
40868 var times = interpolant.parameterPositions,
40869 values = interpolant.sampleValues;
40870
40871 times[ 0 ] = now; values[ 0 ] = weightNow;
40872 times[ 1 ] = now + duration; values[ 1 ] = weightThen;
40873
40874 return this;
40875
40876 }
40877
40878} );
40879
40880/**
40881 *
40882 * Player for AnimationClips.
40883 *
40884 *
40885 * @author Ben Houston / http://clara.io/
40886 * @author David Sarno / http://lighthaus.us/
40887 * @author tschw
40888 */
40889
40890function AnimationMixer( root ) {
40891
40892 this._root = root;
40893 this._initMemoryManager();
40894 this._accuIndex = 0;
40895
40896 this.time = 0;
40897
40898 this.timeScale = 1.0;
40899
40900}
40901
40902AnimationMixer.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
40903
40904 constructor: AnimationMixer,
40905
40906 _bindAction: function ( action, prototypeAction ) {
40907
40908 var root = action._localRoot || this._root,
40909 tracks = action._clip.tracks,
40910 nTracks = tracks.length,
40911 bindings = action._propertyBindings,
40912 interpolants = action._interpolants,
40913 rootUuid = root.uuid,
40914 bindingsByRoot = this._bindingsByRootAndName,
40915 bindingsByName = bindingsByRoot[ rootUuid ];
40916
40917 if ( bindingsByName === undefined ) {
40918
40919 bindingsByName = {};
40920 bindingsByRoot[ rootUuid ] = bindingsByName;
40921
40922 }
40923
40924 for ( var i = 0; i !== nTracks; ++ i ) {
40925
40926 var track = tracks[ i ],
40927 trackName = track.name,
40928 binding = bindingsByName[ trackName ];
40929
40930 if ( binding !== undefined ) {
40931
40932 bindings[ i ] = binding;
40933
40934 } else {
40935
40936 binding = bindings[ i ];
40937
40938 if ( binding !== undefined ) {
40939
40940 // existing binding, make sure the cache knows
40941
40942 if ( binding._cacheIndex === null ) {
40943
40944 ++ binding.referenceCount;
40945 this._addInactiveBinding( binding, rootUuid, trackName );
40946
40947 }
40948
40949 continue;
40950
40951 }
40952
40953 var path = prototypeAction && prototypeAction.
40954 _propertyBindings[ i ].binding.parsedPath;
40955
40956 binding = new PropertyMixer(
40957 PropertyBinding.create( root, trackName, path ),
40958 track.ValueTypeName, track.getValueSize() );
40959
40960 ++ binding.referenceCount;
40961 this._addInactiveBinding( binding, rootUuid, trackName );
40962
40963 bindings[ i ] = binding;
40964
40965 }
40966
40967 interpolants[ i ].resultBuffer = binding.buffer;
40968
40969 }
40970
40971 },
40972
40973 _activateAction: function ( action ) {
40974
40975 if ( ! this._isActiveAction( action ) ) {
40976
40977 if ( action._cacheIndex === null ) {
40978
40979 // this action has been forgotten by the cache, but the user
40980 // appears to be still using it -> rebind
40981
40982 var rootUuid = ( action._localRoot || this._root ).uuid,
40983 clipUuid = action._clip.uuid,
40984 actionsForClip = this._actionsByClip[ clipUuid ];
40985
40986 this._bindAction( action,
40987 actionsForClip && actionsForClip.knownActions[ 0 ] );
40988
40989 this._addInactiveAction( action, clipUuid, rootUuid );
40990
40991 }
40992
40993 var bindings = action._propertyBindings;
40994
40995 // increment reference counts / sort out state
40996 for ( var i = 0, n = bindings.length; i !== n; ++ i ) {
40997
40998 var binding = bindings[ i ];
40999
41000 if ( binding.useCount ++ === 0 ) {
41001
41002 this._lendBinding( binding );
41003 binding.saveOriginalState();
41004
41005 }
41006
41007 }
41008
41009 this._lendAction( action );
41010
41011 }
41012
41013 },
41014
41015 _deactivateAction: function ( action ) {
41016
41017 if ( this._isActiveAction( action ) ) {
41018
41019 var bindings = action._propertyBindings;
41020
41021 // decrement reference counts / sort out state
41022 for ( var i = 0, n = bindings.length; i !== n; ++ i ) {
41023
41024 var binding = bindings[ i ];
41025
41026 if ( -- binding.useCount === 0 ) {
41027
41028 binding.restoreOriginalState();
41029 this._takeBackBinding( binding );
41030
41031 }
41032
41033 }
41034
41035 this._takeBackAction( action );
41036
41037 }
41038
41039 },
41040
41041 // Memory manager
41042
41043 _initMemoryManager: function () {
41044
41045 this._actions = []; // 'nActiveActions' followed by inactive ones
41046 this._nActiveActions = 0;
41047
41048 this._actionsByClip = {};
41049 // inside:
41050 // {
41051 // knownActions: Array< AnimationAction > - used as prototypes
41052 // actionByRoot: AnimationAction - lookup
41053 // }
41054
41055
41056 this._bindings = []; // 'nActiveBindings' followed by inactive ones
41057 this._nActiveBindings = 0;
41058
41059 this._bindingsByRootAndName = {}; // inside: Map< name, PropertyMixer >
41060
41061
41062 this._controlInterpolants = []; // same game as above
41063 this._nActiveControlInterpolants = 0;
41064
41065 var scope = this;
41066
41067 this.stats = {
41068
41069 actions: {
41070 get total() {
41071
41072 return scope._actions.length;
41073
41074 },
41075 get inUse() {
41076
41077 return scope._nActiveActions;
41078
41079 }
41080 },
41081 bindings: {
41082 get total() {
41083
41084 return scope._bindings.length;
41085
41086 },
41087 get inUse() {
41088
41089 return scope._nActiveBindings;
41090
41091 }
41092 },
41093 controlInterpolants: {
41094 get total() {
41095
41096 return scope._controlInterpolants.length;
41097
41098 },
41099 get inUse() {
41100
41101 return scope._nActiveControlInterpolants;
41102
41103 }
41104 }
41105
41106 };
41107
41108 },
41109
41110 // Memory management for AnimationAction objects
41111
41112 _isActiveAction: function ( action ) {
41113
41114 var index = action._cacheIndex;
41115 return index !== null && index < this._nActiveActions;
41116
41117 },
41118
41119 _addInactiveAction: function ( action, clipUuid, rootUuid ) {
41120
41121 var actions = this._actions,
41122 actionsByClip = this._actionsByClip,
41123 actionsForClip = actionsByClip[ clipUuid ];
41124
41125 if ( actionsForClip === undefined ) {
41126
41127 actionsForClip = {
41128
41129 knownActions: [ action ],
41130 actionByRoot: {}
41131
41132 };
41133
41134 action._byClipCacheIndex = 0;
41135
41136 actionsByClip[ clipUuid ] = actionsForClip;
41137
41138 } else {
41139
41140 var knownActions = actionsForClip.knownActions;
41141
41142 action._byClipCacheIndex = knownActions.length;
41143 knownActions.push( action );
41144
41145 }
41146
41147 action._cacheIndex = actions.length;
41148 actions.push( action );
41149
41150 actionsForClip.actionByRoot[ rootUuid ] = action;
41151
41152 },
41153
41154 _removeInactiveAction: function ( action ) {
41155
41156 var actions = this._actions,
41157 lastInactiveAction = actions[ actions.length - 1 ],
41158 cacheIndex = action._cacheIndex;
41159
41160 lastInactiveAction._cacheIndex = cacheIndex;
41161 actions[ cacheIndex ] = lastInactiveAction;
41162 actions.pop();
41163
41164 action._cacheIndex = null;
41165
41166
41167 var clipUuid = action._clip.uuid,
41168 actionsByClip = this._actionsByClip,
41169 actionsForClip = actionsByClip[ clipUuid ],
41170 knownActionsForClip = actionsForClip.knownActions,
41171
41172 lastKnownAction =
41173 knownActionsForClip[ knownActionsForClip.length - 1 ],
41174
41175 byClipCacheIndex = action._byClipCacheIndex;
41176
41177 lastKnownAction._byClipCacheIndex = byClipCacheIndex;
41178 knownActionsForClip[ byClipCacheIndex ] = lastKnownAction;
41179 knownActionsForClip.pop();
41180
41181 action._byClipCacheIndex = null;
41182
41183
41184 var actionByRoot = actionsForClip.actionByRoot,
41185 rootUuid = ( action._localRoot || this._root ).uuid;
41186
41187 delete actionByRoot[ rootUuid ];
41188
41189 if ( knownActionsForClip.length === 0 ) {
41190
41191 delete actionsByClip[ clipUuid ];
41192
41193 }
41194
41195 this._removeInactiveBindingsForAction( action );
41196
41197 },
41198
41199 _removeInactiveBindingsForAction: function ( action ) {
41200
41201 var bindings = action._propertyBindings;
41202 for ( var i = 0, n = bindings.length; i !== n; ++ i ) {
41203
41204 var binding = bindings[ i ];
41205
41206 if ( -- binding.referenceCount === 0 ) {
41207
41208 this._removeInactiveBinding( binding );
41209
41210 }
41211
41212 }
41213
41214 },
41215
41216 _lendAction: function ( action ) {
41217
41218 // [ active actions | inactive actions ]
41219 // [ active actions >| inactive actions ]
41220 // s a
41221 // <-swap->
41222 // a s
41223
41224 var actions = this._actions,
41225 prevIndex = action._cacheIndex,
41226
41227 lastActiveIndex = this._nActiveActions ++,
41228
41229 firstInactiveAction = actions[ lastActiveIndex ];
41230
41231 action._cacheIndex = lastActiveIndex;
41232 actions[ lastActiveIndex ] = action;
41233
41234 firstInactiveAction._cacheIndex = prevIndex;
41235 actions[ prevIndex ] = firstInactiveAction;
41236
41237 },
41238
41239 _takeBackAction: function ( action ) {
41240
41241 // [ active actions | inactive actions ]
41242 // [ active actions |< inactive actions ]
41243 // a s
41244 // <-swap->
41245 // s a
41246
41247 var actions = this._actions,
41248 prevIndex = action._cacheIndex,
41249
41250 firstInactiveIndex = -- this._nActiveActions,
41251
41252 lastActiveAction = actions[ firstInactiveIndex ];
41253
41254 action._cacheIndex = firstInactiveIndex;
41255 actions[ firstInactiveIndex ] = action;
41256
41257 lastActiveAction._cacheIndex = prevIndex;
41258 actions[ prevIndex ] = lastActiveAction;
41259
41260 },
41261
41262 // Memory management for PropertyMixer objects
41263
41264 _addInactiveBinding: function ( binding, rootUuid, trackName ) {
41265
41266 var bindingsByRoot = this._bindingsByRootAndName,
41267 bindingByName = bindingsByRoot[ rootUuid ],
41268
41269 bindings = this._bindings;
41270
41271 if ( bindingByName === undefined ) {
41272
41273 bindingByName = {};
41274 bindingsByRoot[ rootUuid ] = bindingByName;
41275
41276 }
41277
41278 bindingByName[ trackName ] = binding;
41279
41280 binding._cacheIndex = bindings.length;
41281 bindings.push( binding );
41282
41283 },
41284
41285 _removeInactiveBinding: function ( binding ) {
41286
41287 var bindings = this._bindings,
41288 propBinding = binding.binding,
41289 rootUuid = propBinding.rootNode.uuid,
41290 trackName = propBinding.path,
41291 bindingsByRoot = this._bindingsByRootAndName,
41292 bindingByName = bindingsByRoot[ rootUuid ],
41293
41294 lastInactiveBinding = bindings[ bindings.length - 1 ],
41295 cacheIndex = binding._cacheIndex;
41296
41297 lastInactiveBinding._cacheIndex = cacheIndex;
41298 bindings[ cacheIndex ] = lastInactiveBinding;
41299 bindings.pop();
41300
41301 delete bindingByName[ trackName ];
41302
41303 remove_empty_map: {
41304
41305 for ( var _ in bindingByName ) break remove_empty_map; // eslint-disable-line no-unused-vars
41306
41307 delete bindingsByRoot[ rootUuid ];
41308
41309 }
41310
41311 },
41312
41313 _lendBinding: function ( binding ) {
41314
41315 var bindings = this._bindings,
41316 prevIndex = binding._cacheIndex,
41317
41318 lastActiveIndex = this._nActiveBindings ++,
41319
41320 firstInactiveBinding = bindings[ lastActiveIndex ];
41321
41322 binding._cacheIndex = lastActiveIndex;
41323 bindings[ lastActiveIndex ] = binding;
41324
41325 firstInactiveBinding._cacheIndex = prevIndex;
41326 bindings[ prevIndex ] = firstInactiveBinding;
41327
41328 },
41329
41330 _takeBackBinding: function ( binding ) {
41331
41332 var bindings = this._bindings,
41333 prevIndex = binding._cacheIndex,
41334
41335 firstInactiveIndex = -- this._nActiveBindings,
41336
41337 lastActiveBinding = bindings[ firstInactiveIndex ];
41338
41339 binding._cacheIndex = firstInactiveIndex;
41340 bindings[ firstInactiveIndex ] = binding;
41341
41342 lastActiveBinding._cacheIndex = prevIndex;
41343 bindings[ prevIndex ] = lastActiveBinding;
41344
41345 },
41346
41347
41348 // Memory management of Interpolants for weight and time scale
41349
41350 _lendControlInterpolant: function () {
41351
41352 var interpolants = this._controlInterpolants,
41353 lastActiveIndex = this._nActiveControlInterpolants ++,
41354 interpolant = interpolants[ lastActiveIndex ];
41355
41356 if ( interpolant === undefined ) {
41357
41358 interpolant = new LinearInterpolant(
41359 new Float32Array( 2 ), new Float32Array( 2 ),
41360 1, this._controlInterpolantsResultBuffer );
41361
41362 interpolant.__cacheIndex = lastActiveIndex;
41363 interpolants[ lastActiveIndex ] = interpolant;
41364
41365 }
41366
41367 return interpolant;
41368
41369 },
41370
41371 _takeBackControlInterpolant: function ( interpolant ) {
41372
41373 var interpolants = this._controlInterpolants,
41374 prevIndex = interpolant.__cacheIndex,
41375
41376 firstInactiveIndex = -- this._nActiveControlInterpolants,
41377
41378 lastActiveInterpolant = interpolants[ firstInactiveIndex ];
41379
41380 interpolant.__cacheIndex = firstInactiveIndex;
41381 interpolants[ firstInactiveIndex ] = interpolant;
41382
41383 lastActiveInterpolant.__cacheIndex = prevIndex;
41384 interpolants[ prevIndex ] = lastActiveInterpolant;
41385
41386 },
41387
41388 _controlInterpolantsResultBuffer: new Float32Array( 1 ),
41389
41390 // return an action for a clip optionally using a custom root target
41391 // object (this method allocates a lot of dynamic memory in case a
41392 // previously unknown clip/root combination is specified)
41393 clipAction: function ( clip, optionalRoot ) {
41394
41395 var root = optionalRoot || this._root,
41396 rootUuid = root.uuid,
41397
41398 clipObject = typeof clip === 'string' ?
41399 AnimationClip.findByName( root, clip ) : clip,
41400
41401 clipUuid = clipObject !== null ? clipObject.uuid : clip,
41402
41403 actionsForClip = this._actionsByClip[ clipUuid ],
41404 prototypeAction = null;
41405
41406 if ( actionsForClip !== undefined ) {
41407
41408 var existingAction =
41409 actionsForClip.actionByRoot[ rootUuid ];
41410
41411 if ( existingAction !== undefined ) {
41412
41413 return existingAction;
41414
41415 }
41416
41417 // we know the clip, so we don't have to parse all
41418 // the bindings again but can just copy
41419 prototypeAction = actionsForClip.knownActions[ 0 ];
41420
41421 // also, take the clip from the prototype action
41422 if ( clipObject === null )
41423 clipObject = prototypeAction._clip;
41424
41425 }
41426
41427 // clip must be known when specified via string
41428 if ( clipObject === null ) return null;
41429
41430 // allocate all resources required to run it
41431 var newAction = new AnimationAction( this, clipObject, optionalRoot );
41432
41433 this._bindAction( newAction, prototypeAction );
41434
41435 // and make the action known to the memory manager
41436 this._addInactiveAction( newAction, clipUuid, rootUuid );
41437
41438 return newAction;
41439
41440 },
41441
41442 // get an existing action
41443 existingAction: function ( clip, optionalRoot ) {
41444
41445 var root = optionalRoot || this._root,
41446 rootUuid = root.uuid,
41447
41448 clipObject = typeof clip === 'string' ?
41449 AnimationClip.findByName( root, clip ) : clip,
41450
41451 clipUuid = clipObject ? clipObject.uuid : clip,
41452
41453 actionsForClip = this._actionsByClip[ clipUuid ];
41454
41455 if ( actionsForClip !== undefined ) {
41456
41457 return actionsForClip.actionByRoot[ rootUuid ] || null;
41458
41459 }
41460
41461 return null;
41462
41463 },
41464
41465 // deactivates all previously scheduled actions
41466 stopAllAction: function () {
41467
41468 var actions = this._actions,
41469 nActions = this._nActiveActions,
41470 bindings = this._bindings,
41471 nBindings = this._nActiveBindings;
41472
41473 this._nActiveActions = 0;
41474 this._nActiveBindings = 0;
41475
41476 for ( var i = 0; i !== nActions; ++ i ) {
41477
41478 actions[ i ].reset();
41479
41480 }
41481
41482 for ( var i = 0; i !== nBindings; ++ i ) {
41483
41484 bindings[ i ].useCount = 0;
41485
41486 }
41487
41488 return this;
41489
41490 },
41491
41492 // advance the time and update apply the animation
41493 update: function ( deltaTime ) {
41494
41495 deltaTime *= this.timeScale;
41496
41497 var actions = this._actions,
41498 nActions = this._nActiveActions,
41499
41500 time = this.time += deltaTime,
41501 timeDirection = Math.sign( deltaTime ),
41502
41503 accuIndex = this._accuIndex ^= 1;
41504
41505 // run active actions
41506
41507 for ( var i = 0; i !== nActions; ++ i ) {
41508
41509 var action = actions[ i ];
41510
41511 action._update( time, deltaTime, timeDirection, accuIndex );
41512
41513 }
41514
41515 // update scene graph
41516
41517 var bindings = this._bindings,
41518 nBindings = this._nActiveBindings;
41519
41520 for ( var i = 0; i !== nBindings; ++ i ) {
41521
41522 bindings[ i ].apply( accuIndex );
41523
41524 }
41525
41526 return this;
41527
41528 },
41529
41530 // return this mixer's root target object
41531 getRoot: function () {
41532
41533 return this._root;
41534
41535 },
41536
41537 // free all resources specific to a particular clip
41538 uncacheClip: function ( clip ) {
41539
41540 var actions = this._actions,
41541 clipUuid = clip.uuid,
41542 actionsByClip = this._actionsByClip,
41543 actionsForClip = actionsByClip[ clipUuid ];
41544
41545 if ( actionsForClip !== undefined ) {
41546
41547 // note: just calling _removeInactiveAction would mess up the
41548 // iteration state and also require updating the state we can
41549 // just throw away
41550
41551 var actionsToRemove = actionsForClip.knownActions;
41552
41553 for ( var i = 0, n = actionsToRemove.length; i !== n; ++ i ) {
41554
41555 var action = actionsToRemove[ i ];
41556
41557 this._deactivateAction( action );
41558
41559 var cacheIndex = action._cacheIndex,
41560 lastInactiveAction = actions[ actions.length - 1 ];
41561
41562 action._cacheIndex = null;
41563 action._byClipCacheIndex = null;
41564
41565 lastInactiveAction._cacheIndex = cacheIndex;
41566 actions[ cacheIndex ] = lastInactiveAction;
41567 actions.pop();
41568
41569 this._removeInactiveBindingsForAction( action );
41570
41571 }
41572
41573 delete actionsByClip[ clipUuid ];
41574
41575 }
41576
41577 },
41578
41579 // free all resources specific to a particular root target object
41580 uncacheRoot: function ( root ) {
41581
41582 var rootUuid = root.uuid,
41583 actionsByClip = this._actionsByClip;
41584
41585 for ( var clipUuid in actionsByClip ) {
41586
41587 var actionByRoot = actionsByClip[ clipUuid ].actionByRoot,
41588 action = actionByRoot[ rootUuid ];
41589
41590 if ( action !== undefined ) {
41591
41592 this._deactivateAction( action );
41593 this._removeInactiveAction( action );
41594
41595 }
41596
41597 }
41598
41599 var bindingsByRoot = this._bindingsByRootAndName,
41600 bindingByName = bindingsByRoot[ rootUuid ];
41601
41602 if ( bindingByName !== undefined ) {
41603
41604 for ( var trackName in bindingByName ) {
41605
41606 var binding = bindingByName[ trackName ];
41607 binding.restoreOriginalState();
41608 this._removeInactiveBinding( binding );
41609
41610 }
41611
41612 }
41613
41614 },
41615
41616 // remove a targeted clip from the cache
41617 uncacheAction: function ( clip, optionalRoot ) {
41618
41619 var action = this.existingAction( clip, optionalRoot );
41620
41621 if ( action !== null ) {
41622
41623 this._deactivateAction( action );
41624 this._removeInactiveAction( action );
41625
41626 }
41627
41628 }
41629
41630} );
41631
41632/**
41633 * @author mrdoob / http://mrdoob.com/
41634 */
41635
41636function Uniform( value ) {
41637
41638 if ( typeof value === 'string' ) {
41639
41640 console.warn( 'THREE.Uniform: Type parameter is no longer needed.' );
41641 value = arguments[ 1 ];
41642
41643 }
41644
41645 this.value = value;
41646
41647}
41648
41649Uniform.prototype.clone = function () {
41650
41651 return new Uniform( this.value.clone === undefined ? this.value : this.value.clone() );
41652
41653};
41654
41655/**
41656 * @author benaadams / https://twitter.com/ben_a_adams
41657 */
41658
41659function InstancedBufferGeometry() {
41660
41661 BufferGeometry.call( this );
41662
41663 this.type = 'InstancedBufferGeometry';
41664 this.maxInstancedCount = undefined;
41665
41666}
41667
41668InstancedBufferGeometry.prototype = Object.assign( Object.create( BufferGeometry.prototype ), {
41669
41670 constructor: InstancedBufferGeometry,
41671
41672 isInstancedBufferGeometry: true,
41673
41674 copy: function ( source ) {
41675
41676 BufferGeometry.prototype.copy.call( this, source );
41677
41678 this.maxInstancedCount = source.maxInstancedCount;
41679
41680 return this;
41681
41682 },
41683
41684 clone: function () {
41685
41686 return new this.constructor().copy( this );
41687
41688 }
41689
41690} );
41691
41692/**
41693 * @author benaadams / https://twitter.com/ben_a_adams
41694 */
41695
41696function InterleavedBufferAttribute( interleavedBuffer, itemSize, offset, normalized ) {
41697
41698 this.data = interleavedBuffer;
41699 this.itemSize = itemSize;
41700 this.offset = offset;
41701
41702 this.normalized = normalized === true;
41703
41704}
41705
41706Object.defineProperties( InterleavedBufferAttribute.prototype, {
41707
41708 count: {
41709
41710 get: function () {
41711
41712 return this.data.count;
41713
41714 }
41715
41716 },
41717
41718 array: {
41719
41720 get: function () {
41721
41722 return this.data.array;
41723
41724 }
41725
41726 }
41727
41728} );
41729
41730Object.assign( InterleavedBufferAttribute.prototype, {
41731
41732 isInterleavedBufferAttribute: true,
41733
41734 setX: function ( index, x ) {
41735
41736 this.data.array[ index * this.data.stride + this.offset ] = x;
41737
41738 return this;
41739
41740 },
41741
41742 setY: function ( index, y ) {
41743
41744 this.data.array[ index * this.data.stride + this.offset + 1 ] = y;
41745
41746 return this;
41747
41748 },
41749
41750 setZ: function ( index, z ) {
41751
41752 this.data.array[ index * this.data.stride + this.offset + 2 ] = z;
41753
41754 return this;
41755
41756 },
41757
41758 setW: function ( index, w ) {
41759
41760 this.data.array[ index * this.data.stride + this.offset + 3 ] = w;
41761
41762 return this;
41763
41764 },
41765
41766 getX: function ( index ) {
41767
41768 return this.data.array[ index * this.data.stride + this.offset ];
41769
41770 },
41771
41772 getY: function ( index ) {
41773
41774 return this.data.array[ index * this.data.stride + this.offset + 1 ];
41775
41776 },
41777
41778 getZ: function ( index ) {
41779
41780 return this.data.array[ index * this.data.stride + this.offset + 2 ];
41781
41782 },
41783
41784 getW: function ( index ) {
41785
41786 return this.data.array[ index * this.data.stride + this.offset + 3 ];
41787
41788 },
41789
41790 setXY: function ( index, x, y ) {
41791
41792 index = index * this.data.stride + this.offset;
41793
41794 this.data.array[ index + 0 ] = x;
41795 this.data.array[ index + 1 ] = y;
41796
41797 return this;
41798
41799 },
41800
41801 setXYZ: function ( index, x, y, z ) {
41802
41803 index = index * this.data.stride + this.offset;
41804
41805 this.data.array[ index + 0 ] = x;
41806 this.data.array[ index + 1 ] = y;
41807 this.data.array[ index + 2 ] = z;
41808
41809 return this;
41810
41811 },
41812
41813 setXYZW: function ( index, x, y, z, w ) {
41814
41815 index = index * this.data.stride + this.offset;
41816
41817 this.data.array[ index + 0 ] = x;
41818 this.data.array[ index + 1 ] = y;
41819 this.data.array[ index + 2 ] = z;
41820 this.data.array[ index + 3 ] = w;
41821
41822 return this;
41823
41824 }
41825
41826} );
41827
41828/**
41829 * @author benaadams / https://twitter.com/ben_a_adams
41830 */
41831
41832function InterleavedBuffer( array, stride ) {
41833
41834 this.array = array;
41835 this.stride = stride;
41836 this.count = array !== undefined ? array.length / stride : 0;
41837
41838 this.dynamic = false;
41839 this.updateRange = { offset: 0, count: - 1 };
41840
41841 this.version = 0;
41842
41843}
41844
41845Object.defineProperty( InterleavedBuffer.prototype, 'needsUpdate', {
41846
41847 set: function ( value ) {
41848
41849 if ( value === true ) this.version ++;
41850
41851 }
41852
41853} );
41854
41855Object.assign( InterleavedBuffer.prototype, {
41856
41857 isInterleavedBuffer: true,
41858
41859 onUploadCallback: function () {},
41860
41861 setArray: function ( array ) {
41862
41863 if ( Array.isArray( array ) ) {
41864
41865 throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' );
41866
41867 }
41868
41869 this.count = array !== undefined ? array.length / this.stride : 0;
41870 this.array = array;
41871
41872 return this;
41873
41874 },
41875
41876 setDynamic: function ( value ) {
41877
41878 this.dynamic = value;
41879
41880 return this;
41881
41882 },
41883
41884 copy: function ( source ) {
41885
41886 this.array = new source.array.constructor( source.array );
41887 this.count = source.count;
41888 this.stride = source.stride;
41889 this.dynamic = source.dynamic;
41890
41891 return this;
41892
41893 },
41894
41895 copyAt: function ( index1, attribute, index2 ) {
41896
41897 index1 *= this.stride;
41898 index2 *= attribute.stride;
41899
41900 for ( var i = 0, l = this.stride; i < l; i ++ ) {
41901
41902 this.array[ index1 + i ] = attribute.array[ index2 + i ];
41903
41904 }
41905
41906 return this;
41907
41908 },
41909
41910 set: function ( value, offset ) {
41911
41912 if ( offset === undefined ) offset = 0;
41913
41914 this.array.set( value, offset );
41915
41916 return this;
41917
41918 },
41919
41920 clone: function () {
41921
41922 return new this.constructor().copy( this );
41923
41924 },
41925
41926 onUpload: function ( callback ) {
41927
41928 this.onUploadCallback = callback;
41929
41930 return this;
41931
41932 }
41933
41934} );
41935
41936/**
41937 * @author benaadams / https://twitter.com/ben_a_adams
41938 */
41939
41940function InstancedInterleavedBuffer( array, stride, meshPerAttribute ) {
41941
41942 InterleavedBuffer.call( this, array, stride );
41943
41944 this.meshPerAttribute = meshPerAttribute || 1;
41945
41946}
41947
41948InstancedInterleavedBuffer.prototype = Object.assign( Object.create( InterleavedBuffer.prototype ), {
41949
41950 constructor: InstancedInterleavedBuffer,
41951
41952 isInstancedInterleavedBuffer: true,
41953
41954 copy: function ( source ) {
41955
41956 InterleavedBuffer.prototype.copy.call( this, source );
41957
41958 this.meshPerAttribute = source.meshPerAttribute;
41959
41960 return this;
41961
41962 }
41963
41964} );
41965
41966/**
41967 * @author benaadams / https://twitter.com/ben_a_adams
41968 */
41969
41970function InstancedBufferAttribute( array, itemSize, meshPerAttribute ) {
41971
41972 BufferAttribute.call( this, array, itemSize );
41973
41974 this.meshPerAttribute = meshPerAttribute || 1;
41975
41976}
41977
41978InstancedBufferAttribute.prototype = Object.assign( Object.create( BufferAttribute.prototype ), {
41979
41980 constructor: InstancedBufferAttribute,
41981
41982 isInstancedBufferAttribute: true,
41983
41984 copy: function ( source ) {
41985
41986 BufferAttribute.prototype.copy.call( this, source );
41987
41988 this.meshPerAttribute = source.meshPerAttribute;
41989
41990 return this;
41991
41992 }
41993
41994} );
41995
41996/**
41997 * @author mrdoob / http://mrdoob.com/
41998 * @author bhouston / http://clara.io/
41999 * @author stephomi / http://stephaneginier.com/
42000 */
42001
42002function Raycaster( origin, direction, near, far ) {
42003
42004 this.ray = new Ray( origin, direction );
42005 // direction is assumed to be normalized (for accurate distance calculations)
42006
42007 this.near = near || 0;
42008 this.far = far || Infinity;
42009
42010 this.params = {
42011 Mesh: {},
42012 Line: {},
42013 LOD: {},
42014 Points: { threshold: 1 },
42015 Sprite: {}
42016 };
42017
42018 Object.defineProperties( this.params, {
42019 PointCloud: {
42020 get: function () {
42021
42022 console.warn( 'THREE.Raycaster: params.PointCloud has been renamed to params.Points.' );
42023 return this.Points;
42024
42025 }
42026 }
42027 } );
42028
42029}
42030
42031function ascSort( a, b ) {
42032
42033 return a.distance - b.distance;
42034
42035}
42036
42037function intersectObject( object, raycaster, intersects, recursive ) {
42038
42039 if ( object.visible === false ) return;
42040
42041 object.raycast( raycaster, intersects );
42042
42043 if ( recursive === true ) {
42044
42045 var children = object.children;
42046
42047 for ( var i = 0, l = children.length; i < l; i ++ ) {
42048
42049 intersectObject( children[ i ], raycaster, intersects, true );
42050
42051 }
42052
42053 }
42054
42055}
42056
42057Object.assign( Raycaster.prototype, {
42058
42059 linePrecision: 1,
42060
42061 set: function ( origin, direction ) {
42062
42063 // direction is assumed to be normalized (for accurate distance calculations)
42064
42065 this.ray.set( origin, direction );
42066
42067 },
42068
42069 setFromCamera: function ( coords, camera ) {
42070
42071 if ( ( camera && camera.isPerspectiveCamera ) ) {
42072
42073 this.ray.origin.setFromMatrixPosition( camera.matrixWorld );
42074 this.ray.direction.set( coords.x, coords.y, 0.5 ).unproject( camera ).sub( this.ray.origin ).normalize();
42075
42076 } else if ( ( camera && camera.isOrthographicCamera ) ) {
42077
42078 this.ray.origin.set( coords.x, coords.y, ( camera.near + camera.far ) / ( camera.near - camera.far ) ).unproject( camera ); // set origin in plane of camera
42079 this.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld );
42080
42081 } else {
42082
42083 console.error( 'THREE.Raycaster: Unsupported camera type.' );
42084
42085 }
42086
42087 },
42088
42089 intersectObject: function ( object, recursive, optionalTarget ) {
42090
42091 var intersects = optionalTarget || [];
42092
42093 intersectObject( object, this, intersects, recursive );
42094
42095 intersects.sort( ascSort );
42096
42097 return intersects;
42098
42099 },
42100
42101 intersectObjects: function ( objects, recursive, optionalTarget ) {
42102
42103 var intersects = optionalTarget || [];
42104
42105 if ( Array.isArray( objects ) === false ) {
42106
42107 console.warn( 'THREE.Raycaster.intersectObjects: objects is not an Array.' );
42108 return intersects;
42109
42110 }
42111
42112 for ( var i = 0, l = objects.length; i < l; i ++ ) {
42113
42114 intersectObject( objects[ i ], this, intersects, recursive );
42115
42116 }
42117
42118 intersects.sort( ascSort );
42119
42120 return intersects;
42121
42122 }
42123
42124} );
42125
42126/**
42127 * @author alteredq / http://alteredqualia.com/
42128 */
42129
42130function Clock( autoStart ) {
42131
42132 this.autoStart = ( autoStart !== undefined ) ? autoStart : true;
42133
42134 this.startTime = 0;
42135 this.oldTime = 0;
42136 this.elapsedTime = 0;
42137
42138 this.running = false;
42139
42140}
42141
42142Object.assign( Clock.prototype, {
42143
42144 start: function () {
42145
42146 this.startTime = ( typeof performance === 'undefined' ? Date : performance ).now(); // see #10732
42147
42148 this.oldTime = this.startTime;
42149 this.elapsedTime = 0;
42150 this.running = true;
42151
42152 },
42153
42154 stop: function () {
42155
42156 this.getElapsedTime();
42157 this.running = false;
42158 this.autoStart = false;
42159
42160 },
42161
42162 getElapsedTime: function () {
42163
42164 this.getDelta();
42165 return this.elapsedTime;
42166
42167 },
42168
42169 getDelta: function () {
42170
42171 var diff = 0;
42172
42173 if ( this.autoStart && ! this.running ) {
42174
42175 this.start();
42176 return 0;
42177
42178 }
42179
42180 if ( this.running ) {
42181
42182 var newTime = ( typeof performance === 'undefined' ? Date : performance ).now();
42183
42184 diff = ( newTime - this.oldTime ) / 1000;
42185 this.oldTime = newTime;
42186
42187 this.elapsedTime += diff;
42188
42189 }
42190
42191 return diff;
42192
42193 }
42194
42195} );
42196
42197/**
42198 * @author bhouston / http://clara.io
42199 * @author WestLangley / http://github.com/WestLangley
42200 *
42201 * Ref: https://en.wikipedia.org/wiki/Spherical_coordinate_system
42202 *
42203 * The poles (phi) are at the positive and negative y axis.
42204 * The equator starts at positive z.
42205 */
42206
42207function Spherical( radius, phi, theta ) {
42208
42209 this.radius = ( radius !== undefined ) ? radius : 1.0;
42210 this.phi = ( phi !== undefined ) ? phi : 0; // up / down towards top and bottom pole
42211 this.theta = ( theta !== undefined ) ? theta : 0; // around the equator of the sphere
42212
42213 return this;
42214
42215}
42216
42217Object.assign( Spherical.prototype, {
42218
42219 set: function ( radius, phi, theta ) {
42220
42221 this.radius = radius;
42222 this.phi = phi;
42223 this.theta = theta;
42224
42225 return this;
42226
42227 },
42228
42229 clone: function () {
42230
42231 return new this.constructor().copy( this );
42232
42233 },
42234
42235 copy: function ( other ) {
42236
42237 this.radius = other.radius;
42238 this.phi = other.phi;
42239 this.theta = other.theta;
42240
42241 return this;
42242
42243 },
42244
42245 // restrict phi to be betwee EPS and PI-EPS
42246 makeSafe: function () {
42247
42248 var EPS = 0.000001;
42249 this.phi = Math.max( EPS, Math.min( Math.PI - EPS, this.phi ) );
42250
42251 return this;
42252
42253 },
42254
42255 setFromVector3: function ( vec3 ) {
42256
42257 this.radius = vec3.length();
42258
42259 if ( this.radius === 0 ) {
42260
42261 this.theta = 0;
42262 this.phi = 0;
42263
42264 } else {
42265
42266 this.theta = Math.atan2( vec3.x, vec3.z ); // equator angle around y-up axis
42267 this.phi = Math.acos( _Math.clamp( vec3.y / this.radius, - 1, 1 ) ); // polar angle
42268
42269 }
42270
42271 return this;
42272
42273 }
42274
42275} );
42276
42277/**
42278 * @author Mugen87 / https://github.com/Mugen87
42279 *
42280 * Ref: https://en.wikipedia.org/wiki/Cylindrical_coordinate_system
42281 *
42282 */
42283
42284function Cylindrical( radius, theta, y ) {
42285
42286 this.radius = ( radius !== undefined ) ? radius : 1.0; // distance from the origin to a point in the x-z plane
42287 this.theta = ( theta !== undefined ) ? theta : 0; // counterclockwise angle in the x-z plane measured in radians from the positive z-axis
42288 this.y = ( y !== undefined ) ? y : 0; // height above the x-z plane
42289
42290 return this;
42291
42292}
42293
42294Object.assign( Cylindrical.prototype, {
42295
42296 set: function ( radius, theta, y ) {
42297
42298 this.radius = radius;
42299 this.theta = theta;
42300 this.y = y;
42301
42302 return this;
42303
42304 },
42305
42306 clone: function () {
42307
42308 return new this.constructor().copy( this );
42309
42310 },
42311
42312 copy: function ( other ) {
42313
42314 this.radius = other.radius;
42315 this.theta = other.theta;
42316 this.y = other.y;
42317
42318 return this;
42319
42320 },
42321
42322 setFromVector3: function ( vec3 ) {
42323
42324 this.radius = Math.sqrt( vec3.x * vec3.x + vec3.z * vec3.z );
42325 this.theta = Math.atan2( vec3.x, vec3.z );
42326 this.y = vec3.y;
42327
42328 return this;
42329
42330 }
42331
42332} );
42333
42334/**
42335 * @author bhouston / http://clara.io
42336 */
42337
42338function Box2( min, max ) {
42339
42340 this.min = ( min !== undefined ) ? min : new Vector2( + Infinity, + Infinity );
42341 this.max = ( max !== undefined ) ? max : new Vector2( - Infinity, - Infinity );
42342
42343}
42344
42345Object.assign( Box2.prototype, {
42346
42347 set: function ( min, max ) {
42348
42349 this.min.copy( min );
42350 this.max.copy( max );
42351
42352 return this;
42353
42354 },
42355
42356 setFromPoints: function ( points ) {
42357
42358 this.makeEmpty();
42359
42360 for ( var i = 0, il = points.length; i < il; i ++ ) {
42361
42362 this.expandByPoint( points[ i ] );
42363
42364 }
42365
42366 return this;
42367
42368 },
42369
42370 setFromCenterAndSize: function () {
42371
42372 var v1 = new Vector2();
42373
42374 return function setFromCenterAndSize( center, size ) {
42375
42376 var halfSize = v1.copy( size ).multiplyScalar( 0.5 );
42377 this.min.copy( center ).sub( halfSize );
42378 this.max.copy( center ).add( halfSize );
42379
42380 return this;
42381
42382 };
42383
42384 }(),
42385
42386 clone: function () {
42387
42388 return new this.constructor().copy( this );
42389
42390 },
42391
42392 copy: function ( box ) {
42393
42394 this.min.copy( box.min );
42395 this.max.copy( box.max );
42396
42397 return this;
42398
42399 },
42400
42401 makeEmpty: function () {
42402
42403 this.min.x = this.min.y = + Infinity;
42404 this.max.x = this.max.y = - Infinity;
42405
42406 return this;
42407
42408 },
42409
42410 isEmpty: function () {
42411
42412 // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
42413
42414 return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y );
42415
42416 },
42417
42418 getCenter: function ( target ) {
42419
42420 if ( target === undefined ) {
42421
42422 console.warn( 'THREE.Box2: .getCenter() target is now required' );
42423 target = new Vector2();
42424
42425 }
42426
42427 return this.isEmpty() ? target.set( 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 );
42428
42429 },
42430
42431 getSize: function ( target ) {
42432
42433 if ( target === undefined ) {
42434
42435 console.warn( 'THREE.Box2: .getSize() target is now required' );
42436 target = new Vector2();
42437
42438 }
42439
42440 return this.isEmpty() ? target.set( 0, 0 ) : target.subVectors( this.max, this.min );
42441
42442 },
42443
42444 expandByPoint: function ( point ) {
42445
42446 this.min.min( point );
42447 this.max.max( point );
42448
42449 return this;
42450
42451 },
42452
42453 expandByVector: function ( vector ) {
42454
42455 this.min.sub( vector );
42456 this.max.add( vector );
42457
42458 return this;
42459
42460 },
42461
42462 expandByScalar: function ( scalar ) {
42463
42464 this.min.addScalar( - scalar );
42465 this.max.addScalar( scalar );
42466
42467 return this;
42468
42469 },
42470
42471 containsPoint: function ( point ) {
42472
42473 return point.x < this.min.x || point.x > this.max.x ||
42474 point.y < this.min.y || point.y > this.max.y ? false : true;
42475
42476 },
42477
42478 containsBox: function ( box ) {
42479
42480 return this.min.x <= box.min.x && box.max.x <= this.max.x &&
42481 this.min.y <= box.min.y && box.max.y <= this.max.y;
42482
42483 },
42484
42485 getParameter: function ( point, target ) {
42486
42487 // This can potentially have a divide by zero if the box
42488 // has a size dimension of 0.
42489
42490 if ( target === undefined ) {
42491
42492 console.warn( 'THREE.Box2: .getParameter() target is now required' );
42493 target = new Vector2();
42494
42495 }
42496
42497 return target.set(
42498 ( point.x - this.min.x ) / ( this.max.x - this.min.x ),
42499 ( point.y - this.min.y ) / ( this.max.y - this.min.y )
42500 );
42501
42502 },
42503
42504 intersectsBox: function ( box ) {
42505
42506 // using 4 splitting planes to rule out intersections
42507
42508 return box.max.x < this.min.x || box.min.x > this.max.x ||
42509 box.max.y < this.min.y || box.min.y > this.max.y ? false : true;
42510
42511 },
42512
42513 clampPoint: function ( point, target ) {
42514
42515 if ( target === undefined ) {
42516
42517 console.warn( 'THREE.Box2: .clampPoint() target is now required' );
42518 target = new Vector2();
42519
42520 }
42521
42522 return target.copy( point ).clamp( this.min, this.max );
42523
42524 },
42525
42526 distanceToPoint: function () {
42527
42528 var v1 = new Vector2();
42529
42530 return function distanceToPoint( point ) {
42531
42532 var clampedPoint = v1.copy( point ).clamp( this.min, this.max );
42533 return clampedPoint.sub( point ).length();
42534
42535 };
42536
42537 }(),
42538
42539 intersect: function ( box ) {
42540
42541 this.min.max( box.min );
42542 this.max.min( box.max );
42543
42544 return this;
42545
42546 },
42547
42548 union: function ( box ) {
42549
42550 this.min.min( box.min );
42551 this.max.max( box.max );
42552
42553 return this;
42554
42555 },
42556
42557 translate: function ( offset ) {
42558
42559 this.min.add( offset );
42560 this.max.add( offset );
42561
42562 return this;
42563
42564 },
42565
42566 equals: function ( box ) {
42567
42568 return box.min.equals( this.min ) && box.max.equals( this.max );
42569
42570 }
42571
42572} );
42573
42574/**
42575 * @author alteredq / http://alteredqualia.com/
42576 */
42577
42578function ImmediateRenderObject( material ) {
42579
42580 Object3D.call( this );
42581
42582 this.material = material;
42583 this.render = function ( /* renderCallback */ ) {};
42584
42585}
42586
42587ImmediateRenderObject.prototype = Object.create( Object3D.prototype );
42588ImmediateRenderObject.prototype.constructor = ImmediateRenderObject;
42589
42590ImmediateRenderObject.prototype.isImmediateRenderObject = true;
42591
42592/**
42593 * @author mrdoob / http://mrdoob.com/
42594 * @author WestLangley / http://github.com/WestLangley
42595 */
42596
42597function VertexNormalsHelper( object, size, hex, linewidth ) {
42598
42599 this.object = object;
42600
42601 this.size = ( size !== undefined ) ? size : 1;
42602
42603 var color = ( hex !== undefined ) ? hex : 0xff0000;
42604
42605 var width = ( linewidth !== undefined ) ? linewidth : 1;
42606
42607 //
42608
42609 var nNormals = 0;
42610
42611 var objGeometry = this.object.geometry;
42612
42613 if ( objGeometry && objGeometry.isGeometry ) {
42614
42615 nNormals = objGeometry.faces.length * 3;
42616
42617 } else if ( objGeometry && objGeometry.isBufferGeometry ) {
42618
42619 nNormals = objGeometry.attributes.normal.count;
42620
42621 }
42622
42623 //
42624
42625 var geometry = new BufferGeometry();
42626
42627 var positions = new Float32BufferAttribute( nNormals * 2 * 3, 3 );
42628
42629 geometry.addAttribute( 'position', positions );
42630
42631 LineSegments.call( this, geometry, new LineBasicMaterial( { color: color, linewidth: width } ) );
42632
42633 //
42634
42635 this.matrixAutoUpdate = false;
42636
42637 this.update();
42638
42639}
42640
42641VertexNormalsHelper.prototype = Object.create( LineSegments.prototype );
42642VertexNormalsHelper.prototype.constructor = VertexNormalsHelper;
42643
42644VertexNormalsHelper.prototype.update = ( function () {
42645
42646 var v1 = new Vector3();
42647 var v2 = new Vector3();
42648 var normalMatrix = new Matrix3();
42649
42650 return function update() {
42651
42652 var keys = [ 'a', 'b', 'c' ];
42653
42654 this.object.updateMatrixWorld( true );
42655
42656 normalMatrix.getNormalMatrix( this.object.matrixWorld );
42657
42658 var matrixWorld = this.object.matrixWorld;
42659
42660 var position = this.geometry.attributes.position;
42661
42662 //
42663
42664 var objGeometry = this.object.geometry;
42665
42666 if ( objGeometry && objGeometry.isGeometry ) {
42667
42668 var vertices = objGeometry.vertices;
42669
42670 var faces = objGeometry.faces;
42671
42672 var idx = 0;
42673
42674 for ( var i = 0, l = faces.length; i < l; i ++ ) {
42675
42676 var face = faces[ i ];
42677
42678 for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {
42679
42680 var vertex = vertices[ face[ keys[ j ] ] ];
42681
42682 var normal = face.vertexNormals[ j ];
42683
42684 v1.copy( vertex ).applyMatrix4( matrixWorld );
42685
42686 v2.copy( normal ).applyMatrix3( normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 );
42687
42688 position.setXYZ( idx, v1.x, v1.y, v1.z );
42689
42690 idx = idx + 1;
42691
42692 position.setXYZ( idx, v2.x, v2.y, v2.z );
42693
42694 idx = idx + 1;
42695
42696 }
42697
42698 }
42699
42700 } else if ( objGeometry && objGeometry.isBufferGeometry ) {
42701
42702 var objPos = objGeometry.attributes.position;
42703
42704 var objNorm = objGeometry.attributes.normal;
42705
42706 var idx = 0;
42707
42708 // for simplicity, ignore index and drawcalls, and render every normal
42709
42710 for ( var j = 0, jl = objPos.count; j < jl; j ++ ) {
42711
42712 v1.set( objPos.getX( j ), objPos.getY( j ), objPos.getZ( j ) ).applyMatrix4( matrixWorld );
42713
42714 v2.set( objNorm.getX( j ), objNorm.getY( j ), objNorm.getZ( j ) );
42715
42716 v2.applyMatrix3( normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 );
42717
42718 position.setXYZ( idx, v1.x, v1.y, v1.z );
42719
42720 idx = idx + 1;
42721
42722 position.setXYZ( idx, v2.x, v2.y, v2.z );
42723
42724 idx = idx + 1;
42725
42726 }
42727
42728 }
42729
42730 position.needsUpdate = true;
42731
42732 };
42733
42734}() );
42735
42736/**
42737 * @author alteredq / http://alteredqualia.com/
42738 * @author mrdoob / http://mrdoob.com/
42739 * @author WestLangley / http://github.com/WestLangley
42740 */
42741
42742function SpotLightHelper( light, color ) {
42743
42744 Object3D.call( this );
42745
42746 this.light = light;
42747 this.light.updateMatrixWorld();
42748
42749 this.matrix = light.matrixWorld;
42750 this.matrixAutoUpdate = false;
42751
42752 this.color = color;
42753
42754 var geometry = new BufferGeometry();
42755
42756 var positions = [
42757 0, 0, 0, 0, 0, 1,
42758 0, 0, 0, 1, 0, 1,
42759 0, 0, 0, - 1, 0, 1,
42760 0, 0, 0, 0, 1, 1,
42761 0, 0, 0, 0, - 1, 1
42762 ];
42763
42764 for ( var i = 0, j = 1, l = 32; i < l; i ++, j ++ ) {
42765
42766 var p1 = ( i / l ) * Math.PI * 2;
42767 var p2 = ( j / l ) * Math.PI * 2;
42768
42769 positions.push(
42770 Math.cos( p1 ), Math.sin( p1 ), 1,
42771 Math.cos( p2 ), Math.sin( p2 ), 1
42772 );
42773
42774 }
42775
42776 geometry.addAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
42777
42778 var material = new LineBasicMaterial( { fog: false } );
42779
42780 this.cone = new LineSegments( geometry, material );
42781 this.add( this.cone );
42782
42783 this.update();
42784
42785}
42786
42787SpotLightHelper.prototype = Object.create( Object3D.prototype );
42788SpotLightHelper.prototype.constructor = SpotLightHelper;
42789
42790SpotLightHelper.prototype.dispose = function () {
42791
42792 this.cone.geometry.dispose();
42793 this.cone.material.dispose();
42794
42795};
42796
42797SpotLightHelper.prototype.update = function () {
42798
42799 var vector = new Vector3();
42800 var vector2 = new Vector3();
42801
42802 return function update() {
42803
42804 this.light.updateMatrixWorld();
42805
42806 var coneLength = this.light.distance ? this.light.distance : 1000;
42807 var coneWidth = coneLength * Math.tan( this.light.angle );
42808
42809 this.cone.scale.set( coneWidth, coneWidth, coneLength );
42810
42811 vector.setFromMatrixPosition( this.light.matrixWorld );
42812 vector2.setFromMatrixPosition( this.light.target.matrixWorld );
42813
42814 this.cone.lookAt( vector2.sub( vector ) );
42815
42816 if ( this.color !== undefined ) {
42817
42818 this.cone.material.color.set( this.color );
42819
42820 } else {
42821
42822 this.cone.material.color.copy( this.light.color );
42823
42824 }
42825
42826 };
42827
42828}();
42829
42830/**
42831 * @author Sean Griffin / http://twitter.com/sgrif
42832 * @author Michael Guerrero / http://realitymeltdown.com
42833 * @author mrdoob / http://mrdoob.com/
42834 * @author ikerr / http://verold.com
42835 * @author Mugen87 / https://github.com/Mugen87
42836 */
42837
42838function getBoneList( object ) {
42839
42840 var boneList = [];
42841
42842 if ( object && object.isBone ) {
42843
42844 boneList.push( object );
42845
42846 }
42847
42848 for ( var i = 0; i < object.children.length; i ++ ) {
42849
42850 boneList.push.apply( boneList, getBoneList( object.children[ i ] ) );
42851
42852 }
42853
42854 return boneList;
42855
42856}
42857
42858function SkeletonHelper( object ) {
42859
42860 var bones = getBoneList( object );
42861
42862 var geometry = new BufferGeometry();
42863
42864 var vertices = [];
42865 var colors = [];
42866
42867 var color1 = new Color( 0, 0, 1 );
42868 var color2 = new Color( 0, 1, 0 );
42869
42870 for ( var i = 0; i < bones.length; i ++ ) {
42871
42872 var bone = bones[ i ];
42873
42874 if ( bone.parent && bone.parent.isBone ) {
42875
42876 vertices.push( 0, 0, 0 );
42877 vertices.push( 0, 0, 0 );
42878 colors.push( color1.r, color1.g, color1.b );
42879 colors.push( color2.r, color2.g, color2.b );
42880
42881 }
42882
42883 }
42884
42885 geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
42886 geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
42887
42888 var material = new LineBasicMaterial( { vertexColors: VertexColors, depthTest: false, depthWrite: false, transparent: true } );
42889
42890 LineSegments.call( this, geometry, material );
42891
42892 this.root = object;
42893 this.bones = bones;
42894
42895 this.matrix = object.matrixWorld;
42896 this.matrixAutoUpdate = false;
42897
42898}
42899
42900SkeletonHelper.prototype = Object.create( LineSegments.prototype );
42901SkeletonHelper.prototype.constructor = SkeletonHelper;
42902
42903SkeletonHelper.prototype.updateMatrixWorld = function () {
42904
42905 var vector = new Vector3();
42906
42907 var boneMatrix = new Matrix4();
42908 var matrixWorldInv = new Matrix4();
42909
42910 return function updateMatrixWorld( force ) {
42911
42912 var bones = this.bones;
42913
42914 var geometry = this.geometry;
42915 var position = geometry.getAttribute( 'position' );
42916
42917 matrixWorldInv.getInverse( this.root.matrixWorld );
42918
42919 for ( var i = 0, j = 0; i < bones.length; i ++ ) {
42920
42921 var bone = bones[ i ];
42922
42923 if ( bone.parent && bone.parent.isBone ) {
42924
42925 boneMatrix.multiplyMatrices( matrixWorldInv, bone.matrixWorld );
42926 vector.setFromMatrixPosition( boneMatrix );
42927 position.setXYZ( j, vector.x, vector.y, vector.z );
42928
42929 boneMatrix.multiplyMatrices( matrixWorldInv, bone.parent.matrixWorld );
42930 vector.setFromMatrixPosition( boneMatrix );
42931 position.setXYZ( j + 1, vector.x, vector.y, vector.z );
42932
42933 j += 2;
42934
42935 }
42936
42937 }
42938
42939 geometry.getAttribute( 'position' ).needsUpdate = true;
42940
42941 Object3D.prototype.updateMatrixWorld.call( this, force );
42942
42943 };
42944
42945}();
42946
42947/**
42948 * @author alteredq / http://alteredqualia.com/
42949 * @author mrdoob / http://mrdoob.com/
42950 */
42951
42952function PointLightHelper( light, sphereSize, color ) {
42953
42954 this.light = light;
42955 this.light.updateMatrixWorld();
42956
42957 this.color = color;
42958
42959 var geometry = new SphereBufferGeometry( sphereSize, 4, 2 );
42960 var material = new MeshBasicMaterial( { wireframe: true, fog: false } );
42961
42962 Mesh.call( this, geometry, material );
42963
42964 this.matrix = this.light.matrixWorld;
42965 this.matrixAutoUpdate = false;
42966
42967 this.update();
42968
42969
42970 /*
42971 var distanceGeometry = new THREE.IcosahedronGeometry( 1, 2 );
42972 var distanceMaterial = new THREE.MeshBasicMaterial( { color: hexColor, fog: false, wireframe: true, opacity: 0.1, transparent: true } );
42973
42974 this.lightSphere = new THREE.Mesh( bulbGeometry, bulbMaterial );
42975 this.lightDistance = new THREE.Mesh( distanceGeometry, distanceMaterial );
42976
42977 var d = light.distance;
42978
42979 if ( d === 0.0 ) {
42980
42981 this.lightDistance.visible = false;
42982
42983 } else {
42984
42985 this.lightDistance.scale.set( d, d, d );
42986
42987 }
42988
42989 this.add( this.lightDistance );
42990 */
42991
42992}
42993
42994PointLightHelper.prototype = Object.create( Mesh.prototype );
42995PointLightHelper.prototype.constructor = PointLightHelper;
42996
42997PointLightHelper.prototype.dispose = function () {
42998
42999 this.geometry.dispose();
43000 this.material.dispose();
43001
43002};
43003
43004PointLightHelper.prototype.update = function () {
43005
43006 if ( this.color !== undefined ) {
43007
43008 this.material.color.set( this.color );
43009
43010 } else {
43011
43012 this.material.color.copy( this.light.color );
43013
43014 }
43015
43016 /*
43017 var d = this.light.distance;
43018
43019 if ( d === 0.0 ) {
43020
43021 this.lightDistance.visible = false;
43022
43023 } else {
43024
43025 this.lightDistance.visible = true;
43026 this.lightDistance.scale.set( d, d, d );
43027
43028 }
43029 */
43030
43031};
43032
43033/**
43034 * @author abelnation / http://github.com/abelnation
43035 * @author Mugen87 / http://github.com/Mugen87
43036 * @author WestLangley / http://github.com/WestLangley
43037 */
43038
43039function RectAreaLightHelper( light, color ) {
43040
43041 Object3D.call( this );
43042
43043 this.light = light;
43044 this.light.updateMatrixWorld();
43045
43046 this.matrix = light.matrixWorld;
43047 this.matrixAutoUpdate = false;
43048
43049 this.color = color;
43050
43051 var material = new LineBasicMaterial( { fog: false } );
43052
43053 var geometry = new BufferGeometry();
43054
43055 geometry.addAttribute( 'position', new BufferAttribute( new Float32Array( 5 * 3 ), 3 ) );
43056
43057 this.line = new Line( geometry, material );
43058 this.add( this.line );
43059
43060
43061 this.update();
43062
43063}
43064
43065RectAreaLightHelper.prototype = Object.create( Object3D.prototype );
43066RectAreaLightHelper.prototype.constructor = RectAreaLightHelper;
43067
43068RectAreaLightHelper.prototype.dispose = function () {
43069
43070 this.children[ 0 ].geometry.dispose();
43071 this.children[ 0 ].material.dispose();
43072
43073};
43074
43075RectAreaLightHelper.prototype.update = function () {
43076
43077 // calculate new dimensions of the helper
43078
43079 var hx = this.light.width * 0.5;
43080 var hy = this.light.height * 0.5;
43081
43082 var position = this.line.geometry.attributes.position;
43083 var array = position.array;
43084
43085 // update vertices
43086
43087 array[ 0 ] = hx; array[ 1 ] = - hy; array[ 2 ] = 0;
43088 array[ 3 ] = hx; array[ 4 ] = hy; array[ 5 ] = 0;
43089 array[ 6 ] = - hx; array[ 7 ] = hy; array[ 8 ] = 0;
43090 array[ 9 ] = - hx; array[ 10 ] = - hy; array[ 11 ] = 0;
43091 array[ 12 ] = hx; array[ 13 ] = - hy; array[ 14 ] = 0;
43092
43093 position.needsUpdate = true;
43094
43095 if ( this.color !== undefined ) {
43096
43097 this.line.material.color.set( this.color );
43098
43099 } else {
43100
43101 this.line.material.color.copy( this.light.color );
43102
43103 }
43104
43105};
43106
43107/**
43108 * @author alteredq / http://alteredqualia.com/
43109 * @author mrdoob / http://mrdoob.com/
43110 * @author Mugen87 / https://github.com/Mugen87
43111 */
43112
43113function HemisphereLightHelper( light, size, color ) {
43114
43115 Object3D.call( this );
43116
43117 this.light = light;
43118 this.light.updateMatrixWorld();
43119
43120 this.matrix = light.matrixWorld;
43121 this.matrixAutoUpdate = false;
43122
43123 this.color = color;
43124
43125 var geometry = new OctahedronBufferGeometry( size );
43126 geometry.rotateY( Math.PI * 0.5 );
43127
43128 this.material = new MeshBasicMaterial( { wireframe: true, fog: false } );
43129 if ( this.color === undefined ) this.material.vertexColors = VertexColors;
43130
43131 var position = geometry.getAttribute( 'position' );
43132 var colors = new Float32Array( position.count * 3 );
43133
43134 geometry.addAttribute( 'color', new BufferAttribute( colors, 3 ) );
43135
43136 this.add( new Mesh( geometry, this.material ) );
43137
43138 this.update();
43139
43140}
43141
43142HemisphereLightHelper.prototype = Object.create( Object3D.prototype );
43143HemisphereLightHelper.prototype.constructor = HemisphereLightHelper;
43144
43145HemisphereLightHelper.prototype.dispose = function () {
43146
43147 this.children[ 0 ].geometry.dispose();
43148 this.children[ 0 ].material.dispose();
43149
43150};
43151
43152HemisphereLightHelper.prototype.update = function () {
43153
43154 var vector = new Vector3();
43155
43156 var color1 = new Color();
43157 var color2 = new Color();
43158
43159 return function update() {
43160
43161 var mesh = this.children[ 0 ];
43162
43163 if ( this.color !== undefined ) {
43164
43165 this.material.color.set( this.color );
43166
43167 } else {
43168
43169 var colors = mesh.geometry.getAttribute( 'color' );
43170
43171 color1.copy( this.light.color );
43172 color2.copy( this.light.groundColor );
43173
43174 for ( var i = 0, l = colors.count; i < l; i ++ ) {
43175
43176 var color = ( i < ( l / 2 ) ) ? color1 : color2;
43177
43178 colors.setXYZ( i, color.r, color.g, color.b );
43179
43180 }
43181
43182 colors.needsUpdate = true;
43183
43184 }
43185
43186 mesh.lookAt( vector.setFromMatrixPosition( this.light.matrixWorld ).negate() );
43187
43188 };
43189
43190}();
43191
43192/**
43193 * @author mrdoob / http://mrdoob.com/
43194 */
43195
43196function GridHelper( size, divisions, color1, color2 ) {
43197
43198 size = size || 10;
43199 divisions = divisions || 10;
43200 color1 = new Color( color1 !== undefined ? color1 : 0x444444 );
43201 color2 = new Color( color2 !== undefined ? color2 : 0x888888 );
43202
43203 var center = divisions / 2;
43204 var step = size / divisions;
43205 var halfSize = size / 2;
43206
43207 var vertices = [], colors = [];
43208
43209 for ( var i = 0, j = 0, k = - halfSize; i <= divisions; i ++, k += step ) {
43210
43211 vertices.push( - halfSize, 0, k, halfSize, 0, k );
43212 vertices.push( k, 0, - halfSize, k, 0, halfSize );
43213
43214 var color = i === center ? color1 : color2;
43215
43216 color.toArray( colors, j ); j += 3;
43217 color.toArray( colors, j ); j += 3;
43218 color.toArray( colors, j ); j += 3;
43219 color.toArray( colors, j ); j += 3;
43220
43221 }
43222
43223 var geometry = new BufferGeometry();
43224 geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
43225 geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
43226
43227 var material = new LineBasicMaterial( { vertexColors: VertexColors } );
43228
43229 LineSegments.call( this, geometry, material );
43230
43231}
43232
43233GridHelper.prototype = Object.create( LineSegments.prototype );
43234GridHelper.prototype.constructor = GridHelper;
43235
43236/**
43237 * @author mrdoob / http://mrdoob.com/
43238 * @author Mugen87 / http://github.com/Mugen87
43239 * @author Hectate / http://www.github.com/Hectate
43240 */
43241
43242function PolarGridHelper( radius, radials, circles, divisions, color1, color2 ) {
43243
43244 radius = radius || 10;
43245 radials = radials || 16;
43246 circles = circles || 8;
43247 divisions = divisions || 64;
43248 color1 = new Color( color1 !== undefined ? color1 : 0x444444 );
43249 color2 = new Color( color2 !== undefined ? color2 : 0x888888 );
43250
43251 var vertices = [];
43252 var colors = [];
43253
43254 var x, z;
43255 var v, i, j, r, color;
43256
43257 // create the radials
43258
43259 for ( i = 0; i <= radials; i ++ ) {
43260
43261 v = ( i / radials ) * ( Math.PI * 2 );
43262
43263 x = Math.sin( v ) * radius;
43264 z = Math.cos( v ) * radius;
43265
43266 vertices.push( 0, 0, 0 );
43267 vertices.push( x, 0, z );
43268
43269 color = ( i & 1 ) ? color1 : color2;
43270
43271 colors.push( color.r, color.g, color.b );
43272 colors.push( color.r, color.g, color.b );
43273
43274 }
43275
43276 // create the circles
43277
43278 for ( i = 0; i <= circles; i ++ ) {
43279
43280 color = ( i & 1 ) ? color1 : color2;
43281
43282 r = radius - ( radius / circles * i );
43283
43284 for ( j = 0; j < divisions; j ++ ) {
43285
43286 // first vertex
43287
43288 v = ( j / divisions ) * ( Math.PI * 2 );
43289
43290 x = Math.sin( v ) * r;
43291 z = Math.cos( v ) * r;
43292
43293 vertices.push( x, 0, z );
43294 colors.push( color.r, color.g, color.b );
43295
43296 // second vertex
43297
43298 v = ( ( j + 1 ) / divisions ) * ( Math.PI * 2 );
43299
43300 x = Math.sin( v ) * r;
43301 z = Math.cos( v ) * r;
43302
43303 vertices.push( x, 0, z );
43304 colors.push( color.r, color.g, color.b );
43305
43306 }
43307
43308 }
43309
43310 var geometry = new BufferGeometry();
43311 geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
43312 geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
43313
43314 var material = new LineBasicMaterial( { vertexColors: VertexColors } );
43315
43316 LineSegments.call( this, geometry, material );
43317
43318}
43319
43320PolarGridHelper.prototype = Object.create( LineSegments.prototype );
43321PolarGridHelper.prototype.constructor = PolarGridHelper;
43322
43323/**
43324 * @author mrdoob / http://mrdoob.com/
43325 * @author WestLangley / http://github.com/WestLangley
43326 */
43327
43328function FaceNormalsHelper( object, size, hex, linewidth ) {
43329
43330 // FaceNormalsHelper only supports THREE.Geometry
43331
43332 this.object = object;
43333
43334 this.size = ( size !== undefined ) ? size : 1;
43335
43336 var color = ( hex !== undefined ) ? hex : 0xffff00;
43337
43338 var width = ( linewidth !== undefined ) ? linewidth : 1;
43339
43340 //
43341
43342 var nNormals = 0;
43343
43344 var objGeometry = this.object.geometry;
43345
43346 if ( objGeometry && objGeometry.isGeometry ) {
43347
43348 nNormals = objGeometry.faces.length;
43349
43350 } else {
43351
43352 console.warn( 'THREE.FaceNormalsHelper: only THREE.Geometry is supported. Use THREE.VertexNormalsHelper, instead.' );
43353
43354 }
43355
43356 //
43357
43358 var geometry = new BufferGeometry();
43359
43360 var positions = new Float32BufferAttribute( nNormals * 2 * 3, 3 );
43361
43362 geometry.addAttribute( 'position', positions );
43363
43364 LineSegments.call( this, geometry, new LineBasicMaterial( { color: color, linewidth: width } ) );
43365
43366 //
43367
43368 this.matrixAutoUpdate = false;
43369 this.update();
43370
43371}
43372
43373FaceNormalsHelper.prototype = Object.create( LineSegments.prototype );
43374FaceNormalsHelper.prototype.constructor = FaceNormalsHelper;
43375
43376FaceNormalsHelper.prototype.update = ( function () {
43377
43378 var v1 = new Vector3();
43379 var v2 = new Vector3();
43380 var normalMatrix = new Matrix3();
43381
43382 return function update() {
43383
43384 this.object.updateMatrixWorld( true );
43385
43386 normalMatrix.getNormalMatrix( this.object.matrixWorld );
43387
43388 var matrixWorld = this.object.matrixWorld;
43389
43390 var position = this.geometry.attributes.position;
43391
43392 //
43393
43394 var objGeometry = this.object.geometry;
43395
43396 var vertices = objGeometry.vertices;
43397
43398 var faces = objGeometry.faces;
43399
43400 var idx = 0;
43401
43402 for ( var i = 0, l = faces.length; i < l; i ++ ) {
43403
43404 var face = faces[ i ];
43405
43406 var normal = face.normal;
43407
43408 v1.copy( vertices[ face.a ] )
43409 .add( vertices[ face.b ] )
43410 .add( vertices[ face.c ] )
43411 .divideScalar( 3 )
43412 .applyMatrix4( matrixWorld );
43413
43414 v2.copy( normal ).applyMatrix3( normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 );
43415
43416 position.setXYZ( idx, v1.x, v1.y, v1.z );
43417
43418 idx = idx + 1;
43419
43420 position.setXYZ( idx, v2.x, v2.y, v2.z );
43421
43422 idx = idx + 1;
43423
43424 }
43425
43426 position.needsUpdate = true;
43427
43428 };
43429
43430}() );
43431
43432/**
43433 * @author alteredq / http://alteredqualia.com/
43434 * @author mrdoob / http://mrdoob.com/
43435 * @author WestLangley / http://github.com/WestLangley
43436 */
43437
43438function DirectionalLightHelper( light, size, color ) {
43439
43440 Object3D.call( this );
43441
43442 this.light = light;
43443 this.light.updateMatrixWorld();
43444
43445 this.matrix = light.matrixWorld;
43446 this.matrixAutoUpdate = false;
43447
43448 this.color = color;
43449
43450 if ( size === undefined ) size = 1;
43451
43452 var geometry = new BufferGeometry();
43453 geometry.addAttribute( 'position', new Float32BufferAttribute( [
43454 - size, size, 0,
43455 size, size, 0,
43456 size, - size, 0,
43457 - size, - size, 0,
43458 - size, size, 0
43459 ], 3 ) );
43460
43461 var material = new LineBasicMaterial( { fog: false } );
43462
43463 this.lightPlane = new Line( geometry, material );
43464 this.add( this.lightPlane );
43465
43466 geometry = new BufferGeometry();
43467 geometry.addAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 0, 1 ], 3 ) );
43468
43469 this.targetLine = new Line( geometry, material );
43470 this.add( this.targetLine );
43471
43472 this.update();
43473
43474}
43475
43476DirectionalLightHelper.prototype = Object.create( Object3D.prototype );
43477DirectionalLightHelper.prototype.constructor = DirectionalLightHelper;
43478
43479DirectionalLightHelper.prototype.dispose = function () {
43480
43481 this.lightPlane.geometry.dispose();
43482 this.lightPlane.material.dispose();
43483 this.targetLine.geometry.dispose();
43484 this.targetLine.material.dispose();
43485
43486};
43487
43488DirectionalLightHelper.prototype.update = function () {
43489
43490 var v1 = new Vector3();
43491 var v2 = new Vector3();
43492 var v3 = new Vector3();
43493
43494 return function update() {
43495
43496 v1.setFromMatrixPosition( this.light.matrixWorld );
43497 v2.setFromMatrixPosition( this.light.target.matrixWorld );
43498 v3.subVectors( v2, v1 );
43499
43500 this.lightPlane.lookAt( v3 );
43501
43502 if ( this.color !== undefined ) {
43503
43504 this.lightPlane.material.color.set( this.color );
43505 this.targetLine.material.color.set( this.color );
43506
43507 } else {
43508
43509 this.lightPlane.material.color.copy( this.light.color );
43510 this.targetLine.material.color.copy( this.light.color );
43511
43512 }
43513
43514 this.targetLine.lookAt( v3 );
43515 this.targetLine.scale.z = v3.length();
43516
43517 };
43518
43519}();
43520
43521/**
43522 * @author alteredq / http://alteredqualia.com/
43523 * @author Mugen87 / https://github.com/Mugen87
43524 *
43525 * - shows frustum, line of sight and up of the camera
43526 * - suitable for fast updates
43527 * - based on frustum visualization in lightgl.js shadowmap example
43528 * http://evanw.github.com/lightgl.js/tests/shadowmap.html
43529 */
43530
43531function CameraHelper( camera ) {
43532
43533 var geometry = new BufferGeometry();
43534 var material = new LineBasicMaterial( { color: 0xffffff, vertexColors: FaceColors } );
43535
43536 var vertices = [];
43537 var colors = [];
43538
43539 var pointMap = {};
43540
43541 // colors
43542
43543 var colorFrustum = new Color( 0xffaa00 );
43544 var colorCone = new Color( 0xff0000 );
43545 var colorUp = new Color( 0x00aaff );
43546 var colorTarget = new Color( 0xffffff );
43547 var colorCross = new Color( 0x333333 );
43548
43549 // near
43550
43551 addLine( 'n1', 'n2', colorFrustum );
43552 addLine( 'n2', 'n4', colorFrustum );
43553 addLine( 'n4', 'n3', colorFrustum );
43554 addLine( 'n3', 'n1', colorFrustum );
43555
43556 // far
43557
43558 addLine( 'f1', 'f2', colorFrustum );
43559 addLine( 'f2', 'f4', colorFrustum );
43560 addLine( 'f4', 'f3', colorFrustum );
43561 addLine( 'f3', 'f1', colorFrustum );
43562
43563 // sides
43564
43565 addLine( 'n1', 'f1', colorFrustum );
43566 addLine( 'n2', 'f2', colorFrustum );
43567 addLine( 'n3', 'f3', colorFrustum );
43568 addLine( 'n4', 'f4', colorFrustum );
43569
43570 // cone
43571
43572 addLine( 'p', 'n1', colorCone );
43573 addLine( 'p', 'n2', colorCone );
43574 addLine( 'p', 'n3', colorCone );
43575 addLine( 'p', 'n4', colorCone );
43576
43577 // up
43578
43579 addLine( 'u1', 'u2', colorUp );
43580 addLine( 'u2', 'u3', colorUp );
43581 addLine( 'u3', 'u1', colorUp );
43582
43583 // target
43584
43585 addLine( 'c', 't', colorTarget );
43586 addLine( 'p', 'c', colorCross );
43587
43588 // cross
43589
43590 addLine( 'cn1', 'cn2', colorCross );
43591 addLine( 'cn3', 'cn4', colorCross );
43592
43593 addLine( 'cf1', 'cf2', colorCross );
43594 addLine( 'cf3', 'cf4', colorCross );
43595
43596 function addLine( a, b, color ) {
43597
43598 addPoint( a, color );
43599 addPoint( b, color );
43600
43601 }
43602
43603 function addPoint( id, color ) {
43604
43605 vertices.push( 0, 0, 0 );
43606 colors.push( color.r, color.g, color.b );
43607
43608 if ( pointMap[ id ] === undefined ) {
43609
43610 pointMap[ id ] = [];
43611
43612 }
43613
43614 pointMap[ id ].push( ( vertices.length / 3 ) - 1 );
43615
43616 }
43617
43618 geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
43619 geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
43620
43621 LineSegments.call( this, geometry, material );
43622
43623 this.camera = camera;
43624 if ( this.camera.updateProjectionMatrix ) this.camera.updateProjectionMatrix();
43625
43626 this.matrix = camera.matrixWorld;
43627 this.matrixAutoUpdate = false;
43628
43629 this.pointMap = pointMap;
43630
43631 this.update();
43632
43633}
43634
43635CameraHelper.prototype = Object.create( LineSegments.prototype );
43636CameraHelper.prototype.constructor = CameraHelper;
43637
43638CameraHelper.prototype.update = function () {
43639
43640 var geometry, pointMap;
43641
43642 var vector = new Vector3();
43643 var camera = new Camera();
43644
43645 function setPoint( point, x, y, z ) {
43646
43647 vector.set( x, y, z ).unproject( camera );
43648
43649 var points = pointMap[ point ];
43650
43651 if ( points !== undefined ) {
43652
43653 var position = geometry.getAttribute( 'position' );
43654
43655 for ( var i = 0, l = points.length; i < l; i ++ ) {
43656
43657 position.setXYZ( points[ i ], vector.x, vector.y, vector.z );
43658
43659 }
43660
43661 }
43662
43663 }
43664
43665 return function update() {
43666
43667 geometry = this.geometry;
43668 pointMap = this.pointMap;
43669
43670 var w = 1, h = 1;
43671
43672 // we need just camera projection matrix
43673 // world matrix must be identity
43674
43675 camera.projectionMatrix.copy( this.camera.projectionMatrix );
43676
43677 // center / target
43678
43679 setPoint( 'c', 0, 0, - 1 );
43680 setPoint( 't', 0, 0, 1 );
43681
43682 // near
43683
43684 setPoint( 'n1', - w, - h, - 1 );
43685 setPoint( 'n2', w, - h, - 1 );
43686 setPoint( 'n3', - w, h, - 1 );
43687 setPoint( 'n4', w, h, - 1 );
43688
43689 // far
43690
43691 setPoint( 'f1', - w, - h, 1 );
43692 setPoint( 'f2', w, - h, 1 );
43693 setPoint( 'f3', - w, h, 1 );
43694 setPoint( 'f4', w, h, 1 );
43695
43696 // up
43697
43698 setPoint( 'u1', w * 0.7, h * 1.1, - 1 );
43699 setPoint( 'u2', - w * 0.7, h * 1.1, - 1 );
43700 setPoint( 'u3', 0, h * 2, - 1 );
43701
43702 // cross
43703
43704 setPoint( 'cf1', - w, 0, 1 );
43705 setPoint( 'cf2', w, 0, 1 );
43706 setPoint( 'cf3', 0, - h, 1 );
43707 setPoint( 'cf4', 0, h, 1 );
43708
43709 setPoint( 'cn1', - w, 0, - 1 );
43710 setPoint( 'cn2', w, 0, - 1 );
43711 setPoint( 'cn3', 0, - h, - 1 );
43712 setPoint( 'cn4', 0, h, - 1 );
43713
43714 geometry.getAttribute( 'position' ).needsUpdate = true;
43715
43716 };
43717
43718}();
43719
43720/**
43721 * @author mrdoob / http://mrdoob.com/
43722 * @author Mugen87 / http://github.com/Mugen87
43723 */
43724
43725function BoxHelper( object, color ) {
43726
43727 this.object = object;
43728
43729 if ( color === undefined ) color = 0xffff00;
43730
43731 var 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 ] );
43732 var positions = new Float32Array( 8 * 3 );
43733
43734 var geometry = new BufferGeometry();
43735 geometry.setIndex( new BufferAttribute( indices, 1 ) );
43736 geometry.addAttribute( 'position', new BufferAttribute( positions, 3 ) );
43737
43738 LineSegments.call( this, geometry, new LineBasicMaterial( { color: color } ) );
43739
43740 this.matrixAutoUpdate = false;
43741
43742 this.update();
43743
43744}
43745
43746BoxHelper.prototype = Object.create( LineSegments.prototype );
43747BoxHelper.prototype.constructor = BoxHelper;
43748
43749BoxHelper.prototype.update = ( function () {
43750
43751 var box = new Box3();
43752
43753 return function update( object ) {
43754
43755 if ( object !== undefined ) {
43756
43757 console.warn( 'THREE.BoxHelper: .update() has no longer arguments.' );
43758
43759 }
43760
43761 if ( this.object !== undefined ) {
43762
43763 box.setFromObject( this.object );
43764
43765 }
43766
43767 if ( box.isEmpty() ) return;
43768
43769 var min = box.min;
43770 var max = box.max;
43771
43772 /*
43773 5____4
43774 1/___0/|
43775 | 6__|_7
43776 2/___3/
43777
43778 0: max.x, max.y, max.z
43779 1: min.x, max.y, max.z
43780 2: min.x, min.y, max.z
43781 3: max.x, min.y, max.z
43782 4: max.x, max.y, min.z
43783 5: min.x, max.y, min.z
43784 6: min.x, min.y, min.z
43785 7: max.x, min.y, min.z
43786 */
43787
43788 var position = this.geometry.attributes.position;
43789 var array = position.array;
43790
43791 array[ 0 ] = max.x; array[ 1 ] = max.y; array[ 2 ] = max.z;
43792 array[ 3 ] = min.x; array[ 4 ] = max.y; array[ 5 ] = max.z;
43793 array[ 6 ] = min.x; array[ 7 ] = min.y; array[ 8 ] = max.z;
43794 array[ 9 ] = max.x; array[ 10 ] = min.y; array[ 11 ] = max.z;
43795 array[ 12 ] = max.x; array[ 13 ] = max.y; array[ 14 ] = min.z;
43796 array[ 15 ] = min.x; array[ 16 ] = max.y; array[ 17 ] = min.z;
43797 array[ 18 ] = min.x; array[ 19 ] = min.y; array[ 20 ] = min.z;
43798 array[ 21 ] = max.x; array[ 22 ] = min.y; array[ 23 ] = min.z;
43799
43800 position.needsUpdate = true;
43801
43802 this.geometry.computeBoundingSphere();
43803
43804 };
43805
43806} )();
43807
43808BoxHelper.prototype.setFromObject = function ( object ) {
43809
43810 this.object = object;
43811 this.update();
43812
43813 return this;
43814
43815};
43816
43817/**
43818 * @author WestLangley / http://github.com/WestLangley
43819 */
43820
43821function Box3Helper( box, hex ) {
43822
43823 this.type = 'Box3Helper';
43824
43825 this.box = box;
43826
43827 var color = ( hex !== undefined ) ? hex : 0xffff00;
43828
43829 var 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 ] );
43830
43831 var 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 ];
43832
43833 var geometry = new BufferGeometry();
43834
43835 geometry.setIndex( new BufferAttribute( indices, 1 ) );
43836
43837 geometry.addAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
43838
43839 LineSegments.call( this, geometry, new LineBasicMaterial( { color: color } ) );
43840
43841 this.geometry.computeBoundingSphere();
43842
43843}
43844
43845Box3Helper.prototype = Object.create( LineSegments.prototype );
43846Box3Helper.prototype.constructor = Box3Helper;
43847
43848Box3Helper.prototype.updateMatrixWorld = function ( force ) {
43849
43850 var box = this.box;
43851
43852 if ( box.isEmpty() ) return;
43853
43854 box.getCenter( this.position );
43855
43856 box.getSize( this.scale );
43857
43858 this.scale.multiplyScalar( 0.5 );
43859
43860 Object3D.prototype.updateMatrixWorld.call( this, force );
43861
43862};
43863
43864/**
43865 * @author WestLangley / http://github.com/WestLangley
43866 */
43867
43868function PlaneHelper( plane, size, hex ) {
43869
43870 this.type = 'PlaneHelper';
43871
43872 this.plane = plane;
43873
43874 this.size = ( size === undefined ) ? 1 : size;
43875
43876 var color = ( hex !== undefined ) ? hex : 0xffff00;
43877
43878 var 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, 0, 0, 1, 0, 0, 0 ];
43879
43880 var geometry = new BufferGeometry();
43881 geometry.addAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
43882 geometry.computeBoundingSphere();
43883
43884 Line.call( this, geometry, new LineBasicMaterial( { color: color } ) );
43885
43886 //
43887
43888 var positions2 = [ 1, 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, 1, 1, - 1, - 1, 1, 1, - 1, 1 ];
43889
43890 var geometry2 = new BufferGeometry();
43891 geometry2.addAttribute( 'position', new Float32BufferAttribute( positions2, 3 ) );
43892 geometry2.computeBoundingSphere();
43893
43894 this.add( new Mesh( geometry2, new MeshBasicMaterial( { color: color, opacity: 0.2, transparent: true, depthWrite: false } ) ) );
43895
43896}
43897
43898PlaneHelper.prototype = Object.create( Line.prototype );
43899PlaneHelper.prototype.constructor = PlaneHelper;
43900
43901PlaneHelper.prototype.updateMatrixWorld = function ( force ) {
43902
43903 var scale = - this.plane.constant;
43904
43905 if ( Math.abs( scale ) < 1e-8 ) scale = 1e-8; // sign does not matter
43906
43907 this.scale.set( 0.5 * this.size, 0.5 * this.size, scale );
43908
43909 this.lookAt( this.plane.normal );
43910
43911 Object3D.prototype.updateMatrixWorld.call( this, force );
43912
43913};
43914
43915/**
43916 * @author WestLangley / http://github.com/WestLangley
43917 * @author zz85 / http://github.com/zz85
43918 * @author bhouston / http://clara.io
43919 *
43920 * Creates an arrow for visualizing directions
43921 *
43922 * Parameters:
43923 * dir - Vector3
43924 * origin - Vector3
43925 * length - Number
43926 * color - color in hex value
43927 * headLength - Number
43928 * headWidth - Number
43929 */
43930
43931var lineGeometry;
43932var coneGeometry;
43933
43934function ArrowHelper( dir, origin, length, color, headLength, headWidth ) {
43935
43936 // dir is assumed to be normalized
43937
43938 Object3D.call( this );
43939
43940 if ( color === undefined ) color = 0xffff00;
43941 if ( length === undefined ) length = 1;
43942 if ( headLength === undefined ) headLength = 0.2 * length;
43943 if ( headWidth === undefined ) headWidth = 0.2 * headLength;
43944
43945 if ( lineGeometry === undefined ) {
43946
43947 lineGeometry = new BufferGeometry();
43948 lineGeometry.addAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 1, 0 ], 3 ) );
43949
43950 coneGeometry = new CylinderBufferGeometry( 0, 0.5, 1, 5, 1 );
43951 coneGeometry.translate( 0, - 0.5, 0 );
43952
43953 }
43954
43955 this.position.copy( origin );
43956
43957 this.line = new Line( lineGeometry, new LineBasicMaterial( { color: color } ) );
43958 this.line.matrixAutoUpdate = false;
43959 this.add( this.line );
43960
43961 this.cone = new Mesh( coneGeometry, new MeshBasicMaterial( { color: color } ) );
43962 this.cone.matrixAutoUpdate = false;
43963 this.add( this.cone );
43964
43965 this.setDirection( dir );
43966 this.setLength( length, headLength, headWidth );
43967
43968}
43969
43970ArrowHelper.prototype = Object.create( Object3D.prototype );
43971ArrowHelper.prototype.constructor = ArrowHelper;
43972
43973ArrowHelper.prototype.setDirection = ( function () {
43974
43975 var axis = new Vector3();
43976 var radians;
43977
43978 return function setDirection( dir ) {
43979
43980 // dir is assumed to be normalized
43981
43982 if ( dir.y > 0.99999 ) {
43983
43984 this.quaternion.set( 0, 0, 0, 1 );
43985
43986 } else if ( dir.y < - 0.99999 ) {
43987
43988 this.quaternion.set( 1, 0, 0, 0 );
43989
43990 } else {
43991
43992 axis.set( dir.z, 0, - dir.x ).normalize();
43993
43994 radians = Math.acos( dir.y );
43995
43996 this.quaternion.setFromAxisAngle( axis, radians );
43997
43998 }
43999
44000 };
44001
44002}() );
44003
44004ArrowHelper.prototype.setLength = function ( length, headLength, headWidth ) {
44005
44006 if ( headLength === undefined ) headLength = 0.2 * length;
44007 if ( headWidth === undefined ) headWidth = 0.2 * headLength;
44008
44009 this.line.scale.set( 1, Math.max( 0, length - headLength ), 1 );
44010 this.line.updateMatrix();
44011
44012 this.cone.scale.set( headWidth, headLength, headWidth );
44013 this.cone.position.y = length;
44014 this.cone.updateMatrix();
44015
44016};
44017
44018ArrowHelper.prototype.setColor = function ( color ) {
44019
44020 this.line.material.color.copy( color );
44021 this.cone.material.color.copy( color );
44022
44023};
44024
44025/**
44026 * @author sroucheray / http://sroucheray.org/
44027 * @author mrdoob / http://mrdoob.com/
44028 */
44029
44030function AxesHelper( size ) {
44031
44032 size = size || 1;
44033
44034 var vertices = [
44035 0, 0, 0, size, 0, 0,
44036 0, 0, 0, 0, size, 0,
44037 0, 0, 0, 0, 0, size
44038 ];
44039
44040 var colors = [
44041 1, 0, 0, 1, 0.6, 0,
44042 0, 1, 0, 0.6, 1, 0,
44043 0, 0, 1, 0, 0.6, 1
44044 ];
44045
44046 var geometry = new BufferGeometry();
44047 geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
44048 geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
44049
44050 var material = new LineBasicMaterial( { vertexColors: VertexColors } );
44051
44052 LineSegments.call( this, geometry, material );
44053
44054}
44055
44056AxesHelper.prototype = Object.create( LineSegments.prototype );
44057AxesHelper.prototype.constructor = AxesHelper;
44058
44059/**
44060 * @author mrdoob / http://mrdoob.com/
44061 */
44062
44063function Face4( a, b, c, d, normal, color, materialIndex ) {
44064
44065 console.warn( 'THREE.Face4 has been removed. A THREE.Face3 will be created instead.' );
44066 return new Face3( a, b, c, normal, color, materialIndex );
44067
44068}
44069
44070var LineStrip = 0;
44071
44072var LinePieces = 1;
44073
44074function MeshFaceMaterial( materials ) {
44075
44076 console.warn( 'THREE.MeshFaceMaterial has been removed. Use an Array instead.' );
44077 return materials;
44078
44079}
44080
44081function MultiMaterial( materials ) {
44082
44083 if ( materials === undefined ) materials = [];
44084
44085 console.warn( 'THREE.MultiMaterial has been removed. Use an Array instead.' );
44086 materials.isMultiMaterial = true;
44087 materials.materials = materials;
44088 materials.clone = function () {
44089
44090 return materials.slice();
44091
44092 };
44093 return materials;
44094
44095}
44096
44097function PointCloud( geometry, material ) {
44098
44099 console.warn( 'THREE.PointCloud has been renamed to THREE.Points.' );
44100 return new Points( geometry, material );
44101
44102}
44103
44104function Particle( material ) {
44105
44106 console.warn( 'THREE.Particle has been renamed to THREE.Sprite.' );
44107 return new Sprite( material );
44108
44109}
44110
44111function ParticleSystem( geometry, material ) {
44112
44113 console.warn( 'THREE.ParticleSystem has been renamed to THREE.Points.' );
44114 return new Points( geometry, material );
44115
44116}
44117
44118function PointCloudMaterial( parameters ) {
44119
44120 console.warn( 'THREE.PointCloudMaterial has been renamed to THREE.PointsMaterial.' );
44121 return new PointsMaterial( parameters );
44122
44123}
44124
44125function ParticleBasicMaterial( parameters ) {
44126
44127 console.warn( 'THREE.ParticleBasicMaterial has been renamed to THREE.PointsMaterial.' );
44128 return new PointsMaterial( parameters );
44129
44130}
44131
44132function ParticleSystemMaterial( parameters ) {
44133
44134 console.warn( 'THREE.ParticleSystemMaterial has been renamed to THREE.PointsMaterial.' );
44135 return new PointsMaterial( parameters );
44136
44137}
44138
44139function Vertex( x, y, z ) {
44140
44141 console.warn( 'THREE.Vertex has been removed. Use THREE.Vector3 instead.' );
44142 return new Vector3( x, y, z );
44143
44144}
44145
44146//
44147
44148function DynamicBufferAttribute( array, itemSize ) {
44149
44150 console.warn( 'THREE.DynamicBufferAttribute has been removed. Use new THREE.BufferAttribute().setDynamic( true ) instead.' );
44151 return new BufferAttribute( array, itemSize ).setDynamic( true );
44152
44153}
44154
44155function Int8Attribute( array, itemSize ) {
44156
44157 console.warn( 'THREE.Int8Attribute has been removed. Use new THREE.Int8BufferAttribute() instead.' );
44158 return new Int8BufferAttribute( array, itemSize );
44159
44160}
44161
44162function Uint8Attribute( array, itemSize ) {
44163
44164 console.warn( 'THREE.Uint8Attribute has been removed. Use new THREE.Uint8BufferAttribute() instead.' );
44165 return new Uint8BufferAttribute( array, itemSize );
44166
44167}
44168
44169function Uint8ClampedAttribute( array, itemSize ) {
44170
44171 console.warn( 'THREE.Uint8ClampedAttribute has been removed. Use new THREE.Uint8ClampedBufferAttribute() instead.' );
44172 return new Uint8ClampedBufferAttribute( array, itemSize );
44173
44174}
44175
44176function Int16Attribute( array, itemSize ) {
44177
44178 console.warn( 'THREE.Int16Attribute has been removed. Use new THREE.Int16BufferAttribute() instead.' );
44179 return new Int16BufferAttribute( array, itemSize );
44180
44181}
44182
44183function Uint16Attribute( array, itemSize ) {
44184
44185 console.warn( 'THREE.Uint16Attribute has been removed. Use new THREE.Uint16BufferAttribute() instead.' );
44186 return new Uint16BufferAttribute( array, itemSize );
44187
44188}
44189
44190function Int32Attribute( array, itemSize ) {
44191
44192 console.warn( 'THREE.Int32Attribute has been removed. Use new THREE.Int32BufferAttribute() instead.' );
44193 return new Int32BufferAttribute( array, itemSize );
44194
44195}
44196
44197function Uint32Attribute( array, itemSize ) {
44198
44199 console.warn( 'THREE.Uint32Attribute has been removed. Use new THREE.Uint32BufferAttribute() instead.' );
44200 return new Uint32BufferAttribute( array, itemSize );
44201
44202}
44203
44204function Float32Attribute( array, itemSize ) {
44205
44206 console.warn( 'THREE.Float32Attribute has been removed. Use new THREE.Float32BufferAttribute() instead.' );
44207 return new Float32BufferAttribute( array, itemSize );
44208
44209}
44210
44211function Float64Attribute( array, itemSize ) {
44212
44213 console.warn( 'THREE.Float64Attribute has been removed. Use new THREE.Float64BufferAttribute() instead.' );
44214 return new Float64BufferAttribute( array, itemSize );
44215
44216}
44217
44218//
44219
44220Curve.create = function ( construct, getPoint ) {
44221
44222 console.log( 'THREE.Curve.create() has been deprecated' );
44223
44224 construct.prototype = Object.create( Curve.prototype );
44225 construct.prototype.constructor = construct;
44226 construct.prototype.getPoint = getPoint;
44227
44228 return construct;
44229
44230};
44231
44232//
44233
44234Object.assign( CurvePath.prototype, {
44235
44236 createPointsGeometry: function ( divisions ) {
44237
44238 console.warn( 'THREE.CurvePath: .createPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' );
44239
44240 // generate geometry from path points (for Line or Points objects)
44241
44242 var pts = this.getPoints( divisions );
44243 return this.createGeometry( pts );
44244
44245 },
44246
44247 createSpacedPointsGeometry: function ( divisions ) {
44248
44249 console.warn( 'THREE.CurvePath: .createSpacedPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' );
44250
44251 // generate geometry from equidistant sampling along the path
44252
44253 var pts = this.getSpacedPoints( divisions );
44254 return this.createGeometry( pts );
44255
44256 },
44257
44258 createGeometry: function ( points ) {
44259
44260 console.warn( 'THREE.CurvePath: .createGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' );
44261
44262 var geometry = new Geometry();
44263
44264 for ( var i = 0, l = points.length; i < l; i ++ ) {
44265
44266 var point = points[ i ];
44267 geometry.vertices.push( new Vector3( point.x, point.y, point.z || 0 ) );
44268
44269 }
44270
44271 return geometry;
44272
44273 }
44274
44275} );
44276
44277//
44278
44279Object.assign( Path.prototype, {
44280
44281 fromPoints: function ( points ) {
44282
44283 console.warn( 'THREE.Path: .fromPoints() has been renamed to .setFromPoints().' );
44284 this.setFromPoints( points );
44285
44286 }
44287
44288} );
44289
44290//
44291
44292function ClosedSplineCurve3( points ) {
44293
44294 console.warn( 'THREE.ClosedSplineCurve3 has been deprecated. Use THREE.CatmullRomCurve3 instead.' );
44295
44296 CatmullRomCurve3.call( this, points );
44297 this.type = 'catmullrom';
44298 this.closed = true;
44299
44300}
44301
44302ClosedSplineCurve3.prototype = Object.create( CatmullRomCurve3.prototype );
44303
44304//
44305
44306function SplineCurve3( points ) {
44307
44308 console.warn( 'THREE.SplineCurve3 has been deprecated. Use THREE.CatmullRomCurve3 instead.' );
44309
44310 CatmullRomCurve3.call( this, points );
44311 this.type = 'catmullrom';
44312
44313}
44314
44315SplineCurve3.prototype = Object.create( CatmullRomCurve3.prototype );
44316
44317//
44318
44319function Spline( points ) {
44320
44321 console.warn( 'THREE.Spline has been removed. Use THREE.CatmullRomCurve3 instead.' );
44322
44323 CatmullRomCurve3.call( this, points );
44324 this.type = 'catmullrom';
44325
44326}
44327
44328Spline.prototype = Object.create( CatmullRomCurve3.prototype );
44329
44330Object.assign( Spline.prototype, {
44331
44332 initFromArray: function ( /* a */ ) {
44333
44334 console.error( 'THREE.Spline: .initFromArray() has been removed.' );
44335
44336 },
44337 getControlPointsArray: function ( /* optionalTarget */ ) {
44338
44339 console.error( 'THREE.Spline: .getControlPointsArray() has been removed.' );
44340
44341 },
44342 reparametrizeByArcLength: function ( /* samplingCoef */ ) {
44343
44344 console.error( 'THREE.Spline: .reparametrizeByArcLength() has been removed.' );
44345
44346 }
44347
44348} );
44349
44350//
44351
44352function AxisHelper( size ) {
44353
44354 console.warn( 'THREE.AxisHelper has been renamed to THREE.AxesHelper.' );
44355 return new AxesHelper( size );
44356
44357}
44358
44359function BoundingBoxHelper( object, color ) {
44360
44361 console.warn( 'THREE.BoundingBoxHelper has been deprecated. Creating a THREE.BoxHelper instead.' );
44362 return new BoxHelper( object, color );
44363
44364}
44365
44366function EdgesHelper( object, hex ) {
44367
44368 console.warn( 'THREE.EdgesHelper has been removed. Use THREE.EdgesGeometry instead.' );
44369 return new LineSegments( new EdgesGeometry( object.geometry ), new LineBasicMaterial( { color: hex !== undefined ? hex : 0xffffff } ) );
44370
44371}
44372
44373GridHelper.prototype.setColors = function () {
44374
44375 console.error( 'THREE.GridHelper: setColors() has been deprecated, pass them in the constructor instead.' );
44376
44377};
44378
44379SkeletonHelper.prototype.update = function () {
44380
44381 console.error( 'THREE.SkeletonHelper: update() no longer needs to be called.' );
44382
44383};
44384
44385function WireframeHelper( object, hex ) {
44386
44387 console.warn( 'THREE.WireframeHelper has been removed. Use THREE.WireframeGeometry instead.' );
44388 return new LineSegments( new WireframeGeometry( object.geometry ), new LineBasicMaterial( { color: hex !== undefined ? hex : 0xffffff } ) );
44389
44390}
44391
44392//
44393
44394Object.assign( Loader.prototype, {
44395
44396 extractUrlBase: function ( url ) {
44397
44398 console.warn( 'THREE.Loader: .extractUrlBase() has been deprecated. Use THREE.LoaderUtils.extractUrlBase() instead.' );
44399 return LoaderUtils.extractUrlBase( url );
44400
44401 }
44402
44403} );
44404
44405function XHRLoader( manager ) {
44406
44407 console.warn( 'THREE.XHRLoader has been renamed to THREE.FileLoader.' );
44408 return new FileLoader( manager );
44409
44410}
44411
44412function BinaryTextureLoader( manager ) {
44413
44414 console.warn( 'THREE.BinaryTextureLoader has been renamed to THREE.DataTextureLoader.' );
44415 return new DataTextureLoader( manager );
44416
44417}
44418
44419//
44420
44421Object.assign( Box2.prototype, {
44422
44423 center: function ( optionalTarget ) {
44424
44425 console.warn( 'THREE.Box2: .center() has been renamed to .getCenter().' );
44426 return this.getCenter( optionalTarget );
44427
44428 },
44429 empty: function () {
44430
44431 console.warn( 'THREE.Box2: .empty() has been renamed to .isEmpty().' );
44432 return this.isEmpty();
44433
44434 },
44435 isIntersectionBox: function ( box ) {
44436
44437 console.warn( 'THREE.Box2: .isIntersectionBox() has been renamed to .intersectsBox().' );
44438 return this.intersectsBox( box );
44439
44440 },
44441 size: function ( optionalTarget ) {
44442
44443 console.warn( 'THREE.Box2: .size() has been renamed to .getSize().' );
44444 return this.getSize( optionalTarget );
44445
44446 }
44447} );
44448
44449Object.assign( Box3.prototype, {
44450
44451 center: function ( optionalTarget ) {
44452
44453 console.warn( 'THREE.Box3: .center() has been renamed to .getCenter().' );
44454 return this.getCenter( optionalTarget );
44455
44456 },
44457 empty: function () {
44458
44459 console.warn( 'THREE.Box3: .empty() has been renamed to .isEmpty().' );
44460 return this.isEmpty();
44461
44462 },
44463 isIntersectionBox: function ( box ) {
44464
44465 console.warn( 'THREE.Box3: .isIntersectionBox() has been renamed to .intersectsBox().' );
44466 return this.intersectsBox( box );
44467
44468 },
44469 isIntersectionSphere: function ( sphere ) {
44470
44471 console.warn( 'THREE.Box3: .isIntersectionSphere() has been renamed to .intersectsSphere().' );
44472 return this.intersectsSphere( sphere );
44473
44474 },
44475 size: function ( optionalTarget ) {
44476
44477 console.warn( 'THREE.Box3: .size() has been renamed to .getSize().' );
44478 return this.getSize( optionalTarget );
44479
44480 }
44481} );
44482
44483Line3.prototype.center = function ( optionalTarget ) {
44484
44485 console.warn( 'THREE.Line3: .center() has been renamed to .getCenter().' );
44486 return this.getCenter( optionalTarget );
44487
44488};
44489
44490Object.assign( _Math, {
44491
44492 random16: function () {
44493
44494 console.warn( 'THREE.Math: .random16() has been deprecated. Use Math.random() instead.' );
44495 return Math.random();
44496
44497 },
44498
44499 nearestPowerOfTwo: function ( value ) {
44500
44501 console.warn( 'THREE.Math: .nearestPowerOfTwo() has been renamed to .floorPowerOfTwo().' );
44502 return _Math.floorPowerOfTwo( value );
44503
44504 },
44505
44506 nextPowerOfTwo: function ( value ) {
44507
44508 console.warn( 'THREE.Math: .nextPowerOfTwo() has been renamed to .ceilPowerOfTwo().' );
44509 return _Math.ceilPowerOfTwo( value );
44510
44511 }
44512
44513} );
44514
44515Object.assign( Matrix3.prototype, {
44516
44517 flattenToArrayOffset: function ( array, offset ) {
44518
44519 console.warn( "THREE.Matrix3: .flattenToArrayOffset() has been deprecated. Use .toArray() instead." );
44520 return this.toArray( array, offset );
44521
44522 },
44523 multiplyVector3: function ( vector ) {
44524
44525 console.warn( 'THREE.Matrix3: .multiplyVector3() has been removed. Use vector.applyMatrix3( matrix ) instead.' );
44526 return vector.applyMatrix3( this );
44527
44528 },
44529 multiplyVector3Array: function ( /* a */ ) {
44530
44531 console.error( 'THREE.Matrix3: .multiplyVector3Array() has been removed.' );
44532
44533 },
44534 applyToBuffer: function ( buffer /*, offset, length */ ) {
44535
44536 console.warn( 'THREE.Matrix3: .applyToBuffer() has been removed. Use matrix.applyToBufferAttribute( attribute ) instead.' );
44537 return this.applyToBufferAttribute( buffer );
44538
44539 },
44540 applyToVector3Array: function ( /* array, offset, length */ ) {
44541
44542 console.error( 'THREE.Matrix3: .applyToVector3Array() has been removed.' );
44543
44544 }
44545
44546} );
44547
44548Object.assign( Matrix4.prototype, {
44549
44550 extractPosition: function ( m ) {
44551
44552 console.warn( 'THREE.Matrix4: .extractPosition() has been renamed to .copyPosition().' );
44553 return this.copyPosition( m );
44554
44555 },
44556 flattenToArrayOffset: function ( array, offset ) {
44557
44558 console.warn( "THREE.Matrix4: .flattenToArrayOffset() has been deprecated. Use .toArray() instead." );
44559 return this.toArray( array, offset );
44560
44561 },
44562 getPosition: function () {
44563
44564 var v1;
44565
44566 return function getPosition() {
44567
44568 if ( v1 === undefined ) v1 = new Vector3();
44569 console.warn( 'THREE.Matrix4: .getPosition() has been removed. Use Vector3.setFromMatrixPosition( matrix ) instead.' );
44570 return v1.setFromMatrixColumn( this, 3 );
44571
44572 };
44573
44574 }(),
44575 setRotationFromQuaternion: function ( q ) {
44576
44577 console.warn( 'THREE.Matrix4: .setRotationFromQuaternion() has been renamed to .makeRotationFromQuaternion().' );
44578 return this.makeRotationFromQuaternion( q );
44579
44580 },
44581 multiplyToArray: function () {
44582
44583 console.warn( 'THREE.Matrix4: .multiplyToArray() has been removed.' );
44584
44585 },
44586 multiplyVector3: function ( vector ) {
44587
44588 console.warn( 'THREE.Matrix4: .multiplyVector3() has been removed. Use vector.applyMatrix4( matrix ) instead.' );
44589 return vector.applyMatrix4( this );
44590
44591 },
44592 multiplyVector4: function ( vector ) {
44593
44594 console.warn( 'THREE.Matrix4: .multiplyVector4() has been removed. Use vector.applyMatrix4( matrix ) instead.' );
44595 return vector.applyMatrix4( this );
44596
44597 },
44598 multiplyVector3Array: function ( /* a */ ) {
44599
44600 console.error( 'THREE.Matrix4: .multiplyVector3Array() has been removed.' );
44601
44602 },
44603 rotateAxis: function ( v ) {
44604
44605 console.warn( 'THREE.Matrix4: .rotateAxis() has been removed. Use Vector3.transformDirection( matrix ) instead.' );
44606 v.transformDirection( this );
44607
44608 },
44609 crossVector: function ( vector ) {
44610
44611 console.warn( 'THREE.Matrix4: .crossVector() has been removed. Use vector.applyMatrix4( matrix ) instead.' );
44612 return vector.applyMatrix4( this );
44613
44614 },
44615 translate: function () {
44616
44617 console.error( 'THREE.Matrix4: .translate() has been removed.' );
44618
44619 },
44620 rotateX: function () {
44621
44622 console.error( 'THREE.Matrix4: .rotateX() has been removed.' );
44623
44624 },
44625 rotateY: function () {
44626
44627 console.error( 'THREE.Matrix4: .rotateY() has been removed.' );
44628
44629 },
44630 rotateZ: function () {
44631
44632 console.error( 'THREE.Matrix4: .rotateZ() has been removed.' );
44633
44634 },
44635 rotateByAxis: function () {
44636
44637 console.error( 'THREE.Matrix4: .rotateByAxis() has been removed.' );
44638
44639 },
44640 applyToBuffer: function ( buffer /*, offset, length */ ) {
44641
44642 console.warn( 'THREE.Matrix4: .applyToBuffer() has been removed. Use matrix.applyToBufferAttribute( attribute ) instead.' );
44643 return this.applyToBufferAttribute( buffer );
44644
44645 },
44646 applyToVector3Array: function ( /* array, offset, length */ ) {
44647
44648 console.error( 'THREE.Matrix4: .applyToVector3Array() has been removed.' );
44649
44650 },
44651 makeFrustum: function ( left, right, bottom, top, near, far ) {
44652
44653 console.warn( 'THREE.Matrix4: .makeFrustum() has been removed. Use .makePerspective( left, right, top, bottom, near, far ) instead.' );
44654 return this.makePerspective( left, right, top, bottom, near, far );
44655
44656 }
44657
44658} );
44659
44660Plane.prototype.isIntersectionLine = function ( line ) {
44661
44662 console.warn( 'THREE.Plane: .isIntersectionLine() has been renamed to .intersectsLine().' );
44663 return this.intersectsLine( line );
44664
44665};
44666
44667Quaternion.prototype.multiplyVector3 = function ( vector ) {
44668
44669 console.warn( 'THREE.Quaternion: .multiplyVector3() has been removed. Use is now vector.applyQuaternion( quaternion ) instead.' );
44670 return vector.applyQuaternion( this );
44671
44672};
44673
44674Object.assign( Ray.prototype, {
44675
44676 isIntersectionBox: function ( box ) {
44677
44678 console.warn( 'THREE.Ray: .isIntersectionBox() has been renamed to .intersectsBox().' );
44679 return this.intersectsBox( box );
44680
44681 },
44682 isIntersectionPlane: function ( plane ) {
44683
44684 console.warn( 'THREE.Ray: .isIntersectionPlane() has been renamed to .intersectsPlane().' );
44685 return this.intersectsPlane( plane );
44686
44687 },
44688 isIntersectionSphere: function ( sphere ) {
44689
44690 console.warn( 'THREE.Ray: .isIntersectionSphere() has been renamed to .intersectsSphere().' );
44691 return this.intersectsSphere( sphere );
44692
44693 }
44694
44695} );
44696
44697Object.assign( Triangle.prototype, {
44698
44699 area: function () {
44700
44701 console.warn( 'THREE.Triangle: .area() has been renamed to .getArea().' );
44702 return this.getArea();
44703
44704 },
44705 barycoordFromPoint: function ( point, target ) {
44706
44707 console.warn( 'THREE.Triangle: .barycoordFromPoint() has been renamed to .getBarycoord().' );
44708 return this.getBarycoord( point, target );
44709
44710 },
44711 midpoint: function ( target ) {
44712
44713 console.warn( 'THREE.Triangle: .midpoint() has been renamed to .getMidpoint().' );
44714 return this.getMidpoint( target );
44715
44716 },
44717 normal: function ( target ) {
44718
44719 console.warn( 'THREE.Triangle: .normal() has been renamed to .getNormal().' );
44720 return this.getNormal( target );
44721
44722 },
44723 plane: function ( target ) {
44724
44725 console.warn( 'THREE.Triangle: .plane() has been renamed to .getPlane().' );
44726 return this.getPlane( target );
44727
44728 }
44729
44730} );
44731
44732Object.assign( Triangle, {
44733
44734 barycoordFromPoint: function ( point, a, b, c, target ) {
44735
44736 console.warn( 'THREE.Triangle: .barycoordFromPoint() has been renamed to .getBarycoord().' );
44737 return Triangle.getBarycoord( point, a, b, c, target );
44738
44739 },
44740 normal: function ( a, b, c, target ) {
44741
44742 console.warn( 'THREE.Triangle: .normal() has been renamed to .getNormal().' );
44743 return Triangle.getNormal( a, b, c, target );
44744
44745 }
44746
44747} );
44748
44749Object.assign( Shape.prototype, {
44750
44751 extractAllPoints: function ( divisions ) {
44752
44753 console.warn( 'THREE.Shape: .extractAllPoints() has been removed. Use .extractPoints() instead.' );
44754 return this.extractPoints( divisions );
44755
44756 },
44757 extrude: function ( options ) {
44758
44759 console.warn( 'THREE.Shape: .extrude() has been removed. Use ExtrudeGeometry() instead.' );
44760 return new ExtrudeGeometry( this, options );
44761
44762 },
44763 makeGeometry: function ( options ) {
44764
44765 console.warn( 'THREE.Shape: .makeGeometry() has been removed. Use ShapeGeometry() instead.' );
44766 return new ShapeGeometry( this, options );
44767
44768 }
44769
44770} );
44771
44772Object.assign( Vector2.prototype, {
44773
44774 fromAttribute: function ( attribute, index, offset ) {
44775
44776 console.warn( 'THREE.Vector2: .fromAttribute() has been renamed to .fromBufferAttribute().' );
44777 return this.fromBufferAttribute( attribute, index, offset );
44778
44779 },
44780 distanceToManhattan: function ( v ) {
44781
44782 console.warn( 'THREE.Vector2: .distanceToManhattan() has been renamed to .manhattanDistanceTo().' );
44783 return this.manhattanDistanceTo( v );
44784
44785 },
44786 lengthManhattan: function () {
44787
44788 console.warn( 'THREE.Vector2: .lengthManhattan() has been renamed to .manhattanLength().' );
44789 return this.manhattanLength();
44790
44791 }
44792
44793} );
44794
44795Object.assign( Vector3.prototype, {
44796
44797 setEulerFromRotationMatrix: function () {
44798
44799 console.error( 'THREE.Vector3: .setEulerFromRotationMatrix() has been removed. Use Euler.setFromRotationMatrix() instead.' );
44800
44801 },
44802 setEulerFromQuaternion: function () {
44803
44804 console.error( 'THREE.Vector3: .setEulerFromQuaternion() has been removed. Use Euler.setFromQuaternion() instead.' );
44805
44806 },
44807 getPositionFromMatrix: function ( m ) {
44808
44809 console.warn( 'THREE.Vector3: .getPositionFromMatrix() has been renamed to .setFromMatrixPosition().' );
44810 return this.setFromMatrixPosition( m );
44811
44812 },
44813 getScaleFromMatrix: function ( m ) {
44814
44815 console.warn( 'THREE.Vector3: .getScaleFromMatrix() has been renamed to .setFromMatrixScale().' );
44816 return this.setFromMatrixScale( m );
44817
44818 },
44819 getColumnFromMatrix: function ( index, matrix ) {
44820
44821 console.warn( 'THREE.Vector3: .getColumnFromMatrix() has been renamed to .setFromMatrixColumn().' );
44822 return this.setFromMatrixColumn( matrix, index );
44823
44824 },
44825 applyProjection: function ( m ) {
44826
44827 console.warn( 'THREE.Vector3: .applyProjection() has been removed. Use .applyMatrix4( m ) instead.' );
44828 return this.applyMatrix4( m );
44829
44830 },
44831 fromAttribute: function ( attribute, index, offset ) {
44832
44833 console.warn( 'THREE.Vector3: .fromAttribute() has been renamed to .fromBufferAttribute().' );
44834 return this.fromBufferAttribute( attribute, index, offset );
44835
44836 },
44837 distanceToManhattan: function ( v ) {
44838
44839 console.warn( 'THREE.Vector3: .distanceToManhattan() has been renamed to .manhattanDistanceTo().' );
44840 return this.manhattanDistanceTo( v );
44841
44842 },
44843 lengthManhattan: function () {
44844
44845 console.warn( 'THREE.Vector3: .lengthManhattan() has been renamed to .manhattanLength().' );
44846 return this.manhattanLength();
44847
44848 }
44849
44850} );
44851
44852Object.assign( Vector4.prototype, {
44853
44854 fromAttribute: function ( attribute, index, offset ) {
44855
44856 console.warn( 'THREE.Vector4: .fromAttribute() has been renamed to .fromBufferAttribute().' );
44857 return this.fromBufferAttribute( attribute, index, offset );
44858
44859 },
44860 lengthManhattan: function () {
44861
44862 console.warn( 'THREE.Vector4: .lengthManhattan() has been renamed to .manhattanLength().' );
44863 return this.manhattanLength();
44864
44865 }
44866
44867} );
44868
44869//
44870
44871Object.assign( Geometry.prototype, {
44872
44873 computeTangents: function () {
44874
44875 console.error( 'THREE.Geometry: .computeTangents() has been removed.' );
44876
44877 },
44878 computeLineDistances: function () {
44879
44880 console.error( 'THREE.Geometry: .computeLineDistances() has been removed. Use THREE.Line.computeLineDistances() instead.' );
44881
44882 }
44883
44884} );
44885
44886Object.assign( Object3D.prototype, {
44887
44888 getChildByName: function ( name ) {
44889
44890 console.warn( 'THREE.Object3D: .getChildByName() has been renamed to .getObjectByName().' );
44891 return this.getObjectByName( name );
44892
44893 },
44894 renderDepth: function () {
44895
44896 console.warn( 'THREE.Object3D: .renderDepth has been removed. Use .renderOrder, instead.' );
44897
44898 },
44899 translate: function ( distance, axis ) {
44900
44901 console.warn( 'THREE.Object3D: .translate() has been removed. Use .translateOnAxis( axis, distance ) instead.' );
44902 return this.translateOnAxis( axis, distance );
44903
44904 },
44905 getWorldRotation: function () {
44906
44907 console.error( 'THREE.Object3D: .getWorldRotation() has been removed. Use THREE.Object3D.getWorldQuaternion( target ) instead.' );
44908
44909 }
44910
44911} );
44912
44913Object.defineProperties( Object3D.prototype, {
44914
44915 eulerOrder: {
44916 get: function () {
44917
44918 console.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' );
44919 return this.rotation.order;
44920
44921 },
44922 set: function ( value ) {
44923
44924 console.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' );
44925 this.rotation.order = value;
44926
44927 }
44928 },
44929 useQuaternion: {
44930 get: function () {
44931
44932 console.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' );
44933
44934 },
44935 set: function () {
44936
44937 console.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' );
44938
44939 }
44940 }
44941
44942} );
44943
44944Object.defineProperties( LOD.prototype, {
44945
44946 objects: {
44947 get: function () {
44948
44949 console.warn( 'THREE.LOD: .objects has been renamed to .levels.' );
44950 return this.levels;
44951
44952 }
44953 }
44954
44955} );
44956
44957Object.defineProperty( Skeleton.prototype, 'useVertexTexture', {
44958
44959 get: function () {
44960
44961 console.warn( 'THREE.Skeleton: useVertexTexture has been removed.' );
44962
44963 },
44964 set: function () {
44965
44966 console.warn( 'THREE.Skeleton: useVertexTexture has been removed.' );
44967
44968 }
44969
44970} );
44971
44972Object.defineProperty( Curve.prototype, '__arcLengthDivisions', {
44973
44974 get: function () {
44975
44976 console.warn( 'THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.' );
44977 return this.arcLengthDivisions;
44978
44979 },
44980 set: function ( value ) {
44981
44982 console.warn( 'THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.' );
44983 this.arcLengthDivisions = value;
44984
44985 }
44986
44987} );
44988
44989//
44990
44991PerspectiveCamera.prototype.setLens = function ( focalLength, filmGauge ) {
44992
44993 console.warn( "THREE.PerspectiveCamera.setLens is deprecated. " +
44994 "Use .setFocalLength and .filmGauge for a photographic setup." );
44995
44996 if ( filmGauge !== undefined ) this.filmGauge = filmGauge;
44997 this.setFocalLength( focalLength );
44998
44999};
45000
45001//
45002
45003Object.defineProperties( Light.prototype, {
45004 onlyShadow: {
45005 set: function () {
45006
45007 console.warn( 'THREE.Light: .onlyShadow has been removed.' );
45008
45009 }
45010 },
45011 shadowCameraFov: {
45012 set: function ( value ) {
45013
45014 console.warn( 'THREE.Light: .shadowCameraFov is now .shadow.camera.fov.' );
45015 this.shadow.camera.fov = value;
45016
45017 }
45018 },
45019 shadowCameraLeft: {
45020 set: function ( value ) {
45021
45022 console.warn( 'THREE.Light: .shadowCameraLeft is now .shadow.camera.left.' );
45023 this.shadow.camera.left = value;
45024
45025 }
45026 },
45027 shadowCameraRight: {
45028 set: function ( value ) {
45029
45030 console.warn( 'THREE.Light: .shadowCameraRight is now .shadow.camera.right.' );
45031 this.shadow.camera.right = value;
45032
45033 }
45034 },
45035 shadowCameraTop: {
45036 set: function ( value ) {
45037
45038 console.warn( 'THREE.Light: .shadowCameraTop is now .shadow.camera.top.' );
45039 this.shadow.camera.top = value;
45040
45041 }
45042 },
45043 shadowCameraBottom: {
45044 set: function ( value ) {
45045
45046 console.warn( 'THREE.Light: .shadowCameraBottom is now .shadow.camera.bottom.' );
45047 this.shadow.camera.bottom = value;
45048
45049 }
45050 },
45051 shadowCameraNear: {
45052 set: function ( value ) {
45053
45054 console.warn( 'THREE.Light: .shadowCameraNear is now .shadow.camera.near.' );
45055 this.shadow.camera.near = value;
45056
45057 }
45058 },
45059 shadowCameraFar: {
45060 set: function ( value ) {
45061
45062 console.warn( 'THREE.Light: .shadowCameraFar is now .shadow.camera.far.' );
45063 this.shadow.camera.far = value;
45064
45065 }
45066 },
45067 shadowCameraVisible: {
45068 set: function () {
45069
45070 console.warn( 'THREE.Light: .shadowCameraVisible has been removed. Use new THREE.CameraHelper( light.shadow.camera ) instead.' );
45071
45072 }
45073 },
45074 shadowBias: {
45075 set: function ( value ) {
45076
45077 console.warn( 'THREE.Light: .shadowBias is now .shadow.bias.' );
45078 this.shadow.bias = value;
45079
45080 }
45081 },
45082 shadowDarkness: {
45083 set: function () {
45084
45085 console.warn( 'THREE.Light: .shadowDarkness has been removed.' );
45086
45087 }
45088 },
45089 shadowMapWidth: {
45090 set: function ( value ) {
45091
45092 console.warn( 'THREE.Light: .shadowMapWidth is now .shadow.mapSize.width.' );
45093 this.shadow.mapSize.width = value;
45094
45095 }
45096 },
45097 shadowMapHeight: {
45098 set: function ( value ) {
45099
45100 console.warn( 'THREE.Light: .shadowMapHeight is now .shadow.mapSize.height.' );
45101 this.shadow.mapSize.height = value;
45102
45103 }
45104 }
45105} );
45106
45107//
45108
45109Object.defineProperties( BufferAttribute.prototype, {
45110
45111 length: {
45112 get: function () {
45113
45114 console.warn( 'THREE.BufferAttribute: .length has been deprecated. Use .count instead.' );
45115 return this.array.length;
45116
45117 }
45118 },
45119 copyIndicesArray: function ( /* indices */ ) {
45120
45121 console.error( 'THREE.BufferAttribute: .copyIndicesArray() has been removed.' );
45122
45123 }
45124
45125} );
45126
45127Object.assign( BufferGeometry.prototype, {
45128
45129 addIndex: function ( index ) {
45130
45131 console.warn( 'THREE.BufferGeometry: .addIndex() has been renamed to .setIndex().' );
45132 this.setIndex( index );
45133
45134 },
45135 addDrawCall: function ( start, count, indexOffset ) {
45136
45137 if ( indexOffset !== undefined ) {
45138
45139 console.warn( 'THREE.BufferGeometry: .addDrawCall() no longer supports indexOffset.' );
45140
45141 }
45142 console.warn( 'THREE.BufferGeometry: .addDrawCall() is now .addGroup().' );
45143 this.addGroup( start, count );
45144
45145 },
45146 clearDrawCalls: function () {
45147
45148 console.warn( 'THREE.BufferGeometry: .clearDrawCalls() is now .clearGroups().' );
45149 this.clearGroups();
45150
45151 },
45152 computeTangents: function () {
45153
45154 console.warn( 'THREE.BufferGeometry: .computeTangents() has been removed.' );
45155
45156 },
45157 computeOffsets: function () {
45158
45159 console.warn( 'THREE.BufferGeometry: .computeOffsets() has been removed.' );
45160
45161 }
45162
45163} );
45164
45165Object.defineProperties( BufferGeometry.prototype, {
45166
45167 drawcalls: {
45168 get: function () {
45169
45170 console.error( 'THREE.BufferGeometry: .drawcalls has been renamed to .groups.' );
45171 return this.groups;
45172
45173 }
45174 },
45175 offsets: {
45176 get: function () {
45177
45178 console.warn( 'THREE.BufferGeometry: .offsets has been renamed to .groups.' );
45179 return this.groups;
45180
45181 }
45182 }
45183
45184} );
45185
45186//
45187
45188Object.assign( ExtrudeBufferGeometry.prototype, {
45189
45190 getArrays: function () {
45191
45192 console.error( 'THREE.ExtrudeBufferGeometry: .getArrays() has been removed.' );
45193
45194 },
45195
45196 addShapeList: function () {
45197
45198 console.error( 'THREE.ExtrudeBufferGeometry: .addShapeList() has been removed.' );
45199
45200 },
45201
45202 addShape: function () {
45203
45204 console.error( 'THREE.ExtrudeBufferGeometry: .addShape() has been removed.' );
45205
45206 }
45207
45208} );
45209
45210//
45211
45212Object.defineProperties( Uniform.prototype, {
45213
45214 dynamic: {
45215 set: function () {
45216
45217 console.warn( 'THREE.Uniform: .dynamic has been removed. Use object.onBeforeRender() instead.' );
45218
45219 }
45220 },
45221 onUpdate: {
45222 value: function () {
45223
45224 console.warn( 'THREE.Uniform: .onUpdate() has been removed. Use object.onBeforeRender() instead.' );
45225 return this;
45226
45227 }
45228 }
45229
45230} );
45231
45232//
45233
45234Object.defineProperties( Material.prototype, {
45235
45236 wrapAround: {
45237 get: function () {
45238
45239 console.warn( 'THREE.Material: .wrapAround has been removed.' );
45240
45241 },
45242 set: function () {
45243
45244 console.warn( 'THREE.Material: .wrapAround has been removed.' );
45245
45246 }
45247 },
45248 wrapRGB: {
45249 get: function () {
45250
45251 console.warn( 'THREE.Material: .wrapRGB has been removed.' );
45252 return new Color();
45253
45254 }
45255 },
45256
45257 shading: {
45258 get: function () {
45259
45260 console.error( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );
45261
45262 },
45263 set: function ( value ) {
45264
45265 console.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );
45266 this.flatShading = ( value === FlatShading );
45267
45268 }
45269 }
45270
45271} );
45272
45273Object.defineProperties( MeshPhongMaterial.prototype, {
45274
45275 metal: {
45276 get: function () {
45277
45278 console.warn( 'THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead.' );
45279 return false;
45280
45281 },
45282 set: function () {
45283
45284 console.warn( 'THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead' );
45285
45286 }
45287 }
45288
45289} );
45290
45291Object.defineProperties( ShaderMaterial.prototype, {
45292
45293 derivatives: {
45294 get: function () {
45295
45296 console.warn( 'THREE.ShaderMaterial: .derivatives has been moved to .extensions.derivatives.' );
45297 return this.extensions.derivatives;
45298
45299 },
45300 set: function ( value ) {
45301
45302 console.warn( 'THREE. ShaderMaterial: .derivatives has been moved to .extensions.derivatives.' );
45303 this.extensions.derivatives = value;
45304
45305 }
45306 }
45307
45308} );
45309
45310//
45311
45312Object.assign( WebGLRenderer.prototype, {
45313
45314 getCurrentRenderTarget: function () {
45315
45316 console.warn( 'THREE.WebGLRenderer: .getCurrentRenderTarget() is now .getRenderTarget().' );
45317 return this.getRenderTarget();
45318
45319 },
45320
45321 getMaxAnisotropy: function () {
45322
45323 console.warn( 'THREE.WebGLRenderer: .getMaxAnisotropy() is now .capabilities.getMaxAnisotropy().' );
45324 return this.capabilities.getMaxAnisotropy();
45325
45326 },
45327
45328 getPrecision: function () {
45329
45330 console.warn( 'THREE.WebGLRenderer: .getPrecision() is now .capabilities.precision.' );
45331 return this.capabilities.precision;
45332
45333 },
45334
45335 resetGLState: function () {
45336
45337 console.warn( 'THREE.WebGLRenderer: .resetGLState() is now .state.reset().' );
45338 return this.state.reset();
45339
45340 },
45341
45342 supportsFloatTextures: function () {
45343
45344 console.warn( 'THREE.WebGLRenderer: .supportsFloatTextures() is now .extensions.get( \'OES_texture_float\' ).' );
45345 return this.extensions.get( 'OES_texture_float' );
45346
45347 },
45348 supportsHalfFloatTextures: function () {
45349
45350 console.warn( 'THREE.WebGLRenderer: .supportsHalfFloatTextures() is now .extensions.get( \'OES_texture_half_float\' ).' );
45351 return this.extensions.get( 'OES_texture_half_float' );
45352
45353 },
45354 supportsStandardDerivatives: function () {
45355
45356 console.warn( 'THREE.WebGLRenderer: .supportsStandardDerivatives() is now .extensions.get( \'OES_standard_derivatives\' ).' );
45357 return this.extensions.get( 'OES_standard_derivatives' );
45358
45359 },
45360 supportsCompressedTextureS3TC: function () {
45361
45362 console.warn( 'THREE.WebGLRenderer: .supportsCompressedTextureS3TC() is now .extensions.get( \'WEBGL_compressed_texture_s3tc\' ).' );
45363 return this.extensions.get( 'WEBGL_compressed_texture_s3tc' );
45364
45365 },
45366 supportsCompressedTexturePVRTC: function () {
45367
45368 console.warn( 'THREE.WebGLRenderer: .supportsCompressedTexturePVRTC() is now .extensions.get( \'WEBGL_compressed_texture_pvrtc\' ).' );
45369 return this.extensions.get( 'WEBGL_compressed_texture_pvrtc' );
45370
45371 },
45372 supportsBlendMinMax: function () {
45373
45374 console.warn( 'THREE.WebGLRenderer: .supportsBlendMinMax() is now .extensions.get( \'EXT_blend_minmax\' ).' );
45375 return this.extensions.get( 'EXT_blend_minmax' );
45376
45377 },
45378 supportsVertexTextures: function () {
45379
45380 console.warn( 'THREE.WebGLRenderer: .supportsVertexTextures() is now .capabilities.vertexTextures.' );
45381 return this.capabilities.vertexTextures;
45382
45383 },
45384 supportsInstancedArrays: function () {
45385
45386 console.warn( 'THREE.WebGLRenderer: .supportsInstancedArrays() is now .extensions.get( \'ANGLE_instanced_arrays\' ).' );
45387 return this.extensions.get( 'ANGLE_instanced_arrays' );
45388
45389 },
45390 enableScissorTest: function ( boolean ) {
45391
45392 console.warn( 'THREE.WebGLRenderer: .enableScissorTest() is now .setScissorTest().' );
45393 this.setScissorTest( boolean );
45394
45395 },
45396 initMaterial: function () {
45397
45398 console.warn( 'THREE.WebGLRenderer: .initMaterial() has been removed.' );
45399
45400 },
45401 addPrePlugin: function () {
45402
45403 console.warn( 'THREE.WebGLRenderer: .addPrePlugin() has been removed.' );
45404
45405 },
45406 addPostPlugin: function () {
45407
45408 console.warn( 'THREE.WebGLRenderer: .addPostPlugin() has been removed.' );
45409
45410 },
45411 updateShadowMap: function () {
45412
45413 console.warn( 'THREE.WebGLRenderer: .updateShadowMap() has been removed.' );
45414
45415 },
45416 setFaceCulling: function () {
45417
45418 console.warn( 'THREE.WebGLRenderer: .setFaceCulling() has been removed.' );
45419
45420 }
45421
45422} );
45423
45424Object.defineProperties( WebGLRenderer.prototype, {
45425
45426 shadowMapEnabled: {
45427 get: function () {
45428
45429 return this.shadowMap.enabled;
45430
45431 },
45432 set: function ( value ) {
45433
45434 console.warn( 'THREE.WebGLRenderer: .shadowMapEnabled is now .shadowMap.enabled.' );
45435 this.shadowMap.enabled = value;
45436
45437 }
45438 },
45439 shadowMapType: {
45440 get: function () {
45441
45442 return this.shadowMap.type;
45443
45444 },
45445 set: function ( value ) {
45446
45447 console.warn( 'THREE.WebGLRenderer: .shadowMapType is now .shadowMap.type.' );
45448 this.shadowMap.type = value;
45449
45450 }
45451 },
45452 shadowMapCullFace: {
45453 get: function () {
45454
45455 console.warn( 'THREE.WebGLRenderer: .shadowMapCullFace has been removed. Set Material.shadowSide instead.' );
45456 return undefined;
45457
45458 },
45459 set: function ( /* value */ ) {
45460
45461 console.warn( 'THREE.WebGLRenderer: .shadowMapCullFace has been removed. Set Material.shadowSide instead.' );
45462
45463 }
45464 }
45465} );
45466
45467Object.defineProperties( WebGLShadowMap.prototype, {
45468
45469 cullFace: {
45470 get: function () {
45471
45472 console.warn( 'THREE.WebGLRenderer: .shadowMap.cullFace has been removed. Set Material.shadowSide instead.' );
45473 return undefined;
45474
45475 },
45476 set: function ( /* cullFace */ ) {
45477
45478 console.warn( 'THREE.WebGLRenderer: .shadowMap.cullFace has been removed. Set Material.shadowSide instead.' );
45479
45480 }
45481 },
45482 renderReverseSided: {
45483 get: function () {
45484
45485 console.warn( 'THREE.WebGLRenderer: .shadowMap.renderReverseSided has been removed. Set Material.shadowSide instead.' );
45486 return undefined;
45487
45488 },
45489 set: function () {
45490
45491 console.warn( 'THREE.WebGLRenderer: .shadowMap.renderReverseSided has been removed. Set Material.shadowSide instead.' );
45492
45493 }
45494 },
45495 renderSingleSided: {
45496 get: function () {
45497
45498 console.warn( 'THREE.WebGLRenderer: .shadowMap.renderSingleSided has been removed. Set Material.shadowSide instead.' );
45499 return undefined;
45500
45501 },
45502 set: function () {
45503
45504 console.warn( 'THREE.WebGLRenderer: .shadowMap.renderSingleSided has been removed. Set Material.shadowSide instead.' );
45505
45506 }
45507 }
45508
45509} );
45510
45511//
45512
45513Object.defineProperties( WebGLRenderTarget.prototype, {
45514
45515 wrapS: {
45516 get: function () {
45517
45518 console.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' );
45519 return this.texture.wrapS;
45520
45521 },
45522 set: function ( value ) {
45523
45524 console.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' );
45525 this.texture.wrapS = value;
45526
45527 }
45528 },
45529 wrapT: {
45530 get: function () {
45531
45532 console.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' );
45533 return this.texture.wrapT;
45534
45535 },
45536 set: function ( value ) {
45537
45538 console.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' );
45539 this.texture.wrapT = value;
45540
45541 }
45542 },
45543 magFilter: {
45544 get: function () {
45545
45546 console.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' );
45547 return this.texture.magFilter;
45548
45549 },
45550 set: function ( value ) {
45551
45552 console.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' );
45553 this.texture.magFilter = value;
45554
45555 }
45556 },
45557 minFilter: {
45558 get: function () {
45559
45560 console.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' );
45561 return this.texture.minFilter;
45562
45563 },
45564 set: function ( value ) {
45565
45566 console.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' );
45567 this.texture.minFilter = value;
45568
45569 }
45570 },
45571 anisotropy: {
45572 get: function () {
45573
45574 console.warn( 'THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.' );
45575 return this.texture.anisotropy;
45576
45577 },
45578 set: function ( value ) {
45579
45580 console.warn( 'THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.' );
45581 this.texture.anisotropy = value;
45582
45583 }
45584 },
45585 offset: {
45586 get: function () {
45587
45588 console.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' );
45589 return this.texture.offset;
45590
45591 },
45592 set: function ( value ) {
45593
45594 console.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' );
45595 this.texture.offset = value;
45596
45597 }
45598 },
45599 repeat: {
45600 get: function () {
45601
45602 console.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' );
45603 return this.texture.repeat;
45604
45605 },
45606 set: function ( value ) {
45607
45608 console.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' );
45609 this.texture.repeat = value;
45610
45611 }
45612 },
45613 format: {
45614 get: function () {
45615
45616 console.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' );
45617 return this.texture.format;
45618
45619 },
45620 set: function ( value ) {
45621
45622 console.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' );
45623 this.texture.format = value;
45624
45625 }
45626 },
45627 type: {
45628 get: function () {
45629
45630 console.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' );
45631 return this.texture.type;
45632
45633 },
45634 set: function ( value ) {
45635
45636 console.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' );
45637 this.texture.type = value;
45638
45639 }
45640 },
45641 generateMipmaps: {
45642 get: function () {
45643
45644 console.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' );
45645 return this.texture.generateMipmaps;
45646
45647 },
45648 set: function ( value ) {
45649
45650 console.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' );
45651 this.texture.generateMipmaps = value;
45652
45653 }
45654 }
45655
45656} );
45657
45658//
45659
45660Object.defineProperties( WebVRManager.prototype, {
45661
45662 standing: {
45663 set: function ( /* value */ ) {
45664
45665 console.warn( 'THREE.WebVRManager: .standing has been removed.' );
45666
45667 }
45668 }
45669
45670} );
45671
45672//
45673
45674Audio.prototype.load = function ( file ) {
45675
45676 console.warn( 'THREE.Audio: .load has been deprecated. Use THREE.AudioLoader instead.' );
45677 var scope = this;
45678 var audioLoader = new AudioLoader();
45679 audioLoader.load( file, function ( buffer ) {
45680
45681 scope.setBuffer( buffer );
45682
45683 } );
45684 return this;
45685
45686};
45687
45688AudioAnalyser.prototype.getData = function () {
45689
45690 console.warn( 'THREE.AudioAnalyser: .getData() is now .getFrequencyData().' );
45691 return this.getFrequencyData();
45692
45693};
45694
45695//
45696
45697CubeCamera.prototype.updateCubeMap = function ( renderer, scene ) {
45698
45699 console.warn( 'THREE.CubeCamera: .updateCubeMap() is now .update().' );
45700 return this.update( renderer, scene );
45701
45702};
45703
45704//
45705
45706var GeometryUtils = {
45707
45708 merge: function ( geometry1, geometry2, materialIndexOffset ) {
45709
45710 console.warn( 'THREE.GeometryUtils: .merge() has been moved to Geometry. Use geometry.merge( geometry2, matrix, materialIndexOffset ) instead.' );
45711 var matrix;
45712
45713 if ( geometry2.isMesh ) {
45714
45715 geometry2.matrixAutoUpdate && geometry2.updateMatrix();
45716
45717 matrix = geometry2.matrix;
45718 geometry2 = geometry2.geometry;
45719
45720 }
45721
45722 geometry1.merge( geometry2, matrix, materialIndexOffset );
45723
45724 },
45725
45726 center: function ( geometry ) {
45727
45728 console.warn( 'THREE.GeometryUtils: .center() has been moved to Geometry. Use geometry.center() instead.' );
45729 return geometry.center();
45730
45731 }
45732
45733};
45734
45735var ImageUtils = {
45736
45737 crossOrigin: undefined,
45738
45739 loadTexture: function ( url, mapping, onLoad, onError ) {
45740
45741 console.warn( 'THREE.ImageUtils.loadTexture has been deprecated. Use THREE.TextureLoader() instead.' );
45742
45743 var loader = new TextureLoader();
45744 loader.setCrossOrigin( this.crossOrigin );
45745
45746 var texture = loader.load( url, onLoad, undefined, onError );
45747
45748 if ( mapping ) texture.mapping = mapping;
45749
45750 return texture;
45751
45752 },
45753
45754 loadTextureCube: function ( urls, mapping, onLoad, onError ) {
45755
45756 console.warn( 'THREE.ImageUtils.loadTextureCube has been deprecated. Use THREE.CubeTextureLoader() instead.' );
45757
45758 var loader = new CubeTextureLoader();
45759 loader.setCrossOrigin( this.crossOrigin );
45760
45761 var texture = loader.load( urls, onLoad, undefined, onError );
45762
45763 if ( mapping ) texture.mapping = mapping;
45764
45765 return texture;
45766
45767 },
45768
45769 loadCompressedTexture: function () {
45770
45771 console.error( 'THREE.ImageUtils.loadCompressedTexture has been removed. Use THREE.DDSLoader instead.' );
45772
45773 },
45774
45775 loadCompressedTextureCube: function () {
45776
45777 console.error( 'THREE.ImageUtils.loadCompressedTextureCube has been removed. Use THREE.DDSLoader instead.' );
45778
45779 }
45780
45781};
45782
45783//
45784
45785function Projector() {
45786
45787 console.error( 'THREE.Projector has been moved to /examples/js/renderers/Projector.js.' );
45788
45789 this.projectVector = function ( vector, camera ) {
45790
45791 console.warn( 'THREE.Projector: .projectVector() is now vector.project().' );
45792 vector.project( camera );
45793
45794 };
45795
45796 this.unprojectVector = function ( vector, camera ) {
45797
45798 console.warn( 'THREE.Projector: .unprojectVector() is now vector.unproject().' );
45799 vector.unproject( camera );
45800
45801 };
45802
45803 this.pickingRay = function () {
45804
45805 console.error( 'THREE.Projector: .pickingRay() is now raycaster.setFromCamera().' );
45806
45807 };
45808
45809}
45810
45811//
45812
45813function CanvasRenderer() {
45814
45815 console.error( 'THREE.CanvasRenderer has been moved to /examples/js/renderers/CanvasRenderer.js' );
45816
45817 this.domElement = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
45818 this.clear = function () {};
45819 this.render = function () {};
45820 this.setClearColor = function () {};
45821 this.setSize = function () {};
45822
45823}
45824
45825//
45826
45827var SceneUtils = {
45828
45829 createMultiMaterialObject: function ( /* geometry, materials */ ) {
45830
45831 console.error( 'THREE.SceneUtils has been moved to /examples/js/utils/SceneUtils.js' );
45832
45833 },
45834
45835 detach: function ( /* child, parent, scene */ ) {
45836
45837 console.error( 'THREE.SceneUtils has been moved to /examples/js/utils/SceneUtils.js' );
45838
45839 },
45840
45841 attach: function ( /* child, scene, parent */ ) {
45842
45843 console.error( 'THREE.SceneUtils has been moved to /examples/js/utils/SceneUtils.js' );
45844
45845 }
45846
45847};
45848
45849//
45850
45851function LensFlare() {
45852
45853 console.error( 'THREE.LensFlare has been moved to /examples/js/objects/Lensflare.js' );
45854
45855}
45856
45857export { WebGLRenderTargetCube, WebGLRenderTarget, WebGLRenderer, ShaderLib, UniformsLib, UniformsUtils, ShaderChunk, FogExp2, Fog, Scene, Sprite, LOD, SkinnedMesh, Skeleton, Bone, Mesh, LineSegments, LineLoop, Line, Points, Group, VideoTexture, DataTexture, CompressedTexture, CubeTexture, CanvasTexture, DepthTexture, Texture, CompressedTextureLoader, DataTextureLoader, CubeTextureLoader, TextureLoader, ObjectLoader, MaterialLoader, BufferGeometryLoader, DefaultLoadingManager, LoadingManager, JSONLoader, ImageLoader, ImageBitmapLoader, FontLoader, FileLoader, Loader, LoaderUtils, Cache, AudioLoader, SpotLightShadow, SpotLight, PointLight, RectAreaLight, HemisphereLight, DirectionalLightShadow, DirectionalLight, AmbientLight, LightShadow, Light, StereoCamera, PerspectiveCamera, OrthographicCamera, CubeCamera, ArrayCamera, Camera, AudioListener, PositionalAudio, AudioContext, AudioAnalyser, Audio, VectorKeyframeTrack, StringKeyframeTrack, QuaternionKeyframeTrack, NumberKeyframeTrack, ColorKeyframeTrack, BooleanKeyframeTrack, PropertyMixer, PropertyBinding, KeyframeTrack, AnimationUtils, AnimationObjectGroup, AnimationMixer, AnimationClip, Uniform, InstancedBufferGeometry, BufferGeometry, Geometry, InterleavedBufferAttribute, InstancedInterleavedBuffer, InterleavedBuffer, InstancedBufferAttribute, Face3, Object3D, Raycaster, Layers, EventDispatcher, Clock, QuaternionLinearInterpolant, LinearInterpolant, DiscreteInterpolant, CubicInterpolant, Interpolant, Triangle, _Math as Math, Spherical, Cylindrical, Plane, Frustum, Sphere, Ray, Matrix4, Matrix3, Box3, Box2, Line3, Euler, Vector4, Vector3, Vector2, Quaternion, Color, ImmediateRenderObject, VertexNormalsHelper, SpotLightHelper, SkeletonHelper, PointLightHelper, RectAreaLightHelper, HemisphereLightHelper, GridHelper, PolarGridHelper, FaceNormalsHelper, DirectionalLightHelper, CameraHelper, BoxHelper, Box3Helper, PlaneHelper, ArrowHelper, AxesHelper, Shape, Path, ShapePath, Font, CurvePath, Curve, ShapeUtils, WebGLUtils, WireframeGeometry, ParametricGeometry, ParametricBufferGeometry, TetrahedronGeometry, TetrahedronBufferGeometry, OctahedronGeometry, OctahedronBufferGeometry, IcosahedronGeometry, IcosahedronBufferGeometry, DodecahedronGeometry, DodecahedronBufferGeometry, PolyhedronGeometry, PolyhedronBufferGeometry, TubeGeometry, TubeBufferGeometry, TorusKnotGeometry, TorusKnotBufferGeometry, TorusGeometry, TorusBufferGeometry, TextGeometry, TextBufferGeometry, SphereGeometry, SphereBufferGeometry, RingGeometry, RingBufferGeometry, PlaneGeometry, PlaneBufferGeometry, LatheGeometry, LatheBufferGeometry, ShapeGeometry, ShapeBufferGeometry, ExtrudeGeometry, ExtrudeBufferGeometry, EdgesGeometry, ConeGeometry, ConeBufferGeometry, CylinderGeometry, CylinderBufferGeometry, CircleGeometry, CircleBufferGeometry, BoxGeometry, BoxBufferGeometry, ShadowMaterial, SpriteMaterial, RawShaderMaterial, ShaderMaterial, PointsMaterial, MeshPhysicalMaterial, MeshStandardMaterial, MeshPhongMaterial, MeshToonMaterial, MeshNormalMaterial, MeshLambertMaterial, MeshDepthMaterial, MeshDistanceMaterial, MeshBasicMaterial, LineDashedMaterial, LineBasicMaterial, Material, Float64BufferAttribute, Float32BufferAttribute, Uint32BufferAttribute, Int32BufferAttribute, Uint16BufferAttribute, Int16BufferAttribute, Uint8ClampedBufferAttribute, Uint8BufferAttribute, Int8BufferAttribute, BufferAttribute, ArcCurve, CatmullRomCurve3, CubicBezierCurve, CubicBezierCurve3, EllipseCurve, LineCurve, LineCurve3, QuadraticBezierCurve, QuadraticBezierCurve3, SplineCurve, REVISION, MOUSE, CullFaceNone, CullFaceBack, CullFaceFront, CullFaceFrontBack, FrontFaceDirectionCW, FrontFaceDirectionCCW, BasicShadowMap, PCFShadowMap, PCFSoftShadowMap, FrontSide, BackSide, DoubleSide, FlatShading, SmoothShading, NoColors, FaceColors, VertexColors, NoBlending, NormalBlending, AdditiveBlending, SubtractiveBlending, MultiplyBlending, CustomBlending, AddEquation, SubtractEquation, ReverseSubtractEquation, MinEquation, MaxEquation, ZeroFactor, OneFactor, SrcColorFactor, OneMinusSrcColorFactor, SrcAlphaFactor, OneMinusSrcAlphaFactor, DstAlphaFactor, OneMinusDstAlphaFactor, DstColorFactor, OneMinusDstColorFactor, SrcAlphaSaturateFactor, NeverDepth, AlwaysDepth, LessDepth, LessEqualDepth, EqualDepth, GreaterEqualDepth, GreaterDepth, NotEqualDepth, MultiplyOperation, MixOperation, AddOperation, NoToneMapping, LinearToneMapping, ReinhardToneMapping, Uncharted2ToneMapping, CineonToneMapping, UVMapping, CubeReflectionMapping, CubeRefractionMapping, EquirectangularReflectionMapping, EquirectangularRefractionMapping, SphericalReflectionMapping, CubeUVReflectionMapping, CubeUVRefractionMapping, RepeatWrapping, ClampToEdgeWrapping, MirroredRepeatWrapping, NearestFilter, NearestMipMapNearestFilter, NearestMipMapLinearFilter, LinearFilter, LinearMipMapNearestFilter, LinearMipMapLinearFilter, UnsignedByteType, ByteType, ShortType, UnsignedShortType, IntType, UnsignedIntType, FloatType, HalfFloatType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedShort565Type, UnsignedInt248Type, AlphaFormat, RGBFormat, RGBAFormat, LuminanceFormat, LuminanceAlphaFormat, RGBEFormat, DepthFormat, DepthStencilFormat, RGB_S3TC_DXT1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGB_PVRTC_4BPPV1_Format, RGB_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_PVRTC_2BPPV1_Format, RGB_ETC1_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_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_10x10_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, LoopOnce, LoopRepeat, LoopPingPong, InterpolateDiscrete, InterpolateLinear, InterpolateSmooth, ZeroCurvatureEnding, ZeroSlopeEnding, WrapAroundEnding, TrianglesDrawMode, TriangleStripDrawMode, TriangleFanDrawMode, LinearEncoding, sRGBEncoding, GammaEncoding, RGBEEncoding, LogLuvEncoding, RGBM7Encoding, RGBM16Encoding, RGBDEncoding, BasicDepthPacking, RGBADepthPacking, BoxGeometry as CubeGeometry, Face4, LineStrip, LinePieces, MeshFaceMaterial, MultiMaterial, PointCloud, Particle, ParticleSystem, PointCloudMaterial, ParticleBasicMaterial, ParticleSystemMaterial, Vertex, DynamicBufferAttribute, Int8Attribute, Uint8Attribute, Uint8ClampedAttribute, Int16Attribute, Uint16Attribute, Int32Attribute, Uint32Attribute, Float32Attribute, Float64Attribute, ClosedSplineCurve3, SplineCurve3, Spline, AxisHelper, BoundingBoxHelper, EdgesHelper, WireframeHelper, XHRLoader, BinaryTextureLoader, GeometryUtils, ImageUtils, Projector, CanvasRenderer, SceneUtils, LensFlare };