UNPKG

1.08 MBJavaScriptView Raw
1(function (global, factory) {
2 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
3 typeof define === 'function' && define.amd ? define(['exports'], factory) :
4 (factory((global.THREE = {})));
5}(this, (function (exports) { 'use strict';
6
7 // Polyfills
8
9 if ( Number.EPSILON === undefined ) {
10
11 Number.EPSILON = Math.pow( 2, - 52 );
12
13 }
14
15 if ( Number.isInteger === undefined ) {
16
17 // Missing in IE
18 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger
19
20 Number.isInteger = function ( value ) {
21
22 return typeof value === 'number' && isFinite( value ) && Math.floor( value ) === value;
23
24 };
25
26 }
27
28 //
29
30 if ( Math.sign === undefined ) {
31
32 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign
33
34 Math.sign = function ( x ) {
35
36 return ( x < 0 ) ? - 1 : ( x > 0 ) ? 1 : + x;
37
38 };
39
40 }
41
42 if ( 'name' in Function.prototype === false ) {
43
44 // Missing in IE
45 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name
46
47 Object.defineProperty( Function.prototype, 'name', {
48
49 get: function () {
50
51 return this.toString().match( /^\s*function\s*([^\(\s]*)/ )[ 1 ];
52
53 }
54
55 } );
56
57 }
58
59 if ( Object.assign === undefined ) {
60
61 // Missing in IE
62 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
63
64 ( function () {
65
66 Object.assign = function ( target ) {
67
68 if ( target === undefined || target === null ) {
69
70 throw new TypeError( 'Cannot convert undefined or null to object' );
71
72 }
73
74 var output = Object( target );
75
76 for ( var index = 1; index < arguments.length; index ++ ) {
77
78 var source = arguments[ index ];
79
80 if ( source !== undefined && source !== null ) {
81
82 for ( var nextKey in source ) {
83
84 if ( Object.prototype.hasOwnProperty.call( source, nextKey ) ) {
85
86 output[ nextKey ] = source[ nextKey ];
87
88 }
89
90 }
91
92 }
93
94 }
95
96 return output;
97
98 };
99
100 } )();
101
102 }
103
104 /**
105 * https://github.com/mrdoob/eventdispatcher.js/
106 */
107
108 function EventDispatcher() {}
109
110 Object.assign( EventDispatcher.prototype, {
111
112 addEventListener: function ( type, listener ) {
113
114 if ( this._listeners === undefined ) this._listeners = {};
115
116 var listeners = this._listeners;
117
118 if ( listeners[ type ] === undefined ) {
119
120 listeners[ type ] = [];
121
122 }
123
124 if ( listeners[ type ].indexOf( listener ) === - 1 ) {
125
126 listeners[ type ].push( listener );
127
128 }
129
130 },
131
132 hasEventListener: function ( type, listener ) {
133
134 if ( this._listeners === undefined ) return false;
135
136 var listeners = this._listeners;
137
138 return listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1;
139
140 },
141
142 removeEventListener: function ( type, listener ) {
143
144 if ( this._listeners === undefined ) return;
145
146 var listeners = this._listeners;
147 var listenerArray = listeners[ type ];
148
149 if ( listenerArray !== undefined ) {
150
151 var index = listenerArray.indexOf( listener );
152
153 if ( index !== - 1 ) {
154
155 listenerArray.splice( index, 1 );
156
157 }
158
159 }
160
161 },
162
163 dispatchEvent: function ( event ) {
164
165 if ( this._listeners === undefined ) return;
166
167 var listeners = this._listeners;
168 var listenerArray = listeners[ event.type ];
169
170 if ( listenerArray !== undefined ) {
171
172 event.target = this;
173
174 var array = listenerArray.slice( 0 );
175
176 for ( var i = 0, l = array.length; i < l; i ++ ) {
177
178 array[ i ].call( this, event );
179
180 }
181
182 }
183
184 }
185
186 } );
187
188 var REVISION = '92';
189 var MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2 };
190 var CullFaceNone = 0;
191 var CullFaceBack = 1;
192 var CullFaceFront = 2;
193 var CullFaceFrontBack = 3;
194 var FrontFaceDirectionCW = 0;
195 var FrontFaceDirectionCCW = 1;
196 var BasicShadowMap = 0;
197 var PCFShadowMap = 1;
198 var PCFSoftShadowMap = 2;
199 var FrontSide = 0;
200 var BackSide = 1;
201 var DoubleSide = 2;
202 var FlatShading = 1;
203 var SmoothShading = 2;
204 var NoColors = 0;
205 var FaceColors = 1;
206 var VertexColors = 2;
207 var NoBlending = 0;
208 var NormalBlending = 1;
209 var AdditiveBlending = 2;
210 var SubtractiveBlending = 3;
211 var MultiplyBlending = 4;
212 var CustomBlending = 5;
213 var AddEquation = 100;
214 var SubtractEquation = 101;
215 var ReverseSubtractEquation = 102;
216 var MinEquation = 103;
217 var MaxEquation = 104;
218 var ZeroFactor = 200;
219 var OneFactor = 201;
220 var SrcColorFactor = 202;
221 var OneMinusSrcColorFactor = 203;
222 var SrcAlphaFactor = 204;
223 var OneMinusSrcAlphaFactor = 205;
224 var DstAlphaFactor = 206;
225 var OneMinusDstAlphaFactor = 207;
226 var DstColorFactor = 208;
227 var OneMinusDstColorFactor = 209;
228 var SrcAlphaSaturateFactor = 210;
229 var NeverDepth = 0;
230 var AlwaysDepth = 1;
231 var LessDepth = 2;
232 var LessEqualDepth = 3;
233 var EqualDepth = 4;
234 var GreaterEqualDepth = 5;
235 var GreaterDepth = 6;
236 var NotEqualDepth = 7;
237 var MultiplyOperation = 0;
238 var MixOperation = 1;
239 var AddOperation = 2;
240 var NoToneMapping = 0;
241 var LinearToneMapping = 1;
242 var ReinhardToneMapping = 2;
243 var Uncharted2ToneMapping = 3;
244 var CineonToneMapping = 4;
245 var UVMapping = 300;
246 var CubeReflectionMapping = 301;
247 var CubeRefractionMapping = 302;
248 var EquirectangularReflectionMapping = 303;
249 var EquirectangularRefractionMapping = 304;
250 var SphericalReflectionMapping = 305;
251 var CubeUVReflectionMapping = 306;
252 var CubeUVRefractionMapping = 307;
253 var RepeatWrapping = 1000;
254 var ClampToEdgeWrapping = 1001;
255 var MirroredRepeatWrapping = 1002;
256 var NearestFilter = 1003;
257 var NearestMipMapNearestFilter = 1004;
258 var NearestMipMapLinearFilter = 1005;
259 var LinearFilter = 1006;
260 var LinearMipMapNearestFilter = 1007;
261 var LinearMipMapLinearFilter = 1008;
262 var UnsignedByteType = 1009;
263 var ByteType = 1010;
264 var ShortType = 1011;
265 var UnsignedShortType = 1012;
266 var IntType = 1013;
267 var UnsignedIntType = 1014;
268 var FloatType = 1015;
269 var HalfFloatType = 1016;
270 var UnsignedShort4444Type = 1017;
271 var UnsignedShort5551Type = 1018;
272 var UnsignedShort565Type = 1019;
273 var UnsignedInt248Type = 1020;
274 var AlphaFormat = 1021;
275 var RGBFormat = 1022;
276 var RGBAFormat = 1023;
277 var LuminanceFormat = 1024;
278 var LuminanceAlphaFormat = 1025;
279 var RGBEFormat = RGBAFormat;
280 var DepthFormat = 1026;
281 var DepthStencilFormat = 1027;
282 var RGB_S3TC_DXT1_Format = 33776;
283 var RGBA_S3TC_DXT1_Format = 33777;
284 var RGBA_S3TC_DXT3_Format = 33778;
285 var RGBA_S3TC_DXT5_Format = 33779;
286 var RGB_PVRTC_4BPPV1_Format = 35840;
287 var RGB_PVRTC_2BPPV1_Format = 35841;
288 var RGBA_PVRTC_4BPPV1_Format = 35842;
289 var RGBA_PVRTC_2BPPV1_Format = 35843;
290 var RGB_ETC1_Format = 36196;
291 var RGBA_ASTC_4x4_Format = 37808;
292 var RGBA_ASTC_5x4_Format = 37809;
293 var RGBA_ASTC_5x5_Format = 37810;
294 var RGBA_ASTC_6x5_Format = 37811;
295 var RGBA_ASTC_6x6_Format = 37812;
296 var RGBA_ASTC_8x5_Format = 37813;
297 var RGBA_ASTC_8x6_Format = 37814;
298 var RGBA_ASTC_8x8_Format = 37815;
299 var RGBA_ASTC_10x5_Format = 37816;
300 var RGBA_ASTC_10x6_Format = 37817;
301 var RGBA_ASTC_10x8_Format = 37818;
302 var RGBA_ASTC_10x10_Format = 37819;
303 var RGBA_ASTC_12x10_Format = 37820;
304 var RGBA_ASTC_12x12_Format = 37821;
305 var LoopOnce = 2200;
306 var LoopRepeat = 2201;
307 var LoopPingPong = 2202;
308 var InterpolateDiscrete = 2300;
309 var InterpolateLinear = 2301;
310 var InterpolateSmooth = 2302;
311 var ZeroCurvatureEnding = 2400;
312 var ZeroSlopeEnding = 2401;
313 var WrapAroundEnding = 2402;
314 var TrianglesDrawMode = 0;
315 var TriangleStripDrawMode = 1;
316 var TriangleFanDrawMode = 2;
317 var LinearEncoding = 3000;
318 var sRGBEncoding = 3001;
319 var GammaEncoding = 3007;
320 var RGBEEncoding = 3002;
321 var LogLuvEncoding = 3003;
322 var RGBM7Encoding = 3004;
323 var RGBM16Encoding = 3005;
324 var RGBDEncoding = 3006;
325 var BasicDepthPacking = 3200;
326 var RGBADepthPacking = 3201;
327
328 /**
329 * @author alteredq / http://alteredqualia.com/
330 * @author mrdoob / http://mrdoob.com/
331 */
332
333 var _Math = {
334
335 DEG2RAD: Math.PI / 180,
336 RAD2DEG: 180 / Math.PI,
337
338 generateUUID: ( function () {
339
340 // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136
341
342 var lut = [];
343
344 for ( var i = 0; i < 256; i ++ ) {
345
346 lut[ i ] = ( i < 16 ? '0' : '' ) + ( i ).toString( 16 );
347
348 }
349
350 return function generateUUID() {
351
352 var d0 = Math.random() * 0xffffffff | 0;
353 var d1 = Math.random() * 0xffffffff | 0;
354 var d2 = Math.random() * 0xffffffff | 0;
355 var d3 = Math.random() * 0xffffffff | 0;
356 var uuid = lut[ d0 & 0xff ] + lut[ d0 >> 8 & 0xff ] + lut[ d0 >> 16 & 0xff ] + lut[ d0 >> 24 & 0xff ] + '-' +
357 lut[ d1 & 0xff ] + lut[ d1 >> 8 & 0xff ] + '-' + lut[ d1 >> 16 & 0x0f | 0x40 ] + lut[ d1 >> 24 & 0xff ] + '-' +
358 lut[ d2 & 0x3f | 0x80 ] + lut[ d2 >> 8 & 0xff ] + '-' + lut[ d2 >> 16 & 0xff ] + lut[ d2 >> 24 & 0xff ] +
359 lut[ d3 & 0xff ] + lut[ d3 >> 8 & 0xff ] + lut[ d3 >> 16 & 0xff ] + lut[ d3 >> 24 & 0xff ];
360
361 // .toUpperCase() here flattens concatenated strings to save heap memory space.
362 return uuid.toUpperCase();
363
364 };
365
366 } )(),
367
368 clamp: function ( value, min, max ) {
369
370 return Math.max( min, Math.min( max, value ) );
371
372 },
373
374 // compute euclidian modulo of m % n
375 // https://en.wikipedia.org/wiki/Modulo_operation
376
377 euclideanModulo: function ( n, m ) {
378
379 return ( ( n % m ) + m ) % m;
380
381 },
382
383 // Linear mapping from range <a1, a2> to range <b1, b2>
384
385 mapLinear: function ( x, a1, a2, b1, b2 ) {
386
387 return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 );
388
389 },
390
391 // https://en.wikipedia.org/wiki/Linear_interpolation
392
393 lerp: function ( x, y, t ) {
394
395 return ( 1 - t ) * x + t * y;
396
397 },
398
399 // http://en.wikipedia.org/wiki/Smoothstep
400
401 smoothstep: function ( x, min, max ) {
402
403 if ( x <= min ) return 0;
404 if ( x >= max ) return 1;
405
406 x = ( x - min ) / ( max - min );
407
408 return x * x * ( 3 - 2 * x );
409
410 },
411
412 smootherstep: function ( x, min, max ) {
413
414 if ( x <= min ) return 0;
415 if ( x >= max ) return 1;
416
417 x = ( x - min ) / ( max - min );
418
419 return x * x * x * ( x * ( x * 6 - 15 ) + 10 );
420
421 },
422
423 // Random integer from <low, high> interval
424
425 randInt: function ( low, high ) {
426
427 return low + Math.floor( Math.random() * ( high - low + 1 ) );
428
429 },
430
431 // Random float from <low, high> interval
432
433 randFloat: function ( low, high ) {
434
435 return low + Math.random() * ( high - low );
436
437 },
438
439 // Random float from <-range/2, range/2> interval
440
441 randFloatSpread: function ( range ) {
442
443 return range * ( 0.5 - Math.random() );
444
445 },
446
447 degToRad: function ( degrees ) {
448
449 return degrees * _Math.DEG2RAD;
450
451 },
452
453 radToDeg: function ( radians ) {
454
455 return radians * _Math.RAD2DEG;
456
457 },
458
459 isPowerOfTwo: function ( value ) {
460
461 return ( value & ( value - 1 ) ) === 0 && value !== 0;
462
463 },
464
465 ceilPowerOfTwo: function ( value ) {
466
467 return Math.pow( 2, Math.ceil( Math.log( value ) / Math.LN2 ) );
468
469 },
470
471 floorPowerOfTwo: function ( value ) {
472
473 return Math.pow( 2, Math.floor( Math.log( value ) / Math.LN2 ) );
474
475 }
476
477 };
478
479 /**
480 * @author mrdoob / http://mrdoob.com/
481 * @author philogb / http://blog.thejit.org/
482 * @author egraether / http://egraether.com/
483 * @author zz85 / http://www.lab4games.net/zz85/blog
484 */
485
486 function Vector2( x, y ) {
487
488 this.x = x || 0;
489 this.y = y || 0;
490
491 }
492
493 Object.defineProperties( Vector2.prototype, {
494
495 "width": {
496
497 get: function () {
498
499 return this.x;
500
501 },
502
503 set: function ( value ) {
504
505 this.x = value;
506
507 }
508
509 },
510
511 "height": {
512
513 get: function () {
514
515 return this.y;
516
517 },
518
519 set: function ( value ) {
520
521 this.y = value;
522
523 }
524
525 }
526
527 } );
528
529 Object.assign( Vector2.prototype, {
530
531 isVector2: true,
532
533 set: function ( x, y ) {
534
535 this.x = x;
536 this.y = y;
537
538 return this;
539
540 },
541
542 setScalar: function ( scalar ) {
543
544 this.x = scalar;
545 this.y = scalar;
546
547 return this;
548
549 },
550
551 setX: function ( x ) {
552
553 this.x = x;
554
555 return this;
556
557 },
558
559 setY: function ( y ) {
560
561 this.y = y;
562
563 return this;
564
565 },
566
567 setComponent: function ( index, value ) {
568
569 switch ( index ) {
570
571 case 0: this.x = value; break;
572 case 1: this.y = value; break;
573 default: throw new Error( 'index is out of range: ' + index );
574
575 }
576
577 return this;
578
579 },
580
581 getComponent: function ( index ) {
582
583 switch ( index ) {
584
585 case 0: return this.x;
586 case 1: return this.y;
587 default: throw new Error( 'index is out of range: ' + index );
588
589 }
590
591 },
592
593 clone: function () {
594
595 return new this.constructor( this.x, this.y );
596
597 },
598
599 copy: function ( v ) {
600
601 this.x = v.x;
602 this.y = v.y;
603
604 return this;
605
606 },
607
608 add: function ( v, w ) {
609
610 if ( w !== undefined ) {
611
612 console.warn( 'THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
613 return this.addVectors( v, w );
614
615 }
616
617 this.x += v.x;
618 this.y += v.y;
619
620 return this;
621
622 },
623
624 addScalar: function ( s ) {
625
626 this.x += s;
627 this.y += s;
628
629 return this;
630
631 },
632
633 addVectors: function ( a, b ) {
634
635 this.x = a.x + b.x;
636 this.y = a.y + b.y;
637
638 return this;
639
640 },
641
642 addScaledVector: function ( v, s ) {
643
644 this.x += v.x * s;
645 this.y += v.y * s;
646
647 return this;
648
649 },
650
651 sub: function ( v, w ) {
652
653 if ( w !== undefined ) {
654
655 console.warn( 'THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
656 return this.subVectors( v, w );
657
658 }
659
660 this.x -= v.x;
661 this.y -= v.y;
662
663 return this;
664
665 },
666
667 subScalar: function ( s ) {
668
669 this.x -= s;
670 this.y -= s;
671
672 return this;
673
674 },
675
676 subVectors: function ( a, b ) {
677
678 this.x = a.x - b.x;
679 this.y = a.y - b.y;
680
681 return this;
682
683 },
684
685 multiply: function ( v ) {
686
687 this.x *= v.x;
688 this.y *= v.y;
689
690 return this;
691
692 },
693
694 multiplyScalar: function ( scalar ) {
695
696 this.x *= scalar;
697 this.y *= scalar;
698
699 return this;
700
701 },
702
703 divide: function ( v ) {
704
705 this.x /= v.x;
706 this.y /= v.y;
707
708 return this;
709
710 },
711
712 divideScalar: function ( scalar ) {
713
714 return this.multiplyScalar( 1 / scalar );
715
716 },
717
718 applyMatrix3: function ( m ) {
719
720 var x = this.x, y = this.y;
721 var e = m.elements;
722
723 this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ];
724 this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ];
725
726 return this;
727
728 },
729
730 min: function ( v ) {
731
732 this.x = Math.min( this.x, v.x );
733 this.y = Math.min( this.y, v.y );
734
735 return this;
736
737 },
738
739 max: function ( v ) {
740
741 this.x = Math.max( this.x, v.x );
742 this.y = Math.max( this.y, v.y );
743
744 return this;
745
746 },
747
748 clamp: function ( min, max ) {
749
750 // assumes min < max, componentwise
751
752 this.x = Math.max( min.x, Math.min( max.x, this.x ) );
753 this.y = Math.max( min.y, Math.min( max.y, this.y ) );
754
755 return this;
756
757 },
758
759 clampScalar: function () {
760
761 var min = new Vector2();
762 var max = new Vector2();
763
764 return function clampScalar( minVal, maxVal ) {
765
766 min.set( minVal, minVal );
767 max.set( maxVal, maxVal );
768
769 return this.clamp( min, max );
770
771 };
772
773 }(),
774
775 clampLength: function ( min, max ) {
776
777 var length = this.length();
778
779 return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
780
781 },
782
783 floor: function () {
784
785 this.x = Math.floor( this.x );
786 this.y = Math.floor( this.y );
787
788 return this;
789
790 },
791
792 ceil: function () {
793
794 this.x = Math.ceil( this.x );
795 this.y = Math.ceil( this.y );
796
797 return this;
798
799 },
800
801 round: function () {
802
803 this.x = Math.round( this.x );
804 this.y = Math.round( this.y );
805
806 return this;
807
808 },
809
810 roundToZero: function () {
811
812 this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
813 this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
814
815 return this;
816
817 },
818
819 negate: function () {
820
821 this.x = - this.x;
822 this.y = - this.y;
823
824 return this;
825
826 },
827
828 dot: function ( v ) {
829
830 return this.x * v.x + this.y * v.y;
831
832 },
833
834 lengthSq: function () {
835
836 return this.x * this.x + this.y * this.y;
837
838 },
839
840 length: function () {
841
842 return Math.sqrt( this.x * this.x + this.y * this.y );
843
844 },
845
846 manhattanLength: function () {
847
848 return Math.abs( this.x ) + Math.abs( this.y );
849
850 },
851
852 normalize: function () {
853
854 return this.divideScalar( this.length() || 1 );
855
856 },
857
858 angle: function () {
859
860 // computes the angle in radians with respect to the positive x-axis
861
862 var angle = Math.atan2( this.y, this.x );
863
864 if ( angle < 0 ) angle += 2 * Math.PI;
865
866 return angle;
867
868 },
869
870 distanceTo: function ( v ) {
871
872 return Math.sqrt( this.distanceToSquared( v ) );
873
874 },
875
876 distanceToSquared: function ( v ) {
877
878 var dx = this.x - v.x, dy = this.y - v.y;
879 return dx * dx + dy * dy;
880
881 },
882
883 manhattanDistanceTo: function ( v ) {
884
885 return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y );
886
887 },
888
889 setLength: function ( length ) {
890
891 return this.normalize().multiplyScalar( length );
892
893 },
894
895 lerp: function ( v, alpha ) {
896
897 this.x += ( v.x - this.x ) * alpha;
898 this.y += ( v.y - this.y ) * alpha;
899
900 return this;
901
902 },
903
904 lerpVectors: function ( v1, v2, alpha ) {
905
906 return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );
907
908 },
909
910 equals: function ( v ) {
911
912 return ( ( v.x === this.x ) && ( v.y === this.y ) );
913
914 },
915
916 fromArray: function ( array, offset ) {
917
918 if ( offset === undefined ) offset = 0;
919
920 this.x = array[ offset ];
921 this.y = array[ offset + 1 ];
922
923 return this;
924
925 },
926
927 toArray: function ( array, offset ) {
928
929 if ( array === undefined ) array = [];
930 if ( offset === undefined ) offset = 0;
931
932 array[ offset ] = this.x;
933 array[ offset + 1 ] = this.y;
934
935 return array;
936
937 },
938
939 fromBufferAttribute: function ( attribute, index, offset ) {
940
941 if ( offset !== undefined ) {
942
943 console.warn( 'THREE.Vector2: offset has been removed from .fromBufferAttribute().' );
944
945 }
946
947 this.x = attribute.getX( index );
948 this.y = attribute.getY( index );
949
950 return this;
951
952 },
953
954 rotateAround: function ( center, angle ) {
955
956 var c = Math.cos( angle ), s = Math.sin( angle );
957
958 var x = this.x - center.x;
959 var y = this.y - center.y;
960
961 this.x = x * c - y * s + center.x;
962 this.y = x * s + y * c + center.y;
963
964 return this;
965
966 }
967
968 } );
969
970 /**
971 * @author mrdoob / http://mrdoob.com/
972 * @author supereggbert / http://www.paulbrunt.co.uk/
973 * @author philogb / http://blog.thejit.org/
974 * @author jordi_ros / http://plattsoft.com
975 * @author D1plo1d / http://github.com/D1plo1d
976 * @author alteredq / http://alteredqualia.com/
977 * @author mikael emtinger / http://gomo.se/
978 * @author timknip / http://www.floorplanner.com/
979 * @author bhouston / http://clara.io
980 * @author WestLangley / http://github.com/WestLangley
981 */
982
983 function Matrix4() {
984
985 this.elements = [
986
987 1, 0, 0, 0,
988 0, 1, 0, 0,
989 0, 0, 1, 0,
990 0, 0, 0, 1
991
992 ];
993
994 if ( arguments.length > 0 ) {
995
996 console.error( 'THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.' );
997
998 }
999
1000 }
1001
1002 Object.assign( Matrix4.prototype, {
1003
1004 isMatrix4: true,
1005
1006 set: function ( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
1007
1008 var te = this.elements;
1009
1010 te[ 0 ] = n11; te[ 4 ] = n12; te[ 8 ] = n13; te[ 12 ] = n14;
1011 te[ 1 ] = n21; te[ 5 ] = n22; te[ 9 ] = n23; te[ 13 ] = n24;
1012 te[ 2 ] = n31; te[ 6 ] = n32; te[ 10 ] = n33; te[ 14 ] = n34;
1013 te[ 3 ] = n41; te[ 7 ] = n42; te[ 11 ] = n43; te[ 15 ] = n44;
1014
1015 return this;
1016
1017 },
1018
1019 identity: function () {
1020
1021 this.set(
1022
1023 1, 0, 0, 0,
1024 0, 1, 0, 0,
1025 0, 0, 1, 0,
1026 0, 0, 0, 1
1027
1028 );
1029
1030 return this;
1031
1032 },
1033
1034 clone: function () {
1035
1036 return new Matrix4().fromArray( this.elements );
1037
1038 },
1039
1040 copy: function ( m ) {
1041
1042 var te = this.elements;
1043 var me = m.elements;
1044
1045 te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ]; te[ 3 ] = me[ 3 ];
1046 te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ]; te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ];
1047 te[ 8 ] = me[ 8 ]; te[ 9 ] = me[ 9 ]; te[ 10 ] = me[ 10 ]; te[ 11 ] = me[ 11 ];
1048 te[ 12 ] = me[ 12 ]; te[ 13 ] = me[ 13 ]; te[ 14 ] = me[ 14 ]; te[ 15 ] = me[ 15 ];
1049
1050 return this;
1051
1052 },
1053
1054 copyPosition: function ( m ) {
1055
1056 var te = this.elements, me = m.elements;
1057
1058 te[ 12 ] = me[ 12 ];
1059 te[ 13 ] = me[ 13 ];
1060 te[ 14 ] = me[ 14 ];
1061
1062 return this;
1063
1064 },
1065
1066 extractBasis: function ( xAxis, yAxis, zAxis ) {
1067
1068 xAxis.setFromMatrixColumn( this, 0 );
1069 yAxis.setFromMatrixColumn( this, 1 );
1070 zAxis.setFromMatrixColumn( this, 2 );
1071
1072 return this;
1073
1074 },
1075
1076 makeBasis: function ( xAxis, yAxis, zAxis ) {
1077
1078 this.set(
1079 xAxis.x, yAxis.x, zAxis.x, 0,
1080 xAxis.y, yAxis.y, zAxis.y, 0,
1081 xAxis.z, yAxis.z, zAxis.z, 0,
1082 0, 0, 0, 1
1083 );
1084
1085 return this;
1086
1087 },
1088
1089 extractRotation: function () {
1090
1091 var v1 = new Vector3();
1092
1093 return function extractRotation( m ) {
1094
1095 var te = this.elements;
1096 var me = m.elements;
1097
1098 var scaleX = 1 / v1.setFromMatrixColumn( m, 0 ).length();
1099 var scaleY = 1 / v1.setFromMatrixColumn( m, 1 ).length();
1100 var scaleZ = 1 / v1.setFromMatrixColumn( m, 2 ).length();
1101
1102 te[ 0 ] = me[ 0 ] * scaleX;
1103 te[ 1 ] = me[ 1 ] * scaleX;
1104 te[ 2 ] = me[ 2 ] * scaleX;
1105
1106 te[ 4 ] = me[ 4 ] * scaleY;
1107 te[ 5 ] = me[ 5 ] * scaleY;
1108 te[ 6 ] = me[ 6 ] * scaleY;
1109
1110 te[ 8 ] = me[ 8 ] * scaleZ;
1111 te[ 9 ] = me[ 9 ] * scaleZ;
1112 te[ 10 ] = me[ 10 ] * scaleZ;
1113
1114 return this;
1115
1116 };
1117
1118 }(),
1119
1120 makeRotationFromEuler: function ( euler ) {
1121
1122 if ( ! ( euler && euler.isEuler ) ) {
1123
1124 console.error( 'THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.' );
1125
1126 }
1127
1128 var te = this.elements;
1129
1130 var x = euler.x, y = euler.y, z = euler.z;
1131 var a = Math.cos( x ), b = Math.sin( x );
1132 var c = Math.cos( y ), d = Math.sin( y );
1133 var e = Math.cos( z ), f = Math.sin( z );
1134
1135 if ( euler.order === 'XYZ' ) {
1136
1137 var ae = a * e, af = a * f, be = b * e, bf = b * f;
1138
1139 te[ 0 ] = c * e;
1140 te[ 4 ] = - c * f;
1141 te[ 8 ] = d;
1142
1143 te[ 1 ] = af + be * d;
1144 te[ 5 ] = ae - bf * d;
1145 te[ 9 ] = - b * c;
1146
1147 te[ 2 ] = bf - ae * d;
1148 te[ 6 ] = be + af * d;
1149 te[ 10 ] = a * c;
1150
1151 } else if ( euler.order === 'YXZ' ) {
1152
1153 var ce = c * e, cf = c * f, de = d * e, df = d * f;
1154
1155 te[ 0 ] = ce + df * b;
1156 te[ 4 ] = de * b - cf;
1157 te[ 8 ] = a * d;
1158
1159 te[ 1 ] = a * f;
1160 te[ 5 ] = a * e;
1161 te[ 9 ] = - b;
1162
1163 te[ 2 ] = cf * b - de;
1164 te[ 6 ] = df + ce * b;
1165 te[ 10 ] = a * c;
1166
1167 } else if ( euler.order === 'ZXY' ) {
1168
1169 var ce = c * e, cf = c * f, de = d * e, df = d * f;
1170
1171 te[ 0 ] = ce - df * b;
1172 te[ 4 ] = - a * f;
1173 te[ 8 ] = de + cf * b;
1174
1175 te[ 1 ] = cf + de * b;
1176 te[ 5 ] = a * e;
1177 te[ 9 ] = df - ce * b;
1178
1179 te[ 2 ] = - a * d;
1180 te[ 6 ] = b;
1181 te[ 10 ] = a * c;
1182
1183 } else if ( euler.order === 'ZYX' ) {
1184
1185 var ae = a * e, af = a * f, be = b * e, bf = b * f;
1186
1187 te[ 0 ] = c * e;
1188 te[ 4 ] = be * d - af;
1189 te[ 8 ] = ae * d + bf;
1190
1191 te[ 1 ] = c * f;
1192 te[ 5 ] = bf * d + ae;
1193 te[ 9 ] = af * d - be;
1194
1195 te[ 2 ] = - d;
1196 te[ 6 ] = b * c;
1197 te[ 10 ] = a * c;
1198
1199 } else if ( euler.order === 'YZX' ) {
1200
1201 var ac = a * c, ad = a * d, bc = b * c, bd = b * d;
1202
1203 te[ 0 ] = c * e;
1204 te[ 4 ] = bd - ac * f;
1205 te[ 8 ] = bc * f + ad;
1206
1207 te[ 1 ] = f;
1208 te[ 5 ] = a * e;
1209 te[ 9 ] = - b * e;
1210
1211 te[ 2 ] = - d * e;
1212 te[ 6 ] = ad * f + bc;
1213 te[ 10 ] = ac - bd * f;
1214
1215 } else if ( euler.order === 'XZY' ) {
1216
1217 var ac = a * c, ad = a * d, bc = b * c, bd = b * d;
1218
1219 te[ 0 ] = c * e;
1220 te[ 4 ] = - f;
1221 te[ 8 ] = d * e;
1222
1223 te[ 1 ] = ac * f + bd;
1224 te[ 5 ] = a * e;
1225 te[ 9 ] = ad * f - bc;
1226
1227 te[ 2 ] = bc * f - ad;
1228 te[ 6 ] = b * e;
1229 te[ 10 ] = bd * f + ac;
1230
1231 }
1232
1233 // last column
1234 te[ 3 ] = 0;
1235 te[ 7 ] = 0;
1236 te[ 11 ] = 0;
1237
1238 // bottom row
1239 te[ 12 ] = 0;
1240 te[ 13 ] = 0;
1241 te[ 14 ] = 0;
1242 te[ 15 ] = 1;
1243
1244 return this;
1245
1246 },
1247
1248 makeRotationFromQuaternion: function ( q ) {
1249
1250 var te = this.elements;
1251
1252 var x = q._x, y = q._y, z = q._z, w = q._w;
1253 var x2 = x + x, y2 = y + y, z2 = z + z;
1254 var xx = x * x2, xy = x * y2, xz = x * z2;
1255 var yy = y * y2, yz = y * z2, zz = z * z2;
1256 var wx = w * x2, wy = w * y2, wz = w * z2;
1257
1258 te[ 0 ] = 1 - ( yy + zz );
1259 te[ 4 ] = xy - wz;
1260 te[ 8 ] = xz + wy;
1261
1262 te[ 1 ] = xy + wz;
1263 te[ 5 ] = 1 - ( xx + zz );
1264 te[ 9 ] = yz - wx;
1265
1266 te[ 2 ] = xz - wy;
1267 te[ 6 ] = yz + wx;
1268 te[ 10 ] = 1 - ( xx + yy );
1269
1270 // last column
1271 te[ 3 ] = 0;
1272 te[ 7 ] = 0;
1273 te[ 11 ] = 0;
1274
1275 // bottom row
1276 te[ 12 ] = 0;
1277 te[ 13 ] = 0;
1278 te[ 14 ] = 0;
1279 te[ 15 ] = 1;
1280
1281 return this;
1282
1283 },
1284
1285 lookAt: function () {
1286
1287 var x = new Vector3();
1288 var y = new Vector3();
1289 var z = new Vector3();
1290
1291 return function lookAt( eye, target, up ) {
1292
1293 var te = this.elements;
1294
1295 z.subVectors( eye, target );
1296
1297 if ( z.lengthSq() === 0 ) {
1298
1299 // eye and target are in the same position
1300
1301 z.z = 1;
1302
1303 }
1304
1305 z.normalize();
1306 x.crossVectors( up, z );
1307
1308 if ( x.lengthSq() === 0 ) {
1309
1310 // up and z are parallel
1311
1312 if ( Math.abs( up.z ) === 1 ) {
1313
1314 z.x += 0.0001;
1315
1316 } else {
1317
1318 z.z += 0.0001;
1319
1320 }
1321
1322 z.normalize();
1323 x.crossVectors( up, z );
1324
1325 }
1326
1327 x.normalize();
1328 y.crossVectors( z, x );
1329
1330 te[ 0 ] = x.x; te[ 4 ] = y.x; te[ 8 ] = z.x;
1331 te[ 1 ] = x.y; te[ 5 ] = y.y; te[ 9 ] = z.y;
1332 te[ 2 ] = x.z; te[ 6 ] = y.z; te[ 10 ] = z.z;
1333
1334 return this;
1335
1336 };
1337
1338 }(),
1339
1340 multiply: function ( m, n ) {
1341
1342 if ( n !== undefined ) {
1343
1344 console.warn( 'THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead.' );
1345 return this.multiplyMatrices( m, n );
1346
1347 }
1348
1349 return this.multiplyMatrices( this, m );
1350
1351 },
1352
1353 premultiply: function ( m ) {
1354
1355 return this.multiplyMatrices( m, this );
1356
1357 },
1358
1359 multiplyMatrices: function ( a, b ) {
1360
1361 var ae = a.elements;
1362 var be = b.elements;
1363 var te = this.elements;
1364
1365 var a11 = ae[ 0 ], a12 = ae[ 4 ], a13 = ae[ 8 ], a14 = ae[ 12 ];
1366 var a21 = ae[ 1 ], a22 = ae[ 5 ], a23 = ae[ 9 ], a24 = ae[ 13 ];
1367 var a31 = ae[ 2 ], a32 = ae[ 6 ], a33 = ae[ 10 ], a34 = ae[ 14 ];
1368 var a41 = ae[ 3 ], a42 = ae[ 7 ], a43 = ae[ 11 ], a44 = ae[ 15 ];
1369
1370 var b11 = be[ 0 ], b12 = be[ 4 ], b13 = be[ 8 ], b14 = be[ 12 ];
1371 var b21 = be[ 1 ], b22 = be[ 5 ], b23 = be[ 9 ], b24 = be[ 13 ];
1372 var b31 = be[ 2 ], b32 = be[ 6 ], b33 = be[ 10 ], b34 = be[ 14 ];
1373 var b41 = be[ 3 ], b42 = be[ 7 ], b43 = be[ 11 ], b44 = be[ 15 ];
1374
1375 te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
1376 te[ 4 ] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
1377 te[ 8 ] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
1378 te[ 12 ] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
1379
1380 te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
1381 te[ 5 ] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
1382 te[ 9 ] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
1383 te[ 13 ] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
1384
1385 te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
1386 te[ 6 ] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
1387 te[ 10 ] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
1388 te[ 14 ] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
1389
1390 te[ 3 ] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
1391 te[ 7 ] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
1392 te[ 11 ] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
1393 te[ 15 ] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
1394
1395 return this;
1396
1397 },
1398
1399 multiplyScalar: function ( s ) {
1400
1401 var te = this.elements;
1402
1403 te[ 0 ] *= s; te[ 4 ] *= s; te[ 8 ] *= s; te[ 12 ] *= s;
1404 te[ 1 ] *= s; te[ 5 ] *= s; te[ 9 ] *= s; te[ 13 ] *= s;
1405 te[ 2 ] *= s; te[ 6 ] *= s; te[ 10 ] *= s; te[ 14 ] *= s;
1406 te[ 3 ] *= s; te[ 7 ] *= s; te[ 11 ] *= s; te[ 15 ] *= s;
1407
1408 return this;
1409
1410 },
1411
1412 applyToBufferAttribute: function () {
1413
1414 var v1 = new Vector3();
1415
1416 return function applyToBufferAttribute( attribute ) {
1417
1418 for ( var i = 0, l = attribute.count; i < l; i ++ ) {
1419
1420 v1.x = attribute.getX( i );
1421 v1.y = attribute.getY( i );
1422 v1.z = attribute.getZ( i );
1423
1424 v1.applyMatrix4( this );
1425
1426 attribute.setXYZ( i, v1.x, v1.y, v1.z );
1427
1428 }
1429
1430 return attribute;
1431
1432 };
1433
1434 }(),
1435
1436 determinant: function () {
1437
1438 var te = this.elements;
1439
1440 var n11 = te[ 0 ], n12 = te[ 4 ], n13 = te[ 8 ], n14 = te[ 12 ];
1441 var n21 = te[ 1 ], n22 = te[ 5 ], n23 = te[ 9 ], n24 = te[ 13 ];
1442 var n31 = te[ 2 ], n32 = te[ 6 ], n33 = te[ 10 ], n34 = te[ 14 ];
1443 var n41 = te[ 3 ], n42 = te[ 7 ], n43 = te[ 11 ], n44 = te[ 15 ];
1444
1445 //TODO: make this more efficient
1446 //( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm )
1447
1448 return (
1449 n41 * (
1450 + n14 * n23 * n32
1451 - n13 * n24 * n32
1452 - n14 * n22 * n33
1453 + n12 * n24 * n33
1454 + n13 * n22 * n34
1455 - n12 * n23 * n34
1456 ) +
1457 n42 * (
1458 + n11 * n23 * n34
1459 - n11 * n24 * n33
1460 + n14 * n21 * n33
1461 - n13 * n21 * n34
1462 + n13 * n24 * n31
1463 - n14 * n23 * n31
1464 ) +
1465 n43 * (
1466 + n11 * n24 * n32
1467 - n11 * n22 * n34
1468 - n14 * n21 * n32
1469 + n12 * n21 * n34
1470 + n14 * n22 * n31
1471 - n12 * n24 * n31
1472 ) +
1473 n44 * (
1474 - n13 * n22 * n31
1475 - n11 * n23 * n32
1476 + n11 * n22 * n33
1477 + n13 * n21 * n32
1478 - n12 * n21 * n33
1479 + n12 * n23 * n31
1480 )
1481
1482 );
1483
1484 },
1485
1486 transpose: function () {
1487
1488 var te = this.elements;
1489 var tmp;
1490
1491 tmp = te[ 1 ]; te[ 1 ] = te[ 4 ]; te[ 4 ] = tmp;
1492 tmp = te[ 2 ]; te[ 2 ] = te[ 8 ]; te[ 8 ] = tmp;
1493 tmp = te[ 6 ]; te[ 6 ] = te[ 9 ]; te[ 9 ] = tmp;
1494
1495 tmp = te[ 3 ]; te[ 3 ] = te[ 12 ]; te[ 12 ] = tmp;
1496 tmp = te[ 7 ]; te[ 7 ] = te[ 13 ]; te[ 13 ] = tmp;
1497 tmp = te[ 11 ]; te[ 11 ] = te[ 14 ]; te[ 14 ] = tmp;
1498
1499 return this;
1500
1501 },
1502
1503 setPosition: function ( v ) {
1504
1505 var te = this.elements;
1506
1507 te[ 12 ] = v.x;
1508 te[ 13 ] = v.y;
1509 te[ 14 ] = v.z;
1510
1511 return this;
1512
1513 },
1514
1515 getInverse: function ( m, throwOnDegenerate ) {
1516
1517 // based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm
1518 var te = this.elements,
1519 me = m.elements,
1520
1521 n11 = me[ 0 ], n21 = me[ 1 ], n31 = me[ 2 ], n41 = me[ 3 ],
1522 n12 = me[ 4 ], n22 = me[ 5 ], n32 = me[ 6 ], n42 = me[ 7 ],
1523 n13 = me[ 8 ], n23 = me[ 9 ], n33 = me[ 10 ], n43 = me[ 11 ],
1524 n14 = me[ 12 ], n24 = me[ 13 ], n34 = me[ 14 ], n44 = me[ 15 ],
1525
1526 t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44,
1527 t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44,
1528 t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44,
1529 t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34;
1530
1531 var det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14;
1532
1533 if ( det === 0 ) {
1534
1535 var msg = "THREE.Matrix4: .getInverse() can't invert matrix, determinant is 0";
1536
1537 if ( throwOnDegenerate === true ) {
1538
1539 throw new Error( msg );
1540
1541 } else {
1542
1543 console.warn( msg );
1544
1545 }
1546
1547 return this.identity();
1548
1549 }
1550
1551 var detInv = 1 / det;
1552
1553 te[ 0 ] = t11 * detInv;
1554 te[ 1 ] = ( n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44 ) * detInv;
1555 te[ 2 ] = ( n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44 ) * detInv;
1556 te[ 3 ] = ( n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43 ) * detInv;
1557
1558 te[ 4 ] = t12 * detInv;
1559 te[ 5 ] = ( n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44 ) * detInv;
1560 te[ 6 ] = ( n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44 ) * detInv;
1561 te[ 7 ] = ( n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43 ) * detInv;
1562
1563 te[ 8 ] = t13 * detInv;
1564 te[ 9 ] = ( n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44 ) * detInv;
1565 te[ 10 ] = ( n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44 ) * detInv;
1566 te[ 11 ] = ( n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43 ) * detInv;
1567
1568 te[ 12 ] = t14 * detInv;
1569 te[ 13 ] = ( n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34 ) * detInv;
1570 te[ 14 ] = ( n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34 ) * detInv;
1571 te[ 15 ] = ( n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33 ) * detInv;
1572
1573 return this;
1574
1575 },
1576
1577 scale: function ( v ) {
1578
1579 var te = this.elements;
1580 var x = v.x, y = v.y, z = v.z;
1581
1582 te[ 0 ] *= x; te[ 4 ] *= y; te[ 8 ] *= z;
1583 te[ 1 ] *= x; te[ 5 ] *= y; te[ 9 ] *= z;
1584 te[ 2 ] *= x; te[ 6 ] *= y; te[ 10 ] *= z;
1585 te[ 3 ] *= x; te[ 7 ] *= y; te[ 11 ] *= z;
1586
1587 return this;
1588
1589 },
1590
1591 getMaxScaleOnAxis: function () {
1592
1593 var te = this.elements;
1594
1595 var scaleXSq = te[ 0 ] * te[ 0 ] + te[ 1 ] * te[ 1 ] + te[ 2 ] * te[ 2 ];
1596 var scaleYSq = te[ 4 ] * te[ 4 ] + te[ 5 ] * te[ 5 ] + te[ 6 ] * te[ 6 ];
1597 var scaleZSq = te[ 8 ] * te[ 8 ] + te[ 9 ] * te[ 9 ] + te[ 10 ] * te[ 10 ];
1598
1599 return Math.sqrt( Math.max( scaleXSq, scaleYSq, scaleZSq ) );
1600
1601 },
1602
1603 makeTranslation: function ( x, y, z ) {
1604
1605 this.set(
1606
1607 1, 0, 0, x,
1608 0, 1, 0, y,
1609 0, 0, 1, z,
1610 0, 0, 0, 1
1611
1612 );
1613
1614 return this;
1615
1616 },
1617
1618 makeRotationX: function ( theta ) {
1619
1620 var c = Math.cos( theta ), s = Math.sin( theta );
1621
1622 this.set(
1623
1624 1, 0, 0, 0,
1625 0, c, - s, 0,
1626 0, s, c, 0,
1627 0, 0, 0, 1
1628
1629 );
1630
1631 return this;
1632
1633 },
1634
1635 makeRotationY: function ( theta ) {
1636
1637 var c = Math.cos( theta ), s = Math.sin( theta );
1638
1639 this.set(
1640
1641 c, 0, s, 0,
1642 0, 1, 0, 0,
1643 - s, 0, c, 0,
1644 0, 0, 0, 1
1645
1646 );
1647
1648 return this;
1649
1650 },
1651
1652 makeRotationZ: function ( theta ) {
1653
1654 var c = Math.cos( theta ), s = Math.sin( theta );
1655
1656 this.set(
1657
1658 c, - s, 0, 0,
1659 s, c, 0, 0,
1660 0, 0, 1, 0,
1661 0, 0, 0, 1
1662
1663 );
1664
1665 return this;
1666
1667 },
1668
1669 makeRotationAxis: function ( axis, angle ) {
1670
1671 // Based on http://www.gamedev.net/reference/articles/article1199.asp
1672
1673 var c = Math.cos( angle );
1674 var s = Math.sin( angle );
1675 var t = 1 - c;
1676 var x = axis.x, y = axis.y, z = axis.z;
1677 var tx = t * x, ty = t * y;
1678
1679 this.set(
1680
1681 tx * x + c, tx * y - s * z, tx * z + s * y, 0,
1682 tx * y + s * z, ty * y + c, ty * z - s * x, 0,
1683 tx * z - s * y, ty * z + s * x, t * z * z + c, 0,
1684 0, 0, 0, 1
1685
1686 );
1687
1688 return this;
1689
1690 },
1691
1692 makeScale: function ( x, y, z ) {
1693
1694 this.set(
1695
1696 x, 0, 0, 0,
1697 0, y, 0, 0,
1698 0, 0, z, 0,
1699 0, 0, 0, 1
1700
1701 );
1702
1703 return this;
1704
1705 },
1706
1707 makeShear: function ( x, y, z ) {
1708
1709 this.set(
1710
1711 1, y, z, 0,
1712 x, 1, z, 0,
1713 x, y, 1, 0,
1714 0, 0, 0, 1
1715
1716 );
1717
1718 return this;
1719
1720 },
1721
1722 compose: function ( position, quaternion, scale ) {
1723
1724 this.makeRotationFromQuaternion( quaternion );
1725 this.scale( scale );
1726 this.setPosition( position );
1727
1728 return this;
1729
1730 },
1731
1732 decompose: function () {
1733
1734 var vector = new Vector3();
1735 var matrix = new Matrix4();
1736
1737 return function decompose( position, quaternion, scale ) {
1738
1739 var te = this.elements;
1740
1741 var sx = vector.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length();
1742 var sy = vector.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length();
1743 var sz = vector.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length();
1744
1745 // if determine is negative, we need to invert one scale
1746 var det = this.determinant();
1747 if ( det < 0 ) sx = - sx;
1748
1749 position.x = te[ 12 ];
1750 position.y = te[ 13 ];
1751 position.z = te[ 14 ];
1752
1753 // scale the rotation part
1754 matrix.copy( this );
1755
1756 var invSX = 1 / sx;
1757 var invSY = 1 / sy;
1758 var invSZ = 1 / sz;
1759
1760 matrix.elements[ 0 ] *= invSX;
1761 matrix.elements[ 1 ] *= invSX;
1762 matrix.elements[ 2 ] *= invSX;
1763
1764 matrix.elements[ 4 ] *= invSY;
1765 matrix.elements[ 5 ] *= invSY;
1766 matrix.elements[ 6 ] *= invSY;
1767
1768 matrix.elements[ 8 ] *= invSZ;
1769 matrix.elements[ 9 ] *= invSZ;
1770 matrix.elements[ 10 ] *= invSZ;
1771
1772 quaternion.setFromRotationMatrix( matrix );
1773
1774 scale.x = sx;
1775 scale.y = sy;
1776 scale.z = sz;
1777
1778 return this;
1779
1780 };
1781
1782 }(),
1783
1784 makePerspective: function ( left, right, top, bottom, near, far ) {
1785
1786 if ( far === undefined ) {
1787
1788 console.warn( 'THREE.Matrix4: .makePerspective() has been redefined and has a new signature. Please check the docs.' );
1789
1790 }
1791
1792 var te = this.elements;
1793 var x = 2 * near / ( right - left );
1794 var y = 2 * near / ( top - bottom );
1795
1796 var a = ( right + left ) / ( right - left );
1797 var b = ( top + bottom ) / ( top - bottom );
1798 var c = - ( far + near ) / ( far - near );
1799 var d = - 2 * far * near / ( far - near );
1800
1801 te[ 0 ] = x; te[ 4 ] = 0; te[ 8 ] = a; te[ 12 ] = 0;
1802 te[ 1 ] = 0; te[ 5 ] = y; te[ 9 ] = b; te[ 13 ] = 0;
1803 te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = c; te[ 14 ] = d;
1804 te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = - 1; te[ 15 ] = 0;
1805
1806 return this;
1807
1808 },
1809
1810 makeOrthographic: function ( left, right, top, bottom, near, far ) {
1811
1812 var te = this.elements;
1813 var w = 1.0 / ( right - left );
1814 var h = 1.0 / ( top - bottom );
1815 var p = 1.0 / ( far - near );
1816
1817 var x = ( right + left ) * w;
1818 var y = ( top + bottom ) * h;
1819 var z = ( far + near ) * p;
1820
1821 te[ 0 ] = 2 * w; te[ 4 ] = 0; te[ 8 ] = 0; te[ 12 ] = - x;
1822 te[ 1 ] = 0; te[ 5 ] = 2 * h; te[ 9 ] = 0; te[ 13 ] = - y;
1823 te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = - 2 * p; te[ 14 ] = - z;
1824 te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = 0; te[ 15 ] = 1;
1825
1826 return this;
1827
1828 },
1829
1830 equals: function ( matrix ) {
1831
1832 var te = this.elements;
1833 var me = matrix.elements;
1834
1835 for ( var i = 0; i < 16; i ++ ) {
1836
1837 if ( te[ i ] !== me[ i ] ) return false;
1838
1839 }
1840
1841 return true;
1842
1843 },
1844
1845 fromArray: function ( array, offset ) {
1846
1847 if ( offset === undefined ) offset = 0;
1848
1849 for ( var i = 0; i < 16; i ++ ) {
1850
1851 this.elements[ i ] = array[ i + offset ];
1852
1853 }
1854
1855 return this;
1856
1857 },
1858
1859 toArray: function ( array, offset ) {
1860
1861 if ( array === undefined ) array = [];
1862 if ( offset === undefined ) offset = 0;
1863
1864 var te = this.elements;
1865
1866 array[ offset ] = te[ 0 ];
1867 array[ offset + 1 ] = te[ 1 ];
1868 array[ offset + 2 ] = te[ 2 ];
1869 array[ offset + 3 ] = te[ 3 ];
1870
1871 array[ offset + 4 ] = te[ 4 ];
1872 array[ offset + 5 ] = te[ 5 ];
1873 array[ offset + 6 ] = te[ 6 ];
1874 array[ offset + 7 ] = te[ 7 ];
1875
1876 array[ offset + 8 ] = te[ 8 ];
1877 array[ offset + 9 ] = te[ 9 ];
1878 array[ offset + 10 ] = te[ 10 ];
1879 array[ offset + 11 ] = te[ 11 ];
1880
1881 array[ offset + 12 ] = te[ 12 ];
1882 array[ offset + 13 ] = te[ 13 ];
1883 array[ offset + 14 ] = te[ 14 ];
1884 array[ offset + 15 ] = te[ 15 ];
1885
1886 return array;
1887
1888 }
1889
1890 } );
1891
1892 /**
1893 * @author mikael emtinger / http://gomo.se/
1894 * @author alteredq / http://alteredqualia.com/
1895 * @author WestLangley / http://github.com/WestLangley
1896 * @author bhouston / http://clara.io
1897 */
1898
1899 function Quaternion( x, y, z, w ) {
1900
1901 this._x = x || 0;
1902 this._y = y || 0;
1903 this._z = z || 0;
1904 this._w = ( w !== undefined ) ? w : 1;
1905
1906 }
1907
1908 Object.assign( Quaternion, {
1909
1910 slerp: function ( qa, qb, qm, t ) {
1911
1912 return qm.copy( qa ).slerp( qb, t );
1913
1914 },
1915
1916 slerpFlat: function ( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) {
1917
1918 // fuzz-free, array-based Quaternion SLERP operation
1919
1920 var x0 = src0[ srcOffset0 + 0 ],
1921 y0 = src0[ srcOffset0 + 1 ],
1922 z0 = src0[ srcOffset0 + 2 ],
1923 w0 = src0[ srcOffset0 + 3 ],
1924
1925 x1 = src1[ srcOffset1 + 0 ],
1926 y1 = src1[ srcOffset1 + 1 ],
1927 z1 = src1[ srcOffset1 + 2 ],
1928 w1 = src1[ srcOffset1 + 3 ];
1929
1930 if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) {
1931
1932 var s = 1 - t,
1933
1934 cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1,
1935
1936 dir = ( cos >= 0 ? 1 : - 1 ),
1937 sqrSin = 1 - cos * cos;
1938
1939 // Skip the Slerp for tiny steps to avoid numeric problems:
1940 if ( sqrSin > Number.EPSILON ) {
1941
1942 var sin = Math.sqrt( sqrSin ),
1943 len = Math.atan2( sin, cos * dir );
1944
1945 s = Math.sin( s * len ) / sin;
1946 t = Math.sin( t * len ) / sin;
1947
1948 }
1949
1950 var tDir = t * dir;
1951
1952 x0 = x0 * s + x1 * tDir;
1953 y0 = y0 * s + y1 * tDir;
1954 z0 = z0 * s + z1 * tDir;
1955 w0 = w0 * s + w1 * tDir;
1956
1957 // Normalize in case we just did a lerp:
1958 if ( s === 1 - t ) {
1959
1960 var f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 );
1961
1962 x0 *= f;
1963 y0 *= f;
1964 z0 *= f;
1965 w0 *= f;
1966
1967 }
1968
1969 }
1970
1971 dst[ dstOffset ] = x0;
1972 dst[ dstOffset + 1 ] = y0;
1973 dst[ dstOffset + 2 ] = z0;
1974 dst[ dstOffset + 3 ] = w0;
1975
1976 }
1977
1978 } );
1979
1980 Object.defineProperties( Quaternion.prototype, {
1981
1982 x: {
1983
1984 get: function () {
1985
1986 return this._x;
1987
1988 },
1989
1990 set: function ( value ) {
1991
1992 this._x = value;
1993 this.onChangeCallback();
1994
1995 }
1996
1997 },
1998
1999 y: {
2000
2001 get: function () {
2002
2003 return this._y;
2004
2005 },
2006
2007 set: function ( value ) {
2008
2009 this._y = value;
2010 this.onChangeCallback();
2011
2012 }
2013
2014 },
2015
2016 z: {
2017
2018 get: function () {
2019
2020 return this._z;
2021
2022 },
2023
2024 set: function ( value ) {
2025
2026 this._z = value;
2027 this.onChangeCallback();
2028
2029 }
2030
2031 },
2032
2033 w: {
2034
2035 get: function () {
2036
2037 return this._w;
2038
2039 },
2040
2041 set: function ( value ) {
2042
2043 this._w = value;
2044 this.onChangeCallback();
2045
2046 }
2047
2048 }
2049
2050 } );
2051
2052 Object.assign( Quaternion.prototype, {
2053
2054 set: function ( x, y, z, w ) {
2055
2056 this._x = x;
2057 this._y = y;
2058 this._z = z;
2059 this._w = w;
2060
2061 this.onChangeCallback();
2062
2063 return this;
2064
2065 },
2066
2067 clone: function () {
2068
2069 return new this.constructor( this._x, this._y, this._z, this._w );
2070
2071 },
2072
2073 copy: function ( quaternion ) {
2074
2075 this._x = quaternion.x;
2076 this._y = quaternion.y;
2077 this._z = quaternion.z;
2078 this._w = quaternion.w;
2079
2080 this.onChangeCallback();
2081
2082 return this;
2083
2084 },
2085
2086 setFromEuler: function ( euler, update ) {
2087
2088 if ( ! ( euler && euler.isEuler ) ) {
2089
2090 throw new Error( 'THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.' );
2091
2092 }
2093
2094 var x = euler._x, y = euler._y, z = euler._z, order = euler.order;
2095
2096 // http://www.mathworks.com/matlabcentral/fileexchange/
2097 // 20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/
2098 // content/SpinCalc.m
2099
2100 var cos = Math.cos;
2101 var sin = Math.sin;
2102
2103 var c1 = cos( x / 2 );
2104 var c2 = cos( y / 2 );
2105 var c3 = cos( z / 2 );
2106
2107 var s1 = sin( x / 2 );
2108 var s2 = sin( y / 2 );
2109 var s3 = sin( z / 2 );
2110
2111 if ( order === 'XYZ' ) {
2112
2113 this._x = s1 * c2 * c3 + c1 * s2 * s3;
2114 this._y = c1 * s2 * c3 - s1 * c2 * s3;
2115 this._z = c1 * c2 * s3 + s1 * s2 * c3;
2116 this._w = c1 * c2 * c3 - s1 * s2 * s3;
2117
2118 } else if ( order === 'YXZ' ) {
2119
2120 this._x = s1 * c2 * c3 + c1 * s2 * s3;
2121 this._y = c1 * s2 * c3 - s1 * c2 * s3;
2122 this._z = c1 * c2 * s3 - s1 * s2 * c3;
2123 this._w = c1 * c2 * c3 + s1 * s2 * s3;
2124
2125 } else if ( order === 'ZXY' ) {
2126
2127 this._x = s1 * c2 * c3 - c1 * s2 * s3;
2128 this._y = c1 * s2 * c3 + s1 * c2 * s3;
2129 this._z = c1 * c2 * s3 + s1 * s2 * c3;
2130 this._w = c1 * c2 * c3 - s1 * s2 * s3;
2131
2132 } else if ( order === 'ZYX' ) {
2133
2134 this._x = s1 * c2 * c3 - c1 * s2 * s3;
2135 this._y = c1 * s2 * c3 + s1 * c2 * s3;
2136 this._z = c1 * c2 * s3 - s1 * s2 * c3;
2137 this._w = c1 * c2 * c3 + s1 * s2 * s3;
2138
2139 } else if ( order === 'YZX' ) {
2140
2141 this._x = s1 * c2 * c3 + c1 * s2 * s3;
2142 this._y = c1 * s2 * c3 + s1 * c2 * s3;
2143 this._z = c1 * c2 * s3 - s1 * s2 * c3;
2144 this._w = c1 * c2 * c3 - s1 * s2 * s3;
2145
2146 } else if ( order === 'XZY' ) {
2147
2148 this._x = s1 * c2 * c3 - c1 * s2 * s3;
2149 this._y = c1 * s2 * c3 - s1 * c2 * s3;
2150 this._z = c1 * c2 * s3 + s1 * s2 * c3;
2151 this._w = c1 * c2 * c3 + s1 * s2 * s3;
2152
2153 }
2154
2155 if ( update !== false ) this.onChangeCallback();
2156
2157 return this;
2158
2159 },
2160
2161 setFromAxisAngle: function ( axis, angle ) {
2162
2163 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm
2164
2165 // assumes axis is normalized
2166
2167 var halfAngle = angle / 2, s = Math.sin( halfAngle );
2168
2169 this._x = axis.x * s;
2170 this._y = axis.y * s;
2171 this._z = axis.z * s;
2172 this._w = Math.cos( halfAngle );
2173
2174 this.onChangeCallback();
2175
2176 return this;
2177
2178 },
2179
2180 setFromRotationMatrix: function ( m ) {
2181
2182 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
2183
2184 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
2185
2186 var te = m.elements,
2187
2188 m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
2189 m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
2190 m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ],
2191
2192 trace = m11 + m22 + m33,
2193 s;
2194
2195 if ( trace > 0 ) {
2196
2197 s = 0.5 / Math.sqrt( trace + 1.0 );
2198
2199 this._w = 0.25 / s;
2200 this._x = ( m32 - m23 ) * s;
2201 this._y = ( m13 - m31 ) * s;
2202 this._z = ( m21 - m12 ) * s;
2203
2204 } else if ( m11 > m22 && m11 > m33 ) {
2205
2206 s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 );
2207
2208 this._w = ( m32 - m23 ) / s;
2209 this._x = 0.25 * s;
2210 this._y = ( m12 + m21 ) / s;
2211 this._z = ( m13 + m31 ) / s;
2212
2213 } else if ( m22 > m33 ) {
2214
2215 s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 );
2216
2217 this._w = ( m13 - m31 ) / s;
2218 this._x = ( m12 + m21 ) / s;
2219 this._y = 0.25 * s;
2220 this._z = ( m23 + m32 ) / s;
2221
2222 } else {
2223
2224 s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 );
2225
2226 this._w = ( m21 - m12 ) / s;
2227 this._x = ( m13 + m31 ) / s;
2228 this._y = ( m23 + m32 ) / s;
2229 this._z = 0.25 * s;
2230
2231 }
2232
2233 this.onChangeCallback();
2234
2235 return this;
2236
2237 },
2238
2239 setFromUnitVectors: function () {
2240
2241 // assumes direction vectors vFrom and vTo are normalized
2242
2243 var v1 = new Vector3();
2244 var r;
2245
2246 var EPS = 0.000001;
2247
2248 return function setFromUnitVectors( vFrom, vTo ) {
2249
2250 if ( v1 === undefined ) v1 = new Vector3();
2251
2252 r = vFrom.dot( vTo ) + 1;
2253
2254 if ( r < EPS ) {
2255
2256 r = 0;
2257
2258 if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) {
2259
2260 v1.set( - vFrom.y, vFrom.x, 0 );
2261
2262 } else {
2263
2264 v1.set( 0, - vFrom.z, vFrom.y );
2265
2266 }
2267
2268 } else {
2269
2270 v1.crossVectors( vFrom, vTo );
2271
2272 }
2273
2274 this._x = v1.x;
2275 this._y = v1.y;
2276 this._z = v1.z;
2277 this._w = r;
2278
2279 return this.normalize();
2280
2281 };
2282
2283 }(),
2284
2285 inverse: function () {
2286
2287 // quaternion is assumed to have unit length
2288
2289 return this.conjugate();
2290
2291 },
2292
2293 conjugate: function () {
2294
2295 this._x *= - 1;
2296 this._y *= - 1;
2297 this._z *= - 1;
2298
2299 this.onChangeCallback();
2300
2301 return this;
2302
2303 },
2304
2305 dot: function ( v ) {
2306
2307 return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w;
2308
2309 },
2310
2311 lengthSq: function () {
2312
2313 return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w;
2314
2315 },
2316
2317 length: function () {
2318
2319 return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w );
2320
2321 },
2322
2323 normalize: function () {
2324
2325 var l = this.length();
2326
2327 if ( l === 0 ) {
2328
2329 this._x = 0;
2330 this._y = 0;
2331 this._z = 0;
2332 this._w = 1;
2333
2334 } else {
2335
2336 l = 1 / l;
2337
2338 this._x = this._x * l;
2339 this._y = this._y * l;
2340 this._z = this._z * l;
2341 this._w = this._w * l;
2342
2343 }
2344
2345 this.onChangeCallback();
2346
2347 return this;
2348
2349 },
2350
2351 multiply: function ( q, p ) {
2352
2353 if ( p !== undefined ) {
2354
2355 console.warn( 'THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead.' );
2356 return this.multiplyQuaternions( q, p );
2357
2358 }
2359
2360 return this.multiplyQuaternions( this, q );
2361
2362 },
2363
2364 premultiply: function ( q ) {
2365
2366 return this.multiplyQuaternions( q, this );
2367
2368 },
2369
2370 multiplyQuaternions: function ( a, b ) {
2371
2372 // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm
2373
2374 var qax = a._x, qay = a._y, qaz = a._z, qaw = a._w;
2375 var qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w;
2376
2377 this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;
2378 this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;
2379 this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;
2380 this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;
2381
2382 this.onChangeCallback();
2383
2384 return this;
2385
2386 },
2387
2388 slerp: function ( qb, t ) {
2389
2390 if ( t === 0 ) return this;
2391 if ( t === 1 ) return this.copy( qb );
2392
2393 var x = this._x, y = this._y, z = this._z, w = this._w;
2394
2395 // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/
2396
2397 var cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z;
2398
2399 if ( cosHalfTheta < 0 ) {
2400
2401 this._w = - qb._w;
2402 this._x = - qb._x;
2403 this._y = - qb._y;
2404 this._z = - qb._z;
2405
2406 cosHalfTheta = - cosHalfTheta;
2407
2408 } else {
2409
2410 this.copy( qb );
2411
2412 }
2413
2414 if ( cosHalfTheta >= 1.0 ) {
2415
2416 this._w = w;
2417 this._x = x;
2418 this._y = y;
2419 this._z = z;
2420
2421 return this;
2422
2423 }
2424
2425 var sinHalfTheta = Math.sqrt( 1.0 - cosHalfTheta * cosHalfTheta );
2426
2427 if ( Math.abs( sinHalfTheta ) < 0.001 ) {
2428
2429 this._w = 0.5 * ( w + this._w );
2430 this._x = 0.5 * ( x + this._x );
2431 this._y = 0.5 * ( y + this._y );
2432 this._z = 0.5 * ( z + this._z );
2433
2434 return this;
2435
2436 }
2437
2438 var halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta );
2439 var ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta,
2440 ratioB = Math.sin( t * halfTheta ) / sinHalfTheta;
2441
2442 this._w = ( w * ratioA + this._w * ratioB );
2443 this._x = ( x * ratioA + this._x * ratioB );
2444 this._y = ( y * ratioA + this._y * ratioB );
2445 this._z = ( z * ratioA + this._z * ratioB );
2446
2447 this.onChangeCallback();
2448
2449 return this;
2450
2451 },
2452
2453 equals: function ( quaternion ) {
2454
2455 return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w );
2456
2457 },
2458
2459 fromArray: function ( array, offset ) {
2460
2461 if ( offset === undefined ) offset = 0;
2462
2463 this._x = array[ offset ];
2464 this._y = array[ offset + 1 ];
2465 this._z = array[ offset + 2 ];
2466 this._w = array[ offset + 3 ];
2467
2468 this.onChangeCallback();
2469
2470 return this;
2471
2472 },
2473
2474 toArray: function ( array, offset ) {
2475
2476 if ( array === undefined ) array = [];
2477 if ( offset === undefined ) offset = 0;
2478
2479 array[ offset ] = this._x;
2480 array[ offset + 1 ] = this._y;
2481 array[ offset + 2 ] = this._z;
2482 array[ offset + 3 ] = this._w;
2483
2484 return array;
2485
2486 },
2487
2488 onChange: function ( callback ) {
2489
2490 this.onChangeCallback = callback;
2491
2492 return this;
2493
2494 },
2495
2496 onChangeCallback: function () {}
2497
2498 } );
2499
2500 /**
2501 * @author mrdoob / http://mrdoob.com/
2502 * @author kile / http://kile.stravaganza.org/
2503 * @author philogb / http://blog.thejit.org/
2504 * @author mikael emtinger / http://gomo.se/
2505 * @author egraether / http://egraether.com/
2506 * @author WestLangley / http://github.com/WestLangley
2507 */
2508
2509 function Vector3( x, y, z ) {
2510
2511 this.x = x || 0;
2512 this.y = y || 0;
2513 this.z = z || 0;
2514
2515 }
2516
2517 Object.assign( Vector3.prototype, {
2518
2519 isVector3: true,
2520
2521 set: function ( x, y, z ) {
2522
2523 this.x = x;
2524 this.y = y;
2525 this.z = z;
2526
2527 return this;
2528
2529 },
2530
2531 setScalar: function ( scalar ) {
2532
2533 this.x = scalar;
2534 this.y = scalar;
2535 this.z = scalar;
2536
2537 return this;
2538
2539 },
2540
2541 setX: function ( x ) {
2542
2543 this.x = x;
2544
2545 return this;
2546
2547 },
2548
2549 setY: function ( y ) {
2550
2551 this.y = y;
2552
2553 return this;
2554
2555 },
2556
2557 setZ: function ( z ) {
2558
2559 this.z = z;
2560
2561 return this;
2562
2563 },
2564
2565 setComponent: function ( index, value ) {
2566
2567 switch ( index ) {
2568
2569 case 0: this.x = value; break;
2570 case 1: this.y = value; break;
2571 case 2: this.z = value; break;
2572 default: throw new Error( 'index is out of range: ' + index );
2573
2574 }
2575
2576 return this;
2577
2578 },
2579
2580 getComponent: function ( index ) {
2581
2582 switch ( index ) {
2583
2584 case 0: return this.x;
2585 case 1: return this.y;
2586 case 2: return this.z;
2587 default: throw new Error( 'index is out of range: ' + index );
2588
2589 }
2590
2591 },
2592
2593 clone: function () {
2594
2595 return new this.constructor( this.x, this.y, this.z );
2596
2597 },
2598
2599 copy: function ( v ) {
2600
2601 this.x = v.x;
2602 this.y = v.y;
2603 this.z = v.z;
2604
2605 return this;
2606
2607 },
2608
2609 add: function ( v, w ) {
2610
2611 if ( w !== undefined ) {
2612
2613 console.warn( 'THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
2614 return this.addVectors( v, w );
2615
2616 }
2617
2618 this.x += v.x;
2619 this.y += v.y;
2620 this.z += v.z;
2621
2622 return this;
2623
2624 },
2625
2626 addScalar: function ( s ) {
2627
2628 this.x += s;
2629 this.y += s;
2630 this.z += s;
2631
2632 return this;
2633
2634 },
2635
2636 addVectors: function ( a, b ) {
2637
2638 this.x = a.x + b.x;
2639 this.y = a.y + b.y;
2640 this.z = a.z + b.z;
2641
2642 return this;
2643
2644 },
2645
2646 addScaledVector: function ( v, s ) {
2647
2648 this.x += v.x * s;
2649 this.y += v.y * s;
2650 this.z += v.z * s;
2651
2652 return this;
2653
2654 },
2655
2656 sub: function ( v, w ) {
2657
2658 if ( w !== undefined ) {
2659
2660 console.warn( 'THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
2661 return this.subVectors( v, w );
2662
2663 }
2664
2665 this.x -= v.x;
2666 this.y -= v.y;
2667 this.z -= v.z;
2668
2669 return this;
2670
2671 },
2672
2673 subScalar: function ( s ) {
2674
2675 this.x -= s;
2676 this.y -= s;
2677 this.z -= s;
2678
2679 return this;
2680
2681 },
2682
2683 subVectors: function ( a, b ) {
2684
2685 this.x = a.x - b.x;
2686 this.y = a.y - b.y;
2687 this.z = a.z - b.z;
2688
2689 return this;
2690
2691 },
2692
2693 multiply: function ( v, w ) {
2694
2695 if ( w !== undefined ) {
2696
2697 console.warn( 'THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead.' );
2698 return this.multiplyVectors( v, w );
2699
2700 }
2701
2702 this.x *= v.x;
2703 this.y *= v.y;
2704 this.z *= v.z;
2705
2706 return this;
2707
2708 },
2709
2710 multiplyScalar: function ( scalar ) {
2711
2712 this.x *= scalar;
2713 this.y *= scalar;
2714 this.z *= scalar;
2715
2716 return this;
2717
2718 },
2719
2720 multiplyVectors: function ( a, b ) {
2721
2722 this.x = a.x * b.x;
2723 this.y = a.y * b.y;
2724 this.z = a.z * b.z;
2725
2726 return this;
2727
2728 },
2729
2730 applyEuler: function () {
2731
2732 var quaternion = new Quaternion();
2733
2734 return function applyEuler( euler ) {
2735
2736 if ( ! ( euler && euler.isEuler ) ) {
2737
2738 console.error( 'THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order.' );
2739
2740 }
2741
2742 return this.applyQuaternion( quaternion.setFromEuler( euler ) );
2743
2744 };
2745
2746 }(),
2747
2748 applyAxisAngle: function () {
2749
2750 var quaternion = new Quaternion();
2751
2752 return function applyAxisAngle( axis, angle ) {
2753
2754 return this.applyQuaternion( quaternion.setFromAxisAngle( axis, angle ) );
2755
2756 };
2757
2758 }(),
2759
2760 applyMatrix3: function ( m ) {
2761
2762 var x = this.x, y = this.y, z = this.z;
2763 var e = m.elements;
2764
2765 this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z;
2766 this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z;
2767 this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z;
2768
2769 return this;
2770
2771 },
2772
2773 applyMatrix4: function ( m ) {
2774
2775 var x = this.x, y = this.y, z = this.z;
2776 var e = m.elements;
2777
2778 var w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] );
2779
2780 this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w;
2781 this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w;
2782 this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w;
2783
2784 return this;
2785
2786 },
2787
2788 applyQuaternion: function ( q ) {
2789
2790 var x = this.x, y = this.y, z = this.z;
2791 var qx = q.x, qy = q.y, qz = q.z, qw = q.w;
2792
2793 // calculate quat * vector
2794
2795 var ix = qw * x + qy * z - qz * y;
2796 var iy = qw * y + qz * x - qx * z;
2797 var iz = qw * z + qx * y - qy * x;
2798 var iw = - qx * x - qy * y - qz * z;
2799
2800 // calculate result * inverse quat
2801
2802 this.x = ix * qw + iw * - qx + iy * - qz - iz * - qy;
2803 this.y = iy * qw + iw * - qy + iz * - qx - ix * - qz;
2804 this.z = iz * qw + iw * - qz + ix * - qy - iy * - qx;
2805
2806 return this;
2807
2808 },
2809
2810 project: function () {
2811
2812 var matrix = new Matrix4();
2813
2814 return function project( camera ) {
2815
2816 matrix.multiplyMatrices( camera.projectionMatrix, matrix.getInverse( camera.matrixWorld ) );
2817 return this.applyMatrix4( matrix );
2818
2819 };
2820
2821 }(),
2822
2823 unproject: function () {
2824
2825 var matrix = new Matrix4();
2826
2827 return function unproject( camera ) {
2828
2829 matrix.multiplyMatrices( camera.matrixWorld, matrix.getInverse( camera.projectionMatrix ) );
2830 return this.applyMatrix4( matrix );
2831
2832 };
2833
2834 }(),
2835
2836 transformDirection: function ( m ) {
2837
2838 // input: THREE.Matrix4 affine matrix
2839 // vector interpreted as a direction
2840
2841 var x = this.x, y = this.y, z = this.z;
2842 var e = m.elements;
2843
2844 this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z;
2845 this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z;
2846 this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z;
2847
2848 return this.normalize();
2849
2850 },
2851
2852 divide: function ( v ) {
2853
2854 this.x /= v.x;
2855 this.y /= v.y;
2856 this.z /= v.z;
2857
2858 return this;
2859
2860 },
2861
2862 divideScalar: function ( scalar ) {
2863
2864 return this.multiplyScalar( 1 / scalar );
2865
2866 },
2867
2868 min: function ( v ) {
2869
2870 this.x = Math.min( this.x, v.x );
2871 this.y = Math.min( this.y, v.y );
2872 this.z = Math.min( this.z, v.z );
2873
2874 return this;
2875
2876 },
2877
2878 max: function ( v ) {
2879
2880 this.x = Math.max( this.x, v.x );
2881 this.y = Math.max( this.y, v.y );
2882 this.z = Math.max( this.z, v.z );
2883
2884 return this;
2885
2886 },
2887
2888 clamp: function ( min, max ) {
2889
2890 // assumes min < max, componentwise
2891
2892 this.x = Math.max( min.x, Math.min( max.x, this.x ) );
2893 this.y = Math.max( min.y, Math.min( max.y, this.y ) );
2894 this.z = Math.max( min.z, Math.min( max.z, this.z ) );
2895
2896 return this;
2897
2898 },
2899
2900 clampScalar: function () {
2901
2902 var min = new Vector3();
2903 var max = new Vector3();
2904
2905 return function clampScalar( minVal, maxVal ) {
2906
2907 min.set( minVal, minVal, minVal );
2908 max.set( maxVal, maxVal, maxVal );
2909
2910 return this.clamp( min, max );
2911
2912 };
2913
2914 }(),
2915
2916 clampLength: function ( min, max ) {
2917
2918 var length = this.length();
2919
2920 return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
2921
2922 },
2923
2924 floor: function () {
2925
2926 this.x = Math.floor( this.x );
2927 this.y = Math.floor( this.y );
2928 this.z = Math.floor( this.z );
2929
2930 return this;
2931
2932 },
2933
2934 ceil: function () {
2935
2936 this.x = Math.ceil( this.x );
2937 this.y = Math.ceil( this.y );
2938 this.z = Math.ceil( this.z );
2939
2940 return this;
2941
2942 },
2943
2944 round: function () {
2945
2946 this.x = Math.round( this.x );
2947 this.y = Math.round( this.y );
2948 this.z = Math.round( this.z );
2949
2950 return this;
2951
2952 },
2953
2954 roundToZero: function () {
2955
2956 this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
2957 this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
2958 this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );
2959
2960 return this;
2961
2962 },
2963
2964 negate: function () {
2965
2966 this.x = - this.x;
2967 this.y = - this.y;
2968 this.z = - this.z;
2969
2970 return this;
2971
2972 },
2973
2974 dot: function ( v ) {
2975
2976 return this.x * v.x + this.y * v.y + this.z * v.z;
2977
2978 },
2979
2980 // TODO lengthSquared?
2981
2982 lengthSq: function () {
2983
2984 return this.x * this.x + this.y * this.y + this.z * this.z;
2985
2986 },
2987
2988 length: function () {
2989
2990 return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z );
2991
2992 },
2993
2994 manhattanLength: function () {
2995
2996 return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z );
2997
2998 },
2999
3000 normalize: function () {
3001
3002 return this.divideScalar( this.length() || 1 );
3003
3004 },
3005
3006 setLength: function ( length ) {
3007
3008 return this.normalize().multiplyScalar( length );
3009
3010 },
3011
3012 lerp: function ( v, alpha ) {
3013
3014 this.x += ( v.x - this.x ) * alpha;
3015 this.y += ( v.y - this.y ) * alpha;
3016 this.z += ( v.z - this.z ) * alpha;
3017
3018 return this;
3019
3020 },
3021
3022 lerpVectors: function ( v1, v2, alpha ) {
3023
3024 return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );
3025
3026 },
3027
3028 cross: function ( v, w ) {
3029
3030 if ( w !== undefined ) {
3031
3032 console.warn( 'THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead.' );
3033 return this.crossVectors( v, w );
3034
3035 }
3036
3037 return this.crossVectors( this, v );
3038
3039 },
3040
3041 crossVectors: function ( a, b ) {
3042
3043 var ax = a.x, ay = a.y, az = a.z;
3044 var bx = b.x, by = b.y, bz = b.z;
3045
3046 this.x = ay * bz - az * by;
3047 this.y = az * bx - ax * bz;
3048 this.z = ax * by - ay * bx;
3049
3050 return this;
3051
3052 },
3053
3054 projectOnVector: function ( vector ) {
3055
3056 var scalar = vector.dot( this ) / vector.lengthSq();
3057
3058 return this.copy( vector ).multiplyScalar( scalar );
3059
3060 },
3061
3062 projectOnPlane: function () {
3063
3064 var v1 = new Vector3();
3065
3066 return function projectOnPlane( planeNormal ) {
3067
3068 v1.copy( this ).projectOnVector( planeNormal );
3069
3070 return this.sub( v1 );
3071
3072 };
3073
3074 }(),
3075
3076 reflect: function () {
3077
3078 // reflect incident vector off plane orthogonal to normal
3079 // normal is assumed to have unit length
3080
3081 var v1 = new Vector3();
3082
3083 return function reflect( normal ) {
3084
3085 return this.sub( v1.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) );
3086
3087 };
3088
3089 }(),
3090
3091 angleTo: function ( v ) {
3092
3093 var theta = this.dot( v ) / ( Math.sqrt( this.lengthSq() * v.lengthSq() ) );
3094
3095 // clamp, to handle numerical problems
3096
3097 return Math.acos( _Math.clamp( theta, - 1, 1 ) );
3098
3099 },
3100
3101 distanceTo: function ( v ) {
3102
3103 return Math.sqrt( this.distanceToSquared( v ) );
3104
3105 },
3106
3107 distanceToSquared: function ( v ) {
3108
3109 var dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z;
3110
3111 return dx * dx + dy * dy + dz * dz;
3112
3113 },
3114
3115 manhattanDistanceTo: function ( v ) {
3116
3117 return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ) + Math.abs( this.z - v.z );
3118
3119 },
3120
3121 setFromSpherical: function ( s ) {
3122
3123 var sinPhiRadius = Math.sin( s.phi ) * s.radius;
3124
3125 this.x = sinPhiRadius * Math.sin( s.theta );
3126 this.y = Math.cos( s.phi ) * s.radius;
3127 this.z = sinPhiRadius * Math.cos( s.theta );
3128
3129 return this;
3130
3131 },
3132
3133 setFromCylindrical: function ( c ) {
3134
3135 this.x = c.radius * Math.sin( c.theta );
3136 this.y = c.y;
3137 this.z = c.radius * Math.cos( c.theta );
3138
3139 return this;
3140
3141 },
3142
3143 setFromMatrixPosition: function ( m ) {
3144
3145 var e = m.elements;
3146
3147 this.x = e[ 12 ];
3148 this.y = e[ 13 ];
3149 this.z = e[ 14 ];
3150
3151 return this;
3152
3153 },
3154
3155 setFromMatrixScale: function ( m ) {
3156
3157 var sx = this.setFromMatrixColumn( m, 0 ).length();
3158 var sy = this.setFromMatrixColumn( m, 1 ).length();
3159 var sz = this.setFromMatrixColumn( m, 2 ).length();
3160
3161 this.x = sx;
3162 this.y = sy;
3163 this.z = sz;
3164
3165 return this;
3166
3167 },
3168
3169 setFromMatrixColumn: function ( m, index ) {
3170
3171 return this.fromArray( m.elements, index * 4 );
3172
3173 },
3174
3175 equals: function ( v ) {
3176
3177 return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) );
3178
3179 },
3180
3181 fromArray: function ( array, offset ) {
3182
3183 if ( offset === undefined ) offset = 0;
3184
3185 this.x = array[ offset ];
3186 this.y = array[ offset + 1 ];
3187 this.z = array[ offset + 2 ];
3188
3189 return this;
3190
3191 },
3192
3193 toArray: function ( array, offset ) {
3194
3195 if ( array === undefined ) array = [];
3196 if ( offset === undefined ) offset = 0;
3197
3198 array[ offset ] = this.x;
3199 array[ offset + 1 ] = this.y;
3200 array[ offset + 2 ] = this.z;
3201
3202 return array;
3203
3204 },
3205
3206 fromBufferAttribute: function ( attribute, index, offset ) {
3207
3208 if ( offset !== undefined ) {
3209
3210 console.warn( 'THREE.Vector3: offset has been removed from .fromBufferAttribute().' );
3211
3212 }
3213
3214 this.x = attribute.getX( index );
3215 this.y = attribute.getY( index );
3216 this.z = attribute.getZ( index );
3217
3218 return this;
3219
3220 }
3221
3222 } );
3223
3224 /**
3225 * @author alteredq / http://alteredqualia.com/
3226 * @author WestLangley / http://github.com/WestLangley
3227 * @author bhouston / http://clara.io
3228 * @author tschw
3229 */
3230
3231 function Matrix3() {
3232
3233 this.elements = [
3234
3235 1, 0, 0,
3236 0, 1, 0,
3237 0, 0, 1
3238
3239 ];
3240
3241 if ( arguments.length > 0 ) {
3242
3243 console.error( 'THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.' );
3244
3245 }
3246
3247 }
3248
3249 Object.assign( Matrix3.prototype, {
3250
3251 isMatrix3: true,
3252
3253 set: function ( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) {
3254
3255 var te = this.elements;
3256
3257 te[ 0 ] = n11; te[ 1 ] = n21; te[ 2 ] = n31;
3258 te[ 3 ] = n12; te[ 4 ] = n22; te[ 5 ] = n32;
3259 te[ 6 ] = n13; te[ 7 ] = n23; te[ 8 ] = n33;
3260
3261 return this;
3262
3263 },
3264
3265 identity: function () {
3266
3267 this.set(
3268
3269 1, 0, 0,
3270 0, 1, 0,
3271 0, 0, 1
3272
3273 );
3274
3275 return this;
3276
3277 },
3278
3279 clone: function () {
3280
3281 return new this.constructor().fromArray( this.elements );
3282
3283 },
3284
3285 copy: function ( m ) {
3286
3287 var te = this.elements;
3288 var me = m.elements;
3289
3290 te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ];
3291 te[ 3 ] = me[ 3 ]; te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ];
3292 te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ]; te[ 8 ] = me[ 8 ];
3293
3294 return this;
3295
3296 },
3297
3298 setFromMatrix4: function ( m ) {
3299
3300 var me = m.elements;
3301
3302 this.set(
3303
3304 me[ 0 ], me[ 4 ], me[ 8 ],
3305 me[ 1 ], me[ 5 ], me[ 9 ],
3306 me[ 2 ], me[ 6 ], me[ 10 ]
3307
3308 );
3309
3310 return this;
3311
3312 },
3313
3314 applyToBufferAttribute: function () {
3315
3316 var v1 = new Vector3();
3317
3318 return function applyToBufferAttribute( attribute ) {
3319
3320 for ( var i = 0, l = attribute.count; i < l; i ++ ) {
3321
3322 v1.x = attribute.getX( i );
3323 v1.y = attribute.getY( i );
3324 v1.z = attribute.getZ( i );
3325
3326 v1.applyMatrix3( this );
3327
3328 attribute.setXYZ( i, v1.x, v1.y, v1.z );
3329
3330 }
3331
3332 return attribute;
3333
3334 };
3335
3336 }(),
3337
3338 multiply: function ( m ) {
3339
3340 return this.multiplyMatrices( this, m );
3341
3342 },
3343
3344 premultiply: function ( m ) {
3345
3346 return this.multiplyMatrices( m, this );
3347
3348 },
3349
3350 multiplyMatrices: function ( a, b ) {
3351
3352 var ae = a.elements;
3353 var be = b.elements;
3354 var te = this.elements;
3355
3356 var a11 = ae[ 0 ], a12 = ae[ 3 ], a13 = ae[ 6 ];
3357 var a21 = ae[ 1 ], a22 = ae[ 4 ], a23 = ae[ 7 ];
3358 var a31 = ae[ 2 ], a32 = ae[ 5 ], a33 = ae[ 8 ];
3359
3360 var b11 = be[ 0 ], b12 = be[ 3 ], b13 = be[ 6 ];
3361 var b21 = be[ 1 ], b22 = be[ 4 ], b23 = be[ 7 ];
3362 var b31 = be[ 2 ], b32 = be[ 5 ], b33 = be[ 8 ];
3363
3364 te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31;
3365 te[ 3 ] = a11 * b12 + a12 * b22 + a13 * b32;
3366 te[ 6 ] = a11 * b13 + a12 * b23 + a13 * b33;
3367
3368 te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31;
3369 te[ 4 ] = a21 * b12 + a22 * b22 + a23 * b32;
3370 te[ 7 ] = a21 * b13 + a22 * b23 + a23 * b33;
3371
3372 te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31;
3373 te[ 5 ] = a31 * b12 + a32 * b22 + a33 * b32;
3374 te[ 8 ] = a31 * b13 + a32 * b23 + a33 * b33;
3375
3376 return this;
3377
3378 },
3379
3380 multiplyScalar: function ( s ) {
3381
3382 var te = this.elements;
3383
3384 te[ 0 ] *= s; te[ 3 ] *= s; te[ 6 ] *= s;
3385 te[ 1 ] *= s; te[ 4 ] *= s; te[ 7 ] *= s;
3386 te[ 2 ] *= s; te[ 5 ] *= s; te[ 8 ] *= s;
3387
3388 return this;
3389
3390 },
3391
3392 determinant: function () {
3393
3394 var te = this.elements;
3395
3396 var a = te[ 0 ], b = te[ 1 ], c = te[ 2 ],
3397 d = te[ 3 ], e = te[ 4 ], f = te[ 5 ],
3398 g = te[ 6 ], h = te[ 7 ], i = te[ 8 ];
3399
3400 return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g;
3401
3402 },
3403
3404 getInverse: function ( matrix, throwOnDegenerate ) {
3405
3406 if ( matrix && matrix.isMatrix4 ) {
3407
3408 console.error( "THREE.Matrix3: .getInverse() no longer takes a Matrix4 argument." );
3409
3410 }
3411
3412 var me = matrix.elements,
3413 te = this.elements,
3414
3415 n11 = me[ 0 ], n21 = me[ 1 ], n31 = me[ 2 ],
3416 n12 = me[ 3 ], n22 = me[ 4 ], n32 = me[ 5 ],
3417 n13 = me[ 6 ], n23 = me[ 7 ], n33 = me[ 8 ],
3418
3419 t11 = n33 * n22 - n32 * n23,
3420 t12 = n32 * n13 - n33 * n12,
3421 t13 = n23 * n12 - n22 * n13,
3422
3423 det = n11 * t11 + n21 * t12 + n31 * t13;
3424
3425 if ( det === 0 ) {
3426
3427 var msg = "THREE.Matrix3: .getInverse() can't invert matrix, determinant is 0";
3428
3429 if ( throwOnDegenerate === true ) {
3430
3431 throw new Error( msg );
3432
3433 } else {
3434
3435 console.warn( msg );
3436
3437 }
3438
3439 return this.identity();
3440
3441 }
3442
3443 var detInv = 1 / det;
3444
3445 te[ 0 ] = t11 * detInv;
3446 te[ 1 ] = ( n31 * n23 - n33 * n21 ) * detInv;
3447 te[ 2 ] = ( n32 * n21 - n31 * n22 ) * detInv;
3448
3449 te[ 3 ] = t12 * detInv;
3450 te[ 4 ] = ( n33 * n11 - n31 * n13 ) * detInv;
3451 te[ 5 ] = ( n31 * n12 - n32 * n11 ) * detInv;
3452
3453 te[ 6 ] = t13 * detInv;
3454 te[ 7 ] = ( n21 * n13 - n23 * n11 ) * detInv;
3455 te[ 8 ] = ( n22 * n11 - n21 * n12 ) * detInv;
3456
3457 return this;
3458
3459 },
3460
3461 transpose: function () {
3462
3463 var tmp, m = this.elements;
3464
3465 tmp = m[ 1 ]; m[ 1 ] = m[ 3 ]; m[ 3 ] = tmp;
3466 tmp = m[ 2 ]; m[ 2 ] = m[ 6 ]; m[ 6 ] = tmp;
3467 tmp = m[ 5 ]; m[ 5 ] = m[ 7 ]; m[ 7 ] = tmp;
3468
3469 return this;
3470
3471 },
3472
3473 getNormalMatrix: function ( matrix4 ) {
3474
3475 return this.setFromMatrix4( matrix4 ).getInverse( this ).transpose();
3476
3477 },
3478
3479 transposeIntoArray: function ( r ) {
3480
3481 var m = this.elements;
3482
3483 r[ 0 ] = m[ 0 ];
3484 r[ 1 ] = m[ 3 ];
3485 r[ 2 ] = m[ 6 ];
3486 r[ 3 ] = m[ 1 ];
3487 r[ 4 ] = m[ 4 ];
3488 r[ 5 ] = m[ 7 ];
3489 r[ 6 ] = m[ 2 ];
3490 r[ 7 ] = m[ 5 ];
3491 r[ 8 ] = m[ 8 ];
3492
3493 return this;
3494
3495 },
3496
3497 setUvTransform: function ( tx, ty, sx, sy, rotation, cx, cy ) {
3498
3499 var c = Math.cos( rotation );
3500 var s = Math.sin( rotation );
3501
3502 this.set(
3503 sx * c, sx * s, - sx * ( c * cx + s * cy ) + cx + tx,
3504 - sy * s, sy * c, - sy * ( - s * cx + c * cy ) + cy + ty,
3505 0, 0, 1
3506 );
3507
3508 },
3509
3510 scale: function ( sx, sy ) {
3511
3512 var te = this.elements;
3513
3514 te[ 0 ] *= sx; te[ 3 ] *= sx; te[ 6 ] *= sx;
3515 te[ 1 ] *= sy; te[ 4 ] *= sy; te[ 7 ] *= sy;
3516
3517 return this;
3518
3519 },
3520
3521 rotate: function ( theta ) {
3522
3523 var c = Math.cos( theta );
3524 var s = Math.sin( theta );
3525
3526 var te = this.elements;
3527
3528 var a11 = te[ 0 ], a12 = te[ 3 ], a13 = te[ 6 ];
3529 var a21 = te[ 1 ], a22 = te[ 4 ], a23 = te[ 7 ];
3530
3531 te[ 0 ] = c * a11 + s * a21;
3532 te[ 3 ] = c * a12 + s * a22;
3533 te[ 6 ] = c * a13 + s * a23;
3534
3535 te[ 1 ] = - s * a11 + c * a21;
3536 te[ 4 ] = - s * a12 + c * a22;
3537 te[ 7 ] = - s * a13 + c * a23;
3538
3539 return this;
3540
3541 },
3542
3543 translate: function ( tx, ty ) {
3544
3545 var te = this.elements;
3546
3547 te[ 0 ] += tx * te[ 2 ]; te[ 3 ] += tx * te[ 5 ]; te[ 6 ] += tx * te[ 8 ];
3548 te[ 1 ] += ty * te[ 2 ]; te[ 4 ] += ty * te[ 5 ]; te[ 7 ] += ty * te[ 8 ];
3549
3550 return this;
3551
3552 },
3553
3554 equals: function ( matrix ) {
3555
3556 var te = this.elements;
3557 var me = matrix.elements;
3558
3559 for ( var i = 0; i < 9; i ++ ) {
3560
3561 if ( te[ i ] !== me[ i ] ) return false;
3562
3563 }
3564
3565 return true;
3566
3567 },
3568
3569 fromArray: function ( array, offset ) {
3570
3571 if ( offset === undefined ) offset = 0;
3572
3573 for ( var i = 0; i < 9; i ++ ) {
3574
3575 this.elements[ i ] = array[ i + offset ];
3576
3577 }
3578
3579 return this;
3580
3581 },
3582
3583 toArray: function ( array, offset ) {
3584
3585 if ( array === undefined ) array = [];
3586 if ( offset === undefined ) offset = 0;
3587
3588 var te = this.elements;
3589
3590 array[ offset ] = te[ 0 ];
3591 array[ offset + 1 ] = te[ 1 ];
3592 array[ offset + 2 ] = te[ 2 ];
3593
3594 array[ offset + 3 ] = te[ 3 ];
3595 array[ offset + 4 ] = te[ 4 ];
3596 array[ offset + 5 ] = te[ 5 ];
3597
3598 array[ offset + 6 ] = te[ 6 ];
3599 array[ offset + 7 ] = te[ 7 ];
3600 array[ offset + 8 ] = te[ 8 ];
3601
3602 return array;
3603
3604 }
3605
3606 } );
3607
3608 /**
3609 * @author mrdoob / http://mrdoob.com/
3610 * @author alteredq / http://alteredqualia.com/
3611 * @author szimek / https://github.com/szimek/
3612 */
3613
3614 var textureId = 0;
3615
3616 function Texture( image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) {
3617
3618 Object.defineProperty( this, 'id', { value: textureId ++ } );
3619
3620 this.uuid = _Math.generateUUID();
3621
3622 this.name = '';
3623
3624 this.image = image !== undefined ? image : Texture.DEFAULT_IMAGE;
3625 this.mipmaps = [];
3626
3627 this.mapping = mapping !== undefined ? mapping : Texture.DEFAULT_MAPPING;
3628
3629 this.wrapS = wrapS !== undefined ? wrapS : ClampToEdgeWrapping;
3630 this.wrapT = wrapT !== undefined ? wrapT : ClampToEdgeWrapping;
3631
3632 this.magFilter = magFilter !== undefined ? magFilter : LinearFilter;
3633 this.minFilter = minFilter !== undefined ? minFilter : LinearMipMapLinearFilter;
3634
3635 this.anisotropy = anisotropy !== undefined ? anisotropy : 1;
3636
3637 this.format = format !== undefined ? format : RGBAFormat;
3638 this.type = type !== undefined ? type : UnsignedByteType;
3639
3640 this.offset = new Vector2( 0, 0 );
3641 this.repeat = new Vector2( 1, 1 );
3642 this.center = new Vector2( 0, 0 );
3643 this.rotation = 0;
3644
3645 this.matrixAutoUpdate = true;
3646 this.matrix = new Matrix3();
3647
3648 this.generateMipmaps = true;
3649 this.premultiplyAlpha = false;
3650 this.flipY = true;
3651 this.unpackAlignment = 4; // valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml)
3652
3653 // Values of encoding !== THREE.LinearEncoding only supported on map, envMap and emissiveMap.
3654 //
3655 // Also changing the encoding after already used by a Material will not automatically make the Material
3656 // update. You need to explicitly call Material.needsUpdate to trigger it to recompile.
3657 this.encoding = encoding !== undefined ? encoding : LinearEncoding;
3658
3659 this.version = 0;
3660 this.onUpdate = null;
3661
3662 }
3663
3664 Texture.DEFAULT_IMAGE = undefined;
3665 Texture.DEFAULT_MAPPING = UVMapping;
3666
3667 Texture.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
3668
3669 constructor: Texture,
3670
3671 isTexture: true,
3672
3673 updateMatrix: function () {
3674
3675 this.matrix.setUvTransform( this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y );
3676
3677 },
3678
3679 clone: function () {
3680
3681 return new this.constructor().copy( this );
3682
3683 },
3684
3685 copy: function ( source ) {
3686
3687 this.name = source.name;
3688
3689 this.image = source.image;
3690 this.mipmaps = source.mipmaps.slice( 0 );
3691
3692 this.mapping = source.mapping;
3693
3694 this.wrapS = source.wrapS;
3695 this.wrapT = source.wrapT;
3696
3697 this.magFilter = source.magFilter;
3698 this.minFilter = source.minFilter;
3699
3700 this.anisotropy = source.anisotropy;
3701
3702 this.format = source.format;
3703 this.type = source.type;
3704
3705 this.offset.copy( source.offset );
3706 this.repeat.copy( source.repeat );
3707 this.center.copy( source.center );
3708 this.rotation = source.rotation;
3709
3710 this.matrixAutoUpdate = source.matrixAutoUpdate;
3711 this.matrix.copy( source.matrix );
3712
3713 this.generateMipmaps = source.generateMipmaps;
3714 this.premultiplyAlpha = source.premultiplyAlpha;
3715 this.flipY = source.flipY;
3716 this.unpackAlignment = source.unpackAlignment;
3717 this.encoding = source.encoding;
3718
3719 return this;
3720
3721 },
3722
3723 toJSON: function ( meta ) {
3724
3725 var isRootObject = ( meta === undefined || typeof meta === 'string' );
3726
3727 if ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) {
3728
3729 return meta.textures[ this.uuid ];
3730
3731 }
3732
3733 function getDataURL( image ) {
3734
3735 var canvas;
3736
3737 if ( image instanceof HTMLCanvasElement ) {
3738
3739 canvas = image;
3740
3741 } else {
3742
3743 canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
3744 canvas.width = image.width;
3745 canvas.height = image.height;
3746
3747 var context = canvas.getContext( '2d' );
3748
3749 if ( image instanceof ImageData ) {
3750
3751 context.putImageData( image, 0, 0 );
3752
3753 } else {
3754
3755 context.drawImage( image, 0, 0, image.width, image.height );
3756
3757 }
3758
3759 }
3760
3761 if ( canvas.width > 2048 || canvas.height > 2048 ) {
3762
3763 return canvas.toDataURL( 'image/jpeg', 0.6 );
3764
3765 } else {
3766
3767 return canvas.toDataURL( 'image/png' );
3768
3769 }
3770
3771 }
3772
3773 var output = {
3774
3775 metadata: {
3776 version: 4.5,
3777 type: 'Texture',
3778 generator: 'Texture.toJSON'
3779 },
3780
3781 uuid: this.uuid,
3782 name: this.name,
3783
3784 mapping: this.mapping,
3785
3786 repeat: [ this.repeat.x, this.repeat.y ],
3787 offset: [ this.offset.x, this.offset.y ],
3788 center: [ this.center.x, this.center.y ],
3789 rotation: this.rotation,
3790
3791 wrap: [ this.wrapS, this.wrapT ],
3792
3793 format: this.format,
3794 minFilter: this.minFilter,
3795 magFilter: this.magFilter,
3796 anisotropy: this.anisotropy,
3797
3798 flipY: this.flipY
3799
3800 };
3801
3802 if ( this.image !== undefined ) {
3803
3804 // TODO: Move to THREE.Image
3805
3806 var image = this.image;
3807
3808 if ( image.uuid === undefined ) {
3809
3810 image.uuid = _Math.generateUUID(); // UGH
3811
3812 }
3813
3814 if ( ! isRootObject && meta.images[ image.uuid ] === undefined ) {
3815
3816 meta.images[ image.uuid ] = {
3817 uuid: image.uuid,
3818 url: getDataURL( image )
3819 };
3820
3821 }
3822
3823 output.image = image.uuid;
3824
3825 }
3826
3827 if ( ! isRootObject ) {
3828
3829 meta.textures[ this.uuid ] = output;
3830
3831 }
3832
3833 return output;
3834
3835 },
3836
3837 dispose: function () {
3838
3839 this.dispatchEvent( { type: 'dispose' } );
3840
3841 },
3842
3843 transformUv: function ( uv ) {
3844
3845 if ( this.mapping !== UVMapping ) return;
3846
3847 uv.applyMatrix3( this.matrix );
3848
3849 if ( uv.x < 0 || uv.x > 1 ) {
3850
3851 switch ( this.wrapS ) {
3852
3853 case RepeatWrapping:
3854
3855 uv.x = uv.x - Math.floor( uv.x );
3856 break;
3857
3858 case ClampToEdgeWrapping:
3859
3860 uv.x = uv.x < 0 ? 0 : 1;
3861 break;
3862
3863 case MirroredRepeatWrapping:
3864
3865 if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) {
3866
3867 uv.x = Math.ceil( uv.x ) - uv.x;
3868
3869 } else {
3870
3871 uv.x = uv.x - Math.floor( uv.x );
3872
3873 }
3874 break;
3875
3876 }
3877
3878 }
3879
3880 if ( uv.y < 0 || uv.y > 1 ) {
3881
3882 switch ( this.wrapT ) {
3883
3884 case RepeatWrapping:
3885
3886 uv.y = uv.y - Math.floor( uv.y );
3887 break;
3888
3889 case ClampToEdgeWrapping:
3890
3891 uv.y = uv.y < 0 ? 0 : 1;
3892 break;
3893
3894 case MirroredRepeatWrapping:
3895
3896 if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) {
3897
3898 uv.y = Math.ceil( uv.y ) - uv.y;
3899
3900 } else {
3901
3902 uv.y = uv.y - Math.floor( uv.y );
3903
3904 }
3905 break;
3906
3907 }
3908
3909 }
3910
3911 if ( this.flipY ) {
3912
3913 uv.y = 1 - uv.y;
3914
3915 }
3916
3917 }
3918
3919 } );
3920
3921 Object.defineProperty( Texture.prototype, "needsUpdate", {
3922
3923 set: function ( value ) {
3924
3925 if ( value === true ) this.version ++;
3926
3927 }
3928
3929 } );
3930
3931 /**
3932 * @author supereggbert / http://www.paulbrunt.co.uk/
3933 * @author philogb / http://blog.thejit.org/
3934 * @author mikael emtinger / http://gomo.se/
3935 * @author egraether / http://egraether.com/
3936 * @author WestLangley / http://github.com/WestLangley
3937 */
3938
3939 function Vector4( x, y, z, w ) {
3940
3941 this.x = x || 0;
3942 this.y = y || 0;
3943 this.z = z || 0;
3944 this.w = ( w !== undefined ) ? w : 1;
3945
3946 }
3947
3948 Object.assign( Vector4.prototype, {
3949
3950 isVector4: true,
3951
3952 set: function ( x, y, z, w ) {
3953
3954 this.x = x;
3955 this.y = y;
3956 this.z = z;
3957 this.w = w;
3958
3959 return this;
3960
3961 },
3962
3963 setScalar: function ( scalar ) {
3964
3965 this.x = scalar;
3966 this.y = scalar;
3967 this.z = scalar;
3968 this.w = scalar;
3969
3970 return this;
3971
3972 },
3973
3974 setX: function ( x ) {
3975
3976 this.x = x;
3977
3978 return this;
3979
3980 },
3981
3982 setY: function ( y ) {
3983
3984 this.y = y;
3985
3986 return this;
3987
3988 },
3989
3990 setZ: function ( z ) {
3991
3992 this.z = z;
3993
3994 return this;
3995
3996 },
3997
3998 setW: function ( w ) {
3999
4000 this.w = w;
4001
4002 return this;
4003
4004 },
4005
4006 setComponent: function ( index, value ) {
4007
4008 switch ( index ) {
4009
4010 case 0: this.x = value; break;
4011 case 1: this.y = value; break;
4012 case 2: this.z = value; break;
4013 case 3: this.w = value; break;
4014 default: throw new Error( 'index is out of range: ' + index );
4015
4016 }
4017
4018 return this;
4019
4020 },
4021
4022 getComponent: function ( index ) {
4023
4024 switch ( index ) {
4025
4026 case 0: return this.x;
4027 case 1: return this.y;
4028 case 2: return this.z;
4029 case 3: return this.w;
4030 default: throw new Error( 'index is out of range: ' + index );
4031
4032 }
4033
4034 },
4035
4036 clone: function () {
4037
4038 return new this.constructor( this.x, this.y, this.z, this.w );
4039
4040 },
4041
4042 copy: function ( v ) {
4043
4044 this.x = v.x;
4045 this.y = v.y;
4046 this.z = v.z;
4047 this.w = ( v.w !== undefined ) ? v.w : 1;
4048
4049 return this;
4050
4051 },
4052
4053 add: function ( v, w ) {
4054
4055 if ( w !== undefined ) {
4056
4057 console.warn( 'THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
4058 return this.addVectors( v, w );
4059
4060 }
4061
4062 this.x += v.x;
4063 this.y += v.y;
4064 this.z += v.z;
4065 this.w += v.w;
4066
4067 return this;
4068
4069 },
4070
4071 addScalar: function ( s ) {
4072
4073 this.x += s;
4074 this.y += s;
4075 this.z += s;
4076 this.w += s;
4077
4078 return this;
4079
4080 },
4081
4082 addVectors: function ( a, b ) {
4083
4084 this.x = a.x + b.x;
4085 this.y = a.y + b.y;
4086 this.z = a.z + b.z;
4087 this.w = a.w + b.w;
4088
4089 return this;
4090
4091 },
4092
4093 addScaledVector: function ( v, s ) {
4094
4095 this.x += v.x * s;
4096 this.y += v.y * s;
4097 this.z += v.z * s;
4098 this.w += v.w * s;
4099
4100 return this;
4101
4102 },
4103
4104 sub: function ( v, w ) {
4105
4106 if ( w !== undefined ) {
4107
4108 console.warn( 'THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
4109 return this.subVectors( v, w );
4110
4111 }
4112
4113 this.x -= v.x;
4114 this.y -= v.y;
4115 this.z -= v.z;
4116 this.w -= v.w;
4117
4118 return this;
4119
4120 },
4121
4122 subScalar: function ( s ) {
4123
4124 this.x -= s;
4125 this.y -= s;
4126 this.z -= s;
4127 this.w -= s;
4128
4129 return this;
4130
4131 },
4132
4133 subVectors: function ( a, b ) {
4134
4135 this.x = a.x - b.x;
4136 this.y = a.y - b.y;
4137 this.z = a.z - b.z;
4138 this.w = a.w - b.w;
4139
4140 return this;
4141
4142 },
4143
4144 multiplyScalar: function ( scalar ) {
4145
4146 this.x *= scalar;
4147 this.y *= scalar;
4148 this.z *= scalar;
4149 this.w *= scalar;
4150
4151 return this;
4152
4153 },
4154
4155 applyMatrix4: function ( m ) {
4156
4157 var x = this.x, y = this.y, z = this.z, w = this.w;
4158 var e = m.elements;
4159
4160 this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w;
4161 this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w;
4162 this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w;
4163 this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w;
4164
4165 return this;
4166
4167 },
4168
4169 divideScalar: function ( scalar ) {
4170
4171 return this.multiplyScalar( 1 / scalar );
4172
4173 },
4174
4175 setAxisAngleFromQuaternion: function ( q ) {
4176
4177 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm
4178
4179 // q is assumed to be normalized
4180
4181 this.w = 2 * Math.acos( q.w );
4182
4183 var s = Math.sqrt( 1 - q.w * q.w );
4184
4185 if ( s < 0.0001 ) {
4186
4187 this.x = 1;
4188 this.y = 0;
4189 this.z = 0;
4190
4191 } else {
4192
4193 this.x = q.x / s;
4194 this.y = q.y / s;
4195 this.z = q.z / s;
4196
4197 }
4198
4199 return this;
4200
4201 },
4202
4203 setAxisAngleFromRotationMatrix: function ( m ) {
4204
4205 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm
4206
4207 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
4208
4209 var angle, x, y, z, // variables for result
4210 epsilon = 0.01, // margin to allow for rounding errors
4211 epsilon2 = 0.1, // margin to distinguish between 0 and 180 degrees
4212
4213 te = m.elements,
4214
4215 m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
4216 m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
4217 m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
4218
4219 if ( ( Math.abs( m12 - m21 ) < epsilon ) &&
4220 ( Math.abs( m13 - m31 ) < epsilon ) &&
4221 ( Math.abs( m23 - m32 ) < epsilon ) ) {
4222
4223 // singularity found
4224 // first check for identity matrix which must have +1 for all terms
4225 // in leading diagonal and zero in other terms
4226
4227 if ( ( Math.abs( m12 + m21 ) < epsilon2 ) &&
4228 ( Math.abs( m13 + m31 ) < epsilon2 ) &&
4229 ( Math.abs( m23 + m32 ) < epsilon2 ) &&
4230 ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) {
4231
4232 // this singularity is identity matrix so angle = 0
4233
4234 this.set( 1, 0, 0, 0 );
4235
4236 return this; // zero angle, arbitrary axis
4237
4238 }
4239
4240 // otherwise this singularity is angle = 180
4241
4242 angle = Math.PI;
4243
4244 var xx = ( m11 + 1 ) / 2;
4245 var yy = ( m22 + 1 ) / 2;
4246 var zz = ( m33 + 1 ) / 2;
4247 var xy = ( m12 + m21 ) / 4;
4248 var xz = ( m13 + m31 ) / 4;
4249 var yz = ( m23 + m32 ) / 4;
4250
4251 if ( ( xx > yy ) && ( xx > zz ) ) {
4252
4253 // m11 is the largest diagonal term
4254
4255 if ( xx < epsilon ) {
4256
4257 x = 0;
4258 y = 0.707106781;
4259 z = 0.707106781;
4260
4261 } else {
4262
4263 x = Math.sqrt( xx );
4264 y = xy / x;
4265 z = xz / x;
4266
4267 }
4268
4269 } else if ( yy > zz ) {
4270
4271 // m22 is the largest diagonal term
4272
4273 if ( yy < epsilon ) {
4274
4275 x = 0.707106781;
4276 y = 0;
4277 z = 0.707106781;
4278
4279 } else {
4280
4281 y = Math.sqrt( yy );
4282 x = xy / y;
4283 z = yz / y;
4284
4285 }
4286
4287 } else {
4288
4289 // m33 is the largest diagonal term so base result on this
4290
4291 if ( zz < epsilon ) {
4292
4293 x = 0.707106781;
4294 y = 0.707106781;
4295 z = 0;
4296
4297 } else {
4298
4299 z = Math.sqrt( zz );
4300 x = xz / z;
4301 y = yz / z;
4302
4303 }
4304
4305 }
4306
4307 this.set( x, y, z, angle );
4308
4309 return this; // return 180 deg rotation
4310
4311 }
4312
4313 // as we have reached here there are no singularities so we can handle normally
4314
4315 var s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) +
4316 ( m13 - m31 ) * ( m13 - m31 ) +
4317 ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize
4318
4319 if ( Math.abs( s ) < 0.001 ) s = 1;
4320
4321 // prevent divide by zero, should not happen if matrix is orthogonal and should be
4322 // caught by singularity test above, but I've left it in just in case
4323
4324 this.x = ( m32 - m23 ) / s;
4325 this.y = ( m13 - m31 ) / s;
4326 this.z = ( m21 - m12 ) / s;
4327 this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 );
4328
4329 return this;
4330
4331 },
4332
4333 min: function ( v ) {
4334
4335 this.x = Math.min( this.x, v.x );
4336 this.y = Math.min( this.y, v.y );
4337 this.z = Math.min( this.z, v.z );
4338 this.w = Math.min( this.w, v.w );
4339
4340 return this;
4341
4342 },
4343
4344 max: function ( v ) {
4345
4346 this.x = Math.max( this.x, v.x );
4347 this.y = Math.max( this.y, v.y );
4348 this.z = Math.max( this.z, v.z );
4349 this.w = Math.max( this.w, v.w );
4350
4351 return this;
4352
4353 },
4354
4355 clamp: function ( min, max ) {
4356
4357 // assumes min < max, componentwise
4358
4359 this.x = Math.max( min.x, Math.min( max.x, this.x ) );
4360 this.y = Math.max( min.y, Math.min( max.y, this.y ) );
4361 this.z = Math.max( min.z, Math.min( max.z, this.z ) );
4362 this.w = Math.max( min.w, Math.min( max.w, this.w ) );
4363
4364 return this;
4365
4366 },
4367
4368 clampScalar: function () {
4369
4370 var min, max;
4371
4372 return function clampScalar( minVal, maxVal ) {
4373
4374 if ( min === undefined ) {
4375
4376 min = new Vector4();
4377 max = new Vector4();
4378
4379 }
4380
4381 min.set( minVal, minVal, minVal, minVal );
4382 max.set( maxVal, maxVal, maxVal, maxVal );
4383
4384 return this.clamp( min, max );
4385
4386 };
4387
4388 }(),
4389
4390 clampLength: function ( min, max ) {
4391
4392 var length = this.length();
4393
4394 return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
4395
4396 },
4397
4398 floor: function () {
4399
4400 this.x = Math.floor( this.x );
4401 this.y = Math.floor( this.y );
4402 this.z = Math.floor( this.z );
4403 this.w = Math.floor( this.w );
4404
4405 return this;
4406
4407 },
4408
4409 ceil: function () {
4410
4411 this.x = Math.ceil( this.x );
4412 this.y = Math.ceil( this.y );
4413 this.z = Math.ceil( this.z );
4414 this.w = Math.ceil( this.w );
4415
4416 return this;
4417
4418 },
4419
4420 round: function () {
4421
4422 this.x = Math.round( this.x );
4423 this.y = Math.round( this.y );
4424 this.z = Math.round( this.z );
4425 this.w = Math.round( this.w );
4426
4427 return this;
4428
4429 },
4430
4431 roundToZero: function () {
4432
4433 this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
4434 this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
4435 this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );
4436 this.w = ( this.w < 0 ) ? Math.ceil( this.w ) : Math.floor( this.w );
4437
4438 return this;
4439
4440 },
4441
4442 negate: function () {
4443
4444 this.x = - this.x;
4445 this.y = - this.y;
4446 this.z = - this.z;
4447 this.w = - this.w;
4448
4449 return this;
4450
4451 },
4452
4453 dot: function ( v ) {
4454
4455 return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;
4456
4457 },
4458
4459 lengthSq: function () {
4460
4461 return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
4462
4463 },
4464
4465 length: function () {
4466
4467 return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w );
4468
4469 },
4470
4471 manhattanLength: function () {
4472
4473 return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w );
4474
4475 },
4476
4477 normalize: function () {
4478
4479 return this.divideScalar( this.length() || 1 );
4480
4481 },
4482
4483 setLength: function ( length ) {
4484
4485 return this.normalize().multiplyScalar( length );
4486
4487 },
4488
4489 lerp: function ( v, alpha ) {
4490
4491 this.x += ( v.x - this.x ) * alpha;
4492 this.y += ( v.y - this.y ) * alpha;
4493 this.z += ( v.z - this.z ) * alpha;
4494 this.w += ( v.w - this.w ) * alpha;
4495
4496 return this;
4497
4498 },
4499
4500 lerpVectors: function ( v1, v2, alpha ) {
4501
4502 return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );
4503
4504 },
4505
4506 equals: function ( v ) {
4507
4508 return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) );
4509
4510 },
4511
4512 fromArray: function ( array, offset ) {
4513
4514 if ( offset === undefined ) offset = 0;
4515
4516 this.x = array[ offset ];
4517 this.y = array[ offset + 1 ];
4518 this.z = array[ offset + 2 ];
4519 this.w = array[ offset + 3 ];
4520
4521 return this;
4522
4523 },
4524
4525 toArray: function ( array, offset ) {
4526
4527 if ( array === undefined ) array = [];
4528 if ( offset === undefined ) offset = 0;
4529
4530 array[ offset ] = this.x;
4531 array[ offset + 1 ] = this.y;
4532 array[ offset + 2 ] = this.z;
4533 array[ offset + 3 ] = this.w;
4534
4535 return array;
4536
4537 },
4538
4539 fromBufferAttribute: function ( attribute, index, offset ) {
4540
4541 if ( offset !== undefined ) {
4542
4543 console.warn( 'THREE.Vector4: offset has been removed from .fromBufferAttribute().' );
4544
4545 }
4546
4547 this.x = attribute.getX( index );
4548 this.y = attribute.getY( index );
4549 this.z = attribute.getZ( index );
4550 this.w = attribute.getW( index );
4551
4552 return this;
4553
4554 }
4555
4556 } );
4557
4558 /**
4559 * @author szimek / https://github.com/szimek/
4560 * @author alteredq / http://alteredqualia.com/
4561 * @author Marius Kintel / https://github.com/kintel
4562 */
4563
4564 /*
4565 In options, we can specify:
4566 * Texture parameters for an auto-generated target texture
4567 * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers
4568 */
4569 function WebGLRenderTarget( width, height, options ) {
4570
4571 this.width = width;
4572 this.height = height;
4573
4574 this.scissor = new Vector4( 0, 0, width, height );
4575 this.scissorTest = false;
4576
4577 this.viewport = new Vector4( 0, 0, width, height );
4578
4579 options = options || {};
4580
4581 if ( options.minFilter === undefined ) options.minFilter = LinearFilter;
4582
4583 this.texture = new Texture( undefined, undefined, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding );
4584
4585 this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true;
4586 this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : true;
4587 this.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null;
4588
4589 }
4590
4591 WebGLRenderTarget.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
4592
4593 constructor: WebGLRenderTarget,
4594
4595 isWebGLRenderTarget: true,
4596
4597 setSize: function ( width, height ) {
4598
4599 if ( this.width !== width || this.height !== height ) {
4600
4601 this.width = width;
4602 this.height = height;
4603
4604 this.dispose();
4605
4606 }
4607
4608 this.viewport.set( 0, 0, width, height );
4609 this.scissor.set( 0, 0, width, height );
4610
4611 },
4612
4613 clone: function () {
4614
4615 return new this.constructor().copy( this );
4616
4617 },
4618
4619 copy: function ( source ) {
4620
4621 this.width = source.width;
4622 this.height = source.height;
4623
4624 this.viewport.copy( source.viewport );
4625
4626 this.texture = source.texture.clone();
4627
4628 this.depthBuffer = source.depthBuffer;
4629 this.stencilBuffer = source.stencilBuffer;
4630 this.depthTexture = source.depthTexture;
4631
4632 return this;
4633
4634 },
4635
4636 dispose: function () {
4637
4638 this.dispatchEvent( { type: 'dispose' } );
4639
4640 }
4641
4642 } );
4643
4644 /**
4645 * @author alteredq / http://alteredqualia.com
4646 */
4647
4648 function WebGLRenderTargetCube( width, height, options ) {
4649
4650 WebGLRenderTarget.call( this, width, height, options );
4651
4652 this.activeCubeFace = 0; // PX 0, NX 1, PY 2, NY 3, PZ 4, NZ 5
4653 this.activeMipMapLevel = 0;
4654
4655 }
4656
4657 WebGLRenderTargetCube.prototype = Object.create( WebGLRenderTarget.prototype );
4658 WebGLRenderTargetCube.prototype.constructor = WebGLRenderTargetCube;
4659
4660 WebGLRenderTargetCube.prototype.isWebGLRenderTargetCube = true;
4661
4662 /**
4663 * @author alteredq / http://alteredqualia.com/
4664 */
4665
4666 function DataTexture( data, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) {
4667
4668 Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
4669
4670 this.image = { data: data, width: width, height: height };
4671
4672 this.magFilter = magFilter !== undefined ? magFilter : NearestFilter;
4673 this.minFilter = minFilter !== undefined ? minFilter : NearestFilter;
4674
4675 this.generateMipmaps = false;
4676 this.flipY = false;
4677 this.unpackAlignment = 1;
4678
4679 }
4680
4681 DataTexture.prototype = Object.create( Texture.prototype );
4682 DataTexture.prototype.constructor = DataTexture;
4683
4684 DataTexture.prototype.isDataTexture = true;
4685
4686 /**
4687 * @author bhouston / http://clara.io
4688 * @author WestLangley / http://github.com/WestLangley
4689 */
4690
4691 function Box3( min, max ) {
4692
4693 this.min = ( min !== undefined ) ? min : new Vector3( + Infinity, + Infinity, + Infinity );
4694 this.max = ( max !== undefined ) ? max : new Vector3( - Infinity, - Infinity, - Infinity );
4695
4696 }
4697
4698 Object.assign( Box3.prototype, {
4699
4700 isBox3: true,
4701
4702 set: function ( min, max ) {
4703
4704 this.min.copy( min );
4705 this.max.copy( max );
4706
4707 return this;
4708
4709 },
4710
4711 setFromArray: function ( array ) {
4712
4713 var minX = + Infinity;
4714 var minY = + Infinity;
4715 var minZ = + Infinity;
4716
4717 var maxX = - Infinity;
4718 var maxY = - Infinity;
4719 var maxZ = - Infinity;
4720
4721 for ( var i = 0, l = array.length; i < l; i += 3 ) {
4722
4723 var x = array[ i ];
4724 var y = array[ i + 1 ];
4725 var z = array[ i + 2 ];
4726
4727 if ( x < minX ) minX = x;
4728 if ( y < minY ) minY = y;
4729 if ( z < minZ ) minZ = z;
4730
4731 if ( x > maxX ) maxX = x;
4732 if ( y > maxY ) maxY = y;
4733 if ( z > maxZ ) maxZ = z;
4734
4735 }
4736
4737 this.min.set( minX, minY, minZ );
4738 this.max.set( maxX, maxY, maxZ );
4739
4740 return this;
4741
4742 },
4743
4744 setFromBufferAttribute: function ( attribute ) {
4745
4746 var minX = + Infinity;
4747 var minY = + Infinity;
4748 var minZ = + Infinity;
4749
4750 var maxX = - Infinity;
4751 var maxY = - Infinity;
4752 var maxZ = - Infinity;
4753
4754 for ( var i = 0, l = attribute.count; i < l; i ++ ) {
4755
4756 var x = attribute.getX( i );
4757 var y = attribute.getY( i );
4758 var z = attribute.getZ( i );
4759
4760 if ( x < minX ) minX = x;
4761 if ( y < minY ) minY = y;
4762 if ( z < minZ ) minZ = z;
4763
4764 if ( x > maxX ) maxX = x;
4765 if ( y > maxY ) maxY = y;
4766 if ( z > maxZ ) maxZ = z;
4767
4768 }
4769
4770 this.min.set( minX, minY, minZ );
4771 this.max.set( maxX, maxY, maxZ );
4772
4773 return this;
4774
4775 },
4776
4777 setFromPoints: function ( points ) {
4778
4779 this.makeEmpty();
4780
4781 for ( var i = 0, il = points.length; i < il; i ++ ) {
4782
4783 this.expandByPoint( points[ i ] );
4784
4785 }
4786
4787 return this;
4788
4789 },
4790
4791 setFromCenterAndSize: function () {
4792
4793 var v1 = new Vector3();
4794
4795 return function setFromCenterAndSize( center, size ) {
4796
4797 var halfSize = v1.copy( size ).multiplyScalar( 0.5 );
4798
4799 this.min.copy( center ).sub( halfSize );
4800 this.max.copy( center ).add( halfSize );
4801
4802 return this;
4803
4804 };
4805
4806 }(),
4807
4808 setFromObject: function ( object ) {
4809
4810 this.makeEmpty();
4811
4812 return this.expandByObject( object );
4813
4814 },
4815
4816 clone: function () {
4817
4818 return new this.constructor().copy( this );
4819
4820 },
4821
4822 copy: function ( box ) {
4823
4824 this.min.copy( box.min );
4825 this.max.copy( box.max );
4826
4827 return this;
4828
4829 },
4830
4831 makeEmpty: function () {
4832
4833 this.min.x = this.min.y = this.min.z = + Infinity;
4834 this.max.x = this.max.y = this.max.z = - Infinity;
4835
4836 return this;
4837
4838 },
4839
4840 isEmpty: function () {
4841
4842 // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
4843
4844 return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ) || ( this.max.z < this.min.z );
4845
4846 },
4847
4848 getCenter: function ( target ) {
4849
4850 if ( target === undefined ) {
4851
4852 console.warn( 'THREE.Box3: .getCenter() target is now required' );
4853 target = new Vector3();
4854
4855 }
4856
4857 return this.isEmpty() ? target.set( 0, 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 );
4858
4859 },
4860
4861 getSize: function ( target ) {
4862
4863 if ( target === undefined ) {
4864
4865 console.warn( 'THREE.Box3: .getSize() target is now required' );
4866 target = new Vector3();
4867
4868 }
4869
4870 return this.isEmpty() ? target.set( 0, 0, 0 ) : target.subVectors( this.max, this.min );
4871
4872 },
4873
4874 expandByPoint: function ( point ) {
4875
4876 this.min.min( point );
4877 this.max.max( point );
4878
4879 return this;
4880
4881 },
4882
4883 expandByVector: function ( vector ) {
4884
4885 this.min.sub( vector );
4886 this.max.add( vector );
4887
4888 return this;
4889
4890 },
4891
4892 expandByScalar: function ( scalar ) {
4893
4894 this.min.addScalar( - scalar );
4895 this.max.addScalar( scalar );
4896
4897 return this;
4898
4899 },
4900
4901 expandByObject: function () {
4902
4903 // Computes the world-axis-aligned bounding box of an object (including its children),
4904 // accounting for both the object's, and children's, world transforms
4905
4906 var scope, i, l;
4907
4908 var v1 = new Vector3();
4909
4910 function traverse( node ) {
4911
4912 var geometry = node.geometry;
4913
4914 if ( geometry !== undefined ) {
4915
4916 if ( geometry.isGeometry ) {
4917
4918 var vertices = geometry.vertices;
4919
4920 for ( i = 0, l = vertices.length; i < l; i ++ ) {
4921
4922 v1.copy( vertices[ i ] );
4923 v1.applyMatrix4( node.matrixWorld );
4924
4925 scope.expandByPoint( v1 );
4926
4927 }
4928
4929 } else if ( geometry.isBufferGeometry ) {
4930
4931 var attribute = geometry.attributes.position;
4932
4933 if ( attribute !== undefined ) {
4934
4935 for ( i = 0, l = attribute.count; i < l; i ++ ) {
4936
4937 v1.fromBufferAttribute( attribute, i ).applyMatrix4( node.matrixWorld );
4938
4939 scope.expandByPoint( v1 );
4940
4941 }
4942
4943 }
4944
4945 }
4946
4947 }
4948
4949 }
4950
4951 return function expandByObject( object ) {
4952
4953 scope = this;
4954
4955 object.updateMatrixWorld( true );
4956
4957 object.traverse( traverse );
4958
4959 return this;
4960
4961 };
4962
4963 }(),
4964
4965 containsPoint: function ( point ) {
4966
4967 return point.x < this.min.x || point.x > this.max.x ||
4968 point.y < this.min.y || point.y > this.max.y ||
4969 point.z < this.min.z || point.z > this.max.z ? false : true;
4970
4971 },
4972
4973 containsBox: function ( box ) {
4974
4975 return this.min.x <= box.min.x && box.max.x <= this.max.x &&
4976 this.min.y <= box.min.y && box.max.y <= this.max.y &&
4977 this.min.z <= box.min.z && box.max.z <= this.max.z;
4978
4979 },
4980
4981 getParameter: function ( point, target ) {
4982
4983 // This can potentially have a divide by zero if the box
4984 // has a size dimension of 0.
4985
4986 if ( target === undefined ) {
4987
4988 console.warn( 'THREE.Box3: .getParameter() target is now required' );
4989 target = new Vector3();
4990
4991 }
4992
4993 return target.set(
4994 ( point.x - this.min.x ) / ( this.max.x - this.min.x ),
4995 ( point.y - this.min.y ) / ( this.max.y - this.min.y ),
4996 ( point.z - this.min.z ) / ( this.max.z - this.min.z )
4997 );
4998
4999 },
5000
5001 intersectsBox: function ( box ) {
5002
5003 // using 6 splitting planes to rule out intersections.
5004 return box.max.x < this.min.x || box.min.x > this.max.x ||
5005 box.max.y < this.min.y || box.min.y > this.max.y ||
5006 box.max.z < this.min.z || box.min.z > this.max.z ? false : true;
5007
5008 },
5009
5010 intersectsSphere: ( function () {
5011
5012 var closestPoint = new Vector3();
5013
5014 return function intersectsSphere( sphere ) {
5015
5016 // Find the point on the AABB closest to the sphere center.
5017 this.clampPoint( sphere.center, closestPoint );
5018
5019 // If that point is inside the sphere, the AABB and sphere intersect.
5020 return closestPoint.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius );
5021
5022 };
5023
5024 } )(),
5025
5026 intersectsPlane: function ( plane ) {
5027
5028 // We compute the minimum and maximum dot product values. If those values
5029 // are on the same side (back or front) of the plane, then there is no intersection.
5030
5031 var min, max;
5032
5033 if ( plane.normal.x > 0 ) {
5034
5035 min = plane.normal.x * this.min.x;
5036 max = plane.normal.x * this.max.x;
5037
5038 } else {
5039
5040 min = plane.normal.x * this.max.x;
5041 max = plane.normal.x * this.min.x;
5042
5043 }
5044
5045 if ( plane.normal.y > 0 ) {
5046
5047 min += plane.normal.y * this.min.y;
5048 max += plane.normal.y * this.max.y;
5049
5050 } else {
5051
5052 min += plane.normal.y * this.max.y;
5053 max += plane.normal.y * this.min.y;
5054
5055 }
5056
5057 if ( plane.normal.z > 0 ) {
5058
5059 min += plane.normal.z * this.min.z;
5060 max += plane.normal.z * this.max.z;
5061
5062 } else {
5063
5064 min += plane.normal.z * this.max.z;
5065 max += plane.normal.z * this.min.z;
5066
5067 }
5068
5069 return ( min <= plane.constant && max >= plane.constant );
5070
5071 },
5072
5073 intersectsTriangle: ( function () {
5074
5075 // triangle centered vertices
5076 var v0 = new Vector3();
5077 var v1 = new Vector3();
5078 var v2 = new Vector3();
5079
5080 // triangle edge vectors
5081 var f0 = new Vector3();
5082 var f1 = new Vector3();
5083 var f2 = new Vector3();
5084
5085 var testAxis = new Vector3();
5086
5087 var center = new Vector3();
5088 var extents = new Vector3();
5089
5090 var triangleNormal = new Vector3();
5091
5092 function satForAxes( axes ) {
5093
5094 var i, j;
5095
5096 for ( i = 0, j = axes.length - 3; i <= j; i += 3 ) {
5097
5098 testAxis.fromArray( axes, i );
5099 // project the aabb onto the seperating axis
5100 var r = extents.x * Math.abs( testAxis.x ) + extents.y * Math.abs( testAxis.y ) + extents.z * Math.abs( testAxis.z );
5101 // project all 3 vertices of the triangle onto the seperating axis
5102 var p0 = v0.dot( testAxis );
5103 var p1 = v1.dot( testAxis );
5104 var p2 = v2.dot( testAxis );
5105 // actual test, basically see if either of the most extreme of the triangle points intersects r
5106 if ( Math.max( - Math.max( p0, p1, p2 ), Math.min( p0, p1, p2 ) ) > r ) {
5107
5108 // points of the projected triangle are outside the projected half-length of the aabb
5109 // the axis is seperating and we can exit
5110 return false;
5111
5112 }
5113
5114 }
5115
5116 return true;
5117
5118 }
5119
5120 return function intersectsTriangle( triangle ) {
5121
5122 if ( this.isEmpty() ) {
5123
5124 return false;
5125
5126 }
5127
5128 // compute box center and extents
5129 this.getCenter( center );
5130 extents.subVectors( this.max, center );
5131
5132 // translate triangle to aabb origin
5133 v0.subVectors( triangle.a, center );
5134 v1.subVectors( triangle.b, center );
5135 v2.subVectors( triangle.c, center );
5136
5137 // compute edge vectors for triangle
5138 f0.subVectors( v1, v0 );
5139 f1.subVectors( v2, v1 );
5140 f2.subVectors( v0, v2 );
5141
5142 // test against axes that are given by cross product combinations of the edges of the triangle and the edges of the aabb
5143 // 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
5144 // axis_ij = u_i x f_j (u0, u1, u2 = face normals of aabb = x,y,z axes vectors since aabb is axis aligned)
5145 var axes = [
5146 0, - f0.z, f0.y, 0, - f1.z, f1.y, 0, - f2.z, f2.y,
5147 f0.z, 0, - f0.x, f1.z, 0, - f1.x, f2.z, 0, - f2.x,
5148 - f0.y, f0.x, 0, - f1.y, f1.x, 0, - f2.y, f2.x, 0
5149 ];
5150 if ( ! satForAxes( axes ) ) {
5151
5152 return false;
5153
5154 }
5155
5156 // test 3 face normals from the aabb
5157 axes = [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ];
5158 if ( ! satForAxes( axes ) ) {
5159
5160 return false;
5161
5162 }
5163
5164 // finally testing the face normal of the triangle
5165 // use already existing triangle edge vectors here
5166 triangleNormal.crossVectors( f0, f1 );
5167 axes = [ triangleNormal.x, triangleNormal.y, triangleNormal.z ];
5168 return satForAxes( axes );
5169
5170 };
5171
5172 } )(),
5173
5174 clampPoint: function ( point, target ) {
5175
5176 if ( target === undefined ) {
5177
5178 console.warn( 'THREE.Box3: .clampPoint() target is now required' );
5179 target = new Vector3();
5180
5181 }
5182
5183 return target.copy( point ).clamp( this.min, this.max );
5184
5185 },
5186
5187 distanceToPoint: function () {
5188
5189 var v1 = new Vector3();
5190
5191 return function distanceToPoint( point ) {
5192
5193 var clampedPoint = v1.copy( point ).clamp( this.min, this.max );
5194 return clampedPoint.sub( point ).length();
5195
5196 };
5197
5198 }(),
5199
5200 getBoundingSphere: function () {
5201
5202 var v1 = new Vector3();
5203
5204 return function getBoundingSphere( target ) {
5205
5206 if ( target === undefined ) {
5207
5208 console.warn( 'THREE.Box3: .getBoundingSphere() target is now required' );
5209 target = new Sphere();
5210
5211 }
5212
5213 this.getCenter( target.center );
5214
5215 target.radius = this.getSize( v1 ).length() * 0.5;
5216
5217 return target;
5218
5219 };
5220
5221 }(),
5222
5223 intersect: function ( box ) {
5224
5225 this.min.max( box.min );
5226 this.max.min( box.max );
5227
5228 // 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.
5229 if ( this.isEmpty() ) this.makeEmpty();
5230
5231 return this;
5232
5233 },
5234
5235 union: function ( box ) {
5236
5237 this.min.min( box.min );
5238 this.max.max( box.max );
5239
5240 return this;
5241
5242 },
5243
5244 applyMatrix4: function () {
5245
5246 var points = [
5247 new Vector3(),
5248 new Vector3(),
5249 new Vector3(),
5250 new Vector3(),
5251 new Vector3(),
5252 new Vector3(),
5253 new Vector3(),
5254 new Vector3()
5255 ];
5256
5257 return function applyMatrix4( matrix ) {
5258
5259 // transform of empty box is an empty box.
5260 if ( this.isEmpty() ) return this;
5261
5262 // NOTE: I am using a binary pattern to specify all 2^3 combinations below
5263 points[ 0 ].set( this.min.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 000
5264 points[ 1 ].set( this.min.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 001
5265 points[ 2 ].set( this.min.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 010
5266 points[ 3 ].set( this.min.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 011
5267 points[ 4 ].set( this.max.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 100
5268 points[ 5 ].set( this.max.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 101
5269 points[ 6 ].set( this.max.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 110
5270 points[ 7 ].set( this.max.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 111
5271
5272 this.setFromPoints( points );
5273
5274 return this;
5275
5276 };
5277
5278 }(),
5279
5280 translate: function ( offset ) {
5281
5282 this.min.add( offset );
5283 this.max.add( offset );
5284
5285 return this;
5286
5287 },
5288
5289 equals: function ( box ) {
5290
5291 return box.min.equals( this.min ) && box.max.equals( this.max );
5292
5293 }
5294
5295 } );
5296
5297 /**
5298 * @author bhouston / http://clara.io
5299 * @author mrdoob / http://mrdoob.com/
5300 */
5301
5302 function Sphere( center, radius ) {
5303
5304 this.center = ( center !== undefined ) ? center : new Vector3();
5305 this.radius = ( radius !== undefined ) ? radius : 0;
5306
5307 }
5308
5309 Object.assign( Sphere.prototype, {
5310
5311 set: function ( center, radius ) {
5312
5313 this.center.copy( center );
5314 this.radius = radius;
5315
5316 return this;
5317
5318 },
5319
5320 setFromPoints: function () {
5321
5322 var box = new Box3();
5323
5324 return function setFromPoints( points, optionalCenter ) {
5325
5326 var center = this.center;
5327
5328 if ( optionalCenter !== undefined ) {
5329
5330 center.copy( optionalCenter );
5331
5332 } else {
5333
5334 box.setFromPoints( points ).getCenter( center );
5335
5336 }
5337
5338 var maxRadiusSq = 0;
5339
5340 for ( var i = 0, il = points.length; i < il; i ++ ) {
5341
5342 maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( points[ i ] ) );
5343
5344 }
5345
5346 this.radius = Math.sqrt( maxRadiusSq );
5347
5348 return this;
5349
5350 };
5351
5352 }(),
5353
5354 clone: function () {
5355
5356 return new this.constructor().copy( this );
5357
5358 },
5359
5360 copy: function ( sphere ) {
5361
5362 this.center.copy( sphere.center );
5363 this.radius = sphere.radius;
5364
5365 return this;
5366
5367 },
5368
5369 empty: function () {
5370
5371 return ( this.radius <= 0 );
5372
5373 },
5374
5375 containsPoint: function ( point ) {
5376
5377 return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) );
5378
5379 },
5380
5381 distanceToPoint: function ( point ) {
5382
5383 return ( point.distanceTo( this.center ) - this.radius );
5384
5385 },
5386
5387 intersectsSphere: function ( sphere ) {
5388
5389 var radiusSum = this.radius + sphere.radius;
5390
5391 return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum );
5392
5393 },
5394
5395 intersectsBox: function ( box ) {
5396
5397 return box.intersectsSphere( this );
5398
5399 },
5400
5401 intersectsPlane: function ( plane ) {
5402
5403 return Math.abs( plane.distanceToPoint( this.center ) ) <= this.radius;
5404
5405 },
5406
5407 clampPoint: function ( point, target ) {
5408
5409 var deltaLengthSq = this.center.distanceToSquared( point );
5410
5411 if ( target === undefined ) {
5412
5413 console.warn( 'THREE.Sphere: .clampPoint() target is now required' );
5414 target = new Vector3();
5415
5416 }
5417
5418 target.copy( point );
5419
5420 if ( deltaLengthSq > ( this.radius * this.radius ) ) {
5421
5422 target.sub( this.center ).normalize();
5423 target.multiplyScalar( this.radius ).add( this.center );
5424
5425 }
5426
5427 return target;
5428
5429 },
5430
5431 getBoundingBox: function ( target ) {
5432
5433 if ( target === undefined ) {
5434
5435 console.warn( 'THREE.Sphere: .getBoundingBox() target is now required' );
5436 target = new Box3();
5437
5438 }
5439
5440 target.set( this.center, this.center );
5441 target.expandByScalar( this.radius );
5442
5443 return target;
5444
5445 },
5446
5447 applyMatrix4: function ( matrix ) {
5448
5449 this.center.applyMatrix4( matrix );
5450 this.radius = this.radius * matrix.getMaxScaleOnAxis();
5451
5452 return this;
5453
5454 },
5455
5456 translate: function ( offset ) {
5457
5458 this.center.add( offset );
5459
5460 return this;
5461
5462 },
5463
5464 equals: function ( sphere ) {
5465
5466 return sphere.center.equals( this.center ) && ( sphere.radius === this.radius );
5467
5468 }
5469
5470 } );
5471
5472 /**
5473 * @author bhouston / http://clara.io
5474 */
5475
5476 function Plane( normal, constant ) {
5477
5478 // normal is assumed to be normalized
5479
5480 this.normal = ( normal !== undefined ) ? normal : new Vector3( 1, 0, 0 );
5481 this.constant = ( constant !== undefined ) ? constant : 0;
5482
5483 }
5484
5485 Object.assign( Plane.prototype, {
5486
5487 set: function ( normal, constant ) {
5488
5489 this.normal.copy( normal );
5490 this.constant = constant;
5491
5492 return this;
5493
5494 },
5495
5496 setComponents: function ( x, y, z, w ) {
5497
5498 this.normal.set( x, y, z );
5499 this.constant = w;
5500
5501 return this;
5502
5503 },
5504
5505 setFromNormalAndCoplanarPoint: function ( normal, point ) {
5506
5507 this.normal.copy( normal );
5508 this.constant = - point.dot( this.normal );
5509
5510 return this;
5511
5512 },
5513
5514 setFromCoplanarPoints: function () {
5515
5516 var v1 = new Vector3();
5517 var v2 = new Vector3();
5518
5519 return function setFromCoplanarPoints( a, b, c ) {
5520
5521 var normal = v1.subVectors( c, b ).cross( v2.subVectors( a, b ) ).normalize();
5522
5523 // Q: should an error be thrown if normal is zero (e.g. degenerate plane)?
5524
5525 this.setFromNormalAndCoplanarPoint( normal, a );
5526
5527 return this;
5528
5529 };
5530
5531 }(),
5532
5533 clone: function () {
5534
5535 return new this.constructor().copy( this );
5536
5537 },
5538
5539 copy: function ( plane ) {
5540
5541 this.normal.copy( plane.normal );
5542 this.constant = plane.constant;
5543
5544 return this;
5545
5546 },
5547
5548 normalize: function () {
5549
5550 // Note: will lead to a divide by zero if the plane is invalid.
5551
5552 var inverseNormalLength = 1.0 / this.normal.length();
5553 this.normal.multiplyScalar( inverseNormalLength );
5554 this.constant *= inverseNormalLength;
5555
5556 return this;
5557
5558 },
5559
5560 negate: function () {
5561
5562 this.constant *= - 1;
5563 this.normal.negate();
5564
5565 return this;
5566
5567 },
5568
5569 distanceToPoint: function ( point ) {
5570
5571 return this.normal.dot( point ) + this.constant;
5572
5573 },
5574
5575 distanceToSphere: function ( sphere ) {
5576
5577 return this.distanceToPoint( sphere.center ) - sphere.radius;
5578
5579 },
5580
5581 projectPoint: function ( point, target ) {
5582
5583 if ( target === undefined ) {
5584
5585 console.warn( 'THREE.Plane: .projectPoint() target is now required' );
5586 target = new Vector3();
5587
5588 }
5589
5590 return target.copy( this.normal ).multiplyScalar( - this.distanceToPoint( point ) ).add( point );
5591
5592 },
5593
5594 intersectLine: function () {
5595
5596 var v1 = new Vector3();
5597
5598 return function intersectLine( line, target ) {
5599
5600 if ( target === undefined ) {
5601
5602 console.warn( 'THREE.Plane: .intersectLine() target is now required' );
5603 target = new Vector3();
5604
5605 }
5606
5607 var direction = line.delta( v1 );
5608
5609 var denominator = this.normal.dot( direction );
5610
5611 if ( denominator === 0 ) {
5612
5613 // line is coplanar, return origin
5614 if ( this.distanceToPoint( line.start ) === 0 ) {
5615
5616 return target.copy( line.start );
5617
5618 }
5619
5620 // Unsure if this is the correct method to handle this case.
5621 return undefined;
5622
5623 }
5624
5625 var t = - ( line.start.dot( this.normal ) + this.constant ) / denominator;
5626
5627 if ( t < 0 || t > 1 ) {
5628
5629 return undefined;
5630
5631 }
5632
5633 return target.copy( direction ).multiplyScalar( t ).add( line.start );
5634
5635 };
5636
5637 }(),
5638
5639 intersectsLine: function ( line ) {
5640
5641 // Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it.
5642
5643 var startSign = this.distanceToPoint( line.start );
5644 var endSign = this.distanceToPoint( line.end );
5645
5646 return ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 );
5647
5648 },
5649
5650 intersectsBox: function ( box ) {
5651
5652 return box.intersectsPlane( this );
5653
5654 },
5655
5656 intersectsSphere: function ( sphere ) {
5657
5658 return sphere.intersectsPlane( this );
5659
5660 },
5661
5662 coplanarPoint: function ( target ) {
5663
5664 if ( target === undefined ) {
5665
5666 console.warn( 'THREE.Plane: .coplanarPoint() target is now required' );
5667 target = new Vector3();
5668
5669 }
5670
5671 return target.copy( this.normal ).multiplyScalar( - this.constant );
5672
5673 },
5674
5675 applyMatrix4: function () {
5676
5677 var v1 = new Vector3();
5678 var m1 = new Matrix3();
5679
5680 return function applyMatrix4( matrix, optionalNormalMatrix ) {
5681
5682 var normalMatrix = optionalNormalMatrix || m1.getNormalMatrix( matrix );
5683
5684 var referencePoint = this.coplanarPoint( v1 ).applyMatrix4( matrix );
5685
5686 var normal = this.normal.applyMatrix3( normalMatrix ).normalize();
5687
5688 this.constant = - referencePoint.dot( normal );
5689
5690 return this;
5691
5692 };
5693
5694 }(),
5695
5696 translate: function ( offset ) {
5697
5698 this.constant -= offset.dot( this.normal );
5699
5700 return this;
5701
5702 },
5703
5704 equals: function ( plane ) {
5705
5706 return plane.normal.equals( this.normal ) && ( plane.constant === this.constant );
5707
5708 }
5709
5710 } );
5711
5712 /**
5713 * @author mrdoob / http://mrdoob.com/
5714 * @author alteredq / http://alteredqualia.com/
5715 * @author bhouston / http://clara.io
5716 */
5717
5718 function Frustum( p0, p1, p2, p3, p4, p5 ) {
5719
5720 this.planes = [
5721
5722 ( p0 !== undefined ) ? p0 : new Plane(),
5723 ( p1 !== undefined ) ? p1 : new Plane(),
5724 ( p2 !== undefined ) ? p2 : new Plane(),
5725 ( p3 !== undefined ) ? p3 : new Plane(),
5726 ( p4 !== undefined ) ? p4 : new Plane(),
5727 ( p5 !== undefined ) ? p5 : new Plane()
5728
5729 ];
5730
5731 }
5732
5733 Object.assign( Frustum.prototype, {
5734
5735 set: function ( p0, p1, p2, p3, p4, p5 ) {
5736
5737 var planes = this.planes;
5738
5739 planes[ 0 ].copy( p0 );
5740 planes[ 1 ].copy( p1 );
5741 planes[ 2 ].copy( p2 );
5742 planes[ 3 ].copy( p3 );
5743 planes[ 4 ].copy( p4 );
5744 planes[ 5 ].copy( p5 );
5745
5746 return this;
5747
5748 },
5749
5750 clone: function () {
5751
5752 return new this.constructor().copy( this );
5753
5754 },
5755
5756 copy: function ( frustum ) {
5757
5758 var planes = this.planes;
5759
5760 for ( var i = 0; i < 6; i ++ ) {
5761
5762 planes[ i ].copy( frustum.planes[ i ] );
5763
5764 }
5765
5766 return this;
5767
5768 },
5769
5770 setFromMatrix: function ( m ) {
5771
5772 var planes = this.planes;
5773 var me = m.elements;
5774 var me0 = me[ 0 ], me1 = me[ 1 ], me2 = me[ 2 ], me3 = me[ 3 ];
5775 var me4 = me[ 4 ], me5 = me[ 5 ], me6 = me[ 6 ], me7 = me[ 7 ];
5776 var me8 = me[ 8 ], me9 = me[ 9 ], me10 = me[ 10 ], me11 = me[ 11 ];
5777 var me12 = me[ 12 ], me13 = me[ 13 ], me14 = me[ 14 ], me15 = me[ 15 ];
5778
5779 planes[ 0 ].setComponents( me3 - me0, me7 - me4, me11 - me8, me15 - me12 ).normalize();
5780 planes[ 1 ].setComponents( me3 + me0, me7 + me4, me11 + me8, me15 + me12 ).normalize();
5781 planes[ 2 ].setComponents( me3 + me1, me7 + me5, me11 + me9, me15 + me13 ).normalize();
5782 planes[ 3 ].setComponents( me3 - me1, me7 - me5, me11 - me9, me15 - me13 ).normalize();
5783 planes[ 4 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize();
5784 planes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize();
5785
5786 return this;
5787
5788 },
5789
5790 intersectsObject: function () {
5791
5792 var sphere = new Sphere();
5793
5794 return function intersectsObject( object ) {
5795
5796 var geometry = object.geometry;
5797
5798 if ( geometry.boundingSphere === null )
5799 geometry.computeBoundingSphere();
5800
5801 sphere.copy( geometry.boundingSphere )
5802 .applyMatrix4( object.matrixWorld );
5803
5804 return this.intersectsSphere( sphere );
5805
5806 };
5807
5808 }(),
5809
5810 intersectsSprite: function () {
5811
5812 var sphere = new Sphere();
5813
5814 return function intersectsSprite( sprite ) {
5815
5816 sphere.center.set( 0, 0, 0 );
5817 sphere.radius = 0.7071067811865476;
5818 sphere.applyMatrix4( sprite.matrixWorld );
5819
5820 return this.intersectsSphere( sphere );
5821
5822 };
5823
5824 }(),
5825
5826 intersectsSphere: function ( sphere ) {
5827
5828 var planes = this.planes;
5829 var center = sphere.center;
5830 var negRadius = - sphere.radius;
5831
5832 for ( var i = 0; i < 6; i ++ ) {
5833
5834 var distance = planes[ i ].distanceToPoint( center );
5835
5836 if ( distance < negRadius ) {
5837
5838 return false;
5839
5840 }
5841
5842 }
5843
5844 return true;
5845
5846 },
5847
5848 intersectsBox: function () {
5849
5850 var p1 = new Vector3(),
5851 p2 = new Vector3();
5852
5853 return function intersectsBox( box ) {
5854
5855 var planes = this.planes;
5856
5857 for ( var i = 0; i < 6; i ++ ) {
5858
5859 var plane = planes[ i ];
5860
5861 p1.x = plane.normal.x > 0 ? box.min.x : box.max.x;
5862 p2.x = plane.normal.x > 0 ? box.max.x : box.min.x;
5863 p1.y = plane.normal.y > 0 ? box.min.y : box.max.y;
5864 p2.y = plane.normal.y > 0 ? box.max.y : box.min.y;
5865 p1.z = plane.normal.z > 0 ? box.min.z : box.max.z;
5866 p2.z = plane.normal.z > 0 ? box.max.z : box.min.z;
5867
5868 var d1 = plane.distanceToPoint( p1 );
5869 var d2 = plane.distanceToPoint( p2 );
5870
5871 // if both outside plane, no intersection
5872
5873 if ( d1 < 0 && d2 < 0 ) {
5874
5875 return false;
5876
5877 }
5878
5879 }
5880
5881 return true;
5882
5883 };
5884
5885 }(),
5886
5887 containsPoint: function ( point ) {
5888
5889 var planes = this.planes;
5890
5891 for ( var i = 0; i < 6; i ++ ) {
5892
5893 if ( planes[ i ].distanceToPoint( point ) < 0 ) {
5894
5895 return false;
5896
5897 }
5898
5899 }
5900
5901 return true;
5902
5903 }
5904
5905 } );
5906
5907 var alphamap_fragment = "#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vUv ).g;\n#endif\n";
5908
5909 var alphamap_pars_fragment = "#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif\n";
5910
5911 var alphatest_fragment = "#ifdef ALPHATEST\n\tif ( diffuseColor.a < ALPHATEST ) discard;\n#endif\n";
5912
5913 var 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";
5914
5915 var aomap_pars_fragment = "#ifdef USE_AOMAP\n\tuniform sampler2D aoMap;\n\tuniform float aoMapIntensity;\n#endif";
5916
5917 var begin_vertex = "\nvec3 transformed = vec3( position );\n";
5918
5919 var beginnormal_vertex = "\nvec3 objectNormal = vec3( normal );\n";
5920
5921 var 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";
5922
5923 var 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";
5924
5925 var 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";
5926
5927 var 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";
5928
5929 var clipping_planes_pars_vertex = "#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n\tvarying vec3 vViewPosition;\n#endif\n";
5930
5931 var clipping_planes_vertex = "#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n";
5932
5933 var color_fragment = "#ifdef USE_COLOR\n\tdiffuseColor.rgb *= vColor;\n#endif";
5934
5935 var color_pars_fragment = "#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif\n";
5936
5937 var color_pars_vertex = "#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif";
5938
5939 var color_vertex = "#ifdef USE_COLOR\n\tvColor.xyz = color.xyz;\n#endif";
5940
5941 var 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";
5942
5943 var 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";
5944
5945 var defaultnormal_vertex = "vec3 transformedNormal = normalMatrix * objectNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n";
5946
5947 var displacementmap_pars_vertex = "#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif\n";
5948
5949 var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, uv ).x * displacementScale + displacementBias );\n#endif\n";
5950
5951 var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif\n";
5952
5953 var emissivemap_pars_fragment = "#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif\n";
5954
5955 var encodings_fragment = " gl_FragColor = linearToOutputTexel( gl_FragColor );\n";
5956
5957 var 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";
5958
5959 var 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";
5960
5961 var 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";
5962
5963 var 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";
5964
5965 var 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";
5966
5967 var fog_vertex = "\n#ifdef USE_FOG\nfogDepth = -mvPosition.z;\n#endif";
5968
5969 var fog_pars_vertex = "#ifdef USE_FOG\n varying float fogDepth;\n#endif\n";
5970
5971 var 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";
5972
5973 var 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";
5974
5975 var 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";
5976
5977 var lightmap_fragment = "#ifdef USE_LIGHTMAP\n\treflectedLight.indirectDiffuse += PI * texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n#endif\n";
5978
5979 var lightmap_pars_fragment = "#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif";
5980
5981 var 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";
5982
5983 var 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";
5984
5985 var 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";
5986
5987 var lights_phong_fragment = "BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;\n";
5988
5989 var 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";
5990
5991 var 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";
5992
5993 var 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";
5994
5995 var 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";
5996
5997 var 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";
5998
5999 var 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";
6000
6001 var logdepthbuf_fragment = "#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif";
6002
6003 var 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";
6004
6005 var 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";
6006
6007 var 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";
6008
6009 var map_fragment = "#ifdef USE_MAP\n\tvec4 texelColor = texture2D( map, vUv );\n\ttexelColor = mapTexelToLinear( texelColor );\n\tdiffuseColor *= texelColor;\n#endif\n";
6010
6011 var map_pars_fragment = "#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n";
6012
6013 var 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";
6014
6015 var map_particle_pars_fragment = "#ifdef USE_MAP\n\tuniform mat3 uvTransform;\n\tuniform sampler2D map;\n#endif\n";
6016
6017 var metalnessmap_fragment = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif\n";
6018
6019 var metalnessmap_pars_fragment = "#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif";
6020
6021 var 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";
6022
6023 var 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";
6024
6025 var 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";
6026
6027 var 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";
6028
6029 var 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";
6030
6031 var 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";
6032
6033 var 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";
6034
6035 var premultiplied_alpha_fragment = "#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif\n";
6036
6037 var project_vertex = "vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );\ngl_Position = projectionMatrix * mvPosition;\n";
6038
6039 var dithering_fragment = "#if defined( DITHERING )\n gl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif\n";
6040
6041 var 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";
6042
6043 var roughnessmap_fragment = "float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif\n";
6044
6045 var roughnessmap_pars_fragment = "#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif";
6046
6047 var 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";
6048
6049 var 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";
6050
6051 var 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";
6052
6053 var 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";
6054
6055 var 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";
6056
6057 var 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";
6058
6059 var 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";
6060
6061 var 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";
6062
6063 var 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";
6064
6065 var specularmap_pars_fragment = "#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif";
6066
6067 var tonemapping_fragment = "#if defined( TONE_MAPPING )\n gl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif\n";
6068
6069 var 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";
6070
6071 var 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";
6072
6073 var 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";
6074
6075 var 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";
6076
6077 var uv2_pars_fragment = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif";
6078
6079 var uv2_pars_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tattribute vec2 uv2;\n\tvarying vec2 vUv2;\n#endif";
6080
6081 var uv2_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = uv2;\n#endif";
6082
6083 var worldpos_vertex = "#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )\n\tvec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );\n#endif\n";
6084
6085 var 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";
6086
6087 var 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";
6088
6089 var 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";
6090
6091 var 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";
6092
6093 var 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";
6094
6095 var 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";
6096
6097 var 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";
6098
6099 var 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";
6100
6101 var 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";
6102
6103 var 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";
6104
6105 var 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";
6106
6107 var 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";
6108
6109 var 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";
6110
6111 var 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";
6112
6113 var 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";
6114
6115 var 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";
6116
6117 var 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";
6118
6119 var 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";
6120
6121 var 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";
6122
6123 var 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";
6124
6125 var 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";
6126
6127 var 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";
6128
6129 var 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";
6130
6131 var 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";
6132
6133 var ShaderChunk = {
6134 alphamap_fragment: alphamap_fragment,
6135 alphamap_pars_fragment: alphamap_pars_fragment,
6136 alphatest_fragment: alphatest_fragment,
6137 aomap_fragment: aomap_fragment,
6138 aomap_pars_fragment: aomap_pars_fragment,
6139 begin_vertex: begin_vertex,
6140 beginnormal_vertex: beginnormal_vertex,
6141 bsdfs: bsdfs,
6142 bumpmap_pars_fragment: bumpmap_pars_fragment,
6143 clipping_planes_fragment: clipping_planes_fragment,
6144 clipping_planes_pars_fragment: clipping_planes_pars_fragment,
6145 clipping_planes_pars_vertex: clipping_planes_pars_vertex,
6146 clipping_planes_vertex: clipping_planes_vertex,
6147 color_fragment: color_fragment,
6148 color_pars_fragment: color_pars_fragment,
6149 color_pars_vertex: color_pars_vertex,
6150 color_vertex: color_vertex,
6151 common: common,
6152 cube_uv_reflection_fragment: cube_uv_reflection_fragment,
6153 defaultnormal_vertex: defaultnormal_vertex,
6154 displacementmap_pars_vertex: displacementmap_pars_vertex,
6155 displacementmap_vertex: displacementmap_vertex,
6156 emissivemap_fragment: emissivemap_fragment,
6157 emissivemap_pars_fragment: emissivemap_pars_fragment,
6158 encodings_fragment: encodings_fragment,
6159 encodings_pars_fragment: encodings_pars_fragment,
6160 envmap_fragment: envmap_fragment,
6161 envmap_pars_fragment: envmap_pars_fragment,
6162 envmap_pars_vertex: envmap_pars_vertex,
6163 envmap_vertex: envmap_vertex,
6164 fog_vertex: fog_vertex,
6165 fog_pars_vertex: fog_pars_vertex,
6166 fog_fragment: fog_fragment,
6167 fog_pars_fragment: fog_pars_fragment,
6168 gradientmap_pars_fragment: gradientmap_pars_fragment,
6169 lightmap_fragment: lightmap_fragment,
6170 lightmap_pars_fragment: lightmap_pars_fragment,
6171 lights_lambert_vertex: lights_lambert_vertex,
6172 lights_pars_begin: lights_pars_begin,
6173 lights_pars_maps: lights_pars_maps,
6174 lights_phong_fragment: lights_phong_fragment,
6175 lights_phong_pars_fragment: lights_phong_pars_fragment,
6176 lights_physical_fragment: lights_physical_fragment,
6177 lights_physical_pars_fragment: lights_physical_pars_fragment,
6178 lights_fragment_begin: lights_fragment_begin,
6179 lights_fragment_maps: lights_fragment_maps,
6180 lights_fragment_end: lights_fragment_end,
6181 logdepthbuf_fragment: logdepthbuf_fragment,
6182 logdepthbuf_pars_fragment: logdepthbuf_pars_fragment,
6183 logdepthbuf_pars_vertex: logdepthbuf_pars_vertex,
6184 logdepthbuf_vertex: logdepthbuf_vertex,
6185 map_fragment: map_fragment,
6186 map_pars_fragment: map_pars_fragment,
6187 map_particle_fragment: map_particle_fragment,
6188 map_particle_pars_fragment: map_particle_pars_fragment,
6189 metalnessmap_fragment: metalnessmap_fragment,
6190 metalnessmap_pars_fragment: metalnessmap_pars_fragment,
6191 morphnormal_vertex: morphnormal_vertex,
6192 morphtarget_pars_vertex: morphtarget_pars_vertex,
6193 morphtarget_vertex: morphtarget_vertex,
6194 normal_fragment_begin: normal_fragment_begin,
6195 normal_fragment_maps: normal_fragment_maps,
6196 normalmap_pars_fragment: normalmap_pars_fragment,
6197 packing: packing,
6198 premultiplied_alpha_fragment: premultiplied_alpha_fragment,
6199 project_vertex: project_vertex,
6200 dithering_fragment: dithering_fragment,
6201 dithering_pars_fragment: dithering_pars_fragment,
6202 roughnessmap_fragment: roughnessmap_fragment,
6203 roughnessmap_pars_fragment: roughnessmap_pars_fragment,
6204 shadowmap_pars_fragment: shadowmap_pars_fragment,
6205 shadowmap_pars_vertex: shadowmap_pars_vertex,
6206 shadowmap_vertex: shadowmap_vertex,
6207 shadowmask_pars_fragment: shadowmask_pars_fragment,
6208 skinbase_vertex: skinbase_vertex,
6209 skinning_pars_vertex: skinning_pars_vertex,
6210 skinning_vertex: skinning_vertex,
6211 skinnormal_vertex: skinnormal_vertex,
6212 specularmap_fragment: specularmap_fragment,
6213 specularmap_pars_fragment: specularmap_pars_fragment,
6214 tonemapping_fragment: tonemapping_fragment,
6215 tonemapping_pars_fragment: tonemapping_pars_fragment,
6216 uv_pars_fragment: uv_pars_fragment,
6217 uv_pars_vertex: uv_pars_vertex,
6218 uv_vertex: uv_vertex,
6219 uv2_pars_fragment: uv2_pars_fragment,
6220 uv2_pars_vertex: uv2_pars_vertex,
6221 uv2_vertex: uv2_vertex,
6222 worldpos_vertex: worldpos_vertex,
6223
6224 cube_frag: cube_frag,
6225 cube_vert: cube_vert,
6226 depth_frag: depth_frag,
6227 depth_vert: depth_vert,
6228 distanceRGBA_frag: distanceRGBA_frag,
6229 distanceRGBA_vert: distanceRGBA_vert,
6230 equirect_frag: equirect_frag,
6231 equirect_vert: equirect_vert,
6232 linedashed_frag: linedashed_frag,
6233 linedashed_vert: linedashed_vert,
6234 meshbasic_frag: meshbasic_frag,
6235 meshbasic_vert: meshbasic_vert,
6236 meshlambert_frag: meshlambert_frag,
6237 meshlambert_vert: meshlambert_vert,
6238 meshphong_frag: meshphong_frag,
6239 meshphong_vert: meshphong_vert,
6240 meshphysical_frag: meshphysical_frag,
6241 meshphysical_vert: meshphysical_vert,
6242 normal_frag: normal_frag,
6243 normal_vert: normal_vert,
6244 points_frag: points_frag,
6245 points_vert: points_vert,
6246 shadow_frag: shadow_frag,
6247 shadow_vert: shadow_vert
6248 };
6249
6250 /**
6251 * Uniform Utilities
6252 */
6253
6254 var UniformsUtils = {
6255
6256 merge: function ( uniforms ) {
6257
6258 var merged = {};
6259
6260 for ( var u = 0; u < uniforms.length; u ++ ) {
6261
6262 var tmp = this.clone( uniforms[ u ] );
6263
6264 for ( var p in tmp ) {
6265
6266 merged[ p ] = tmp[ p ];
6267
6268 }
6269
6270 }
6271
6272 return merged;
6273
6274 },
6275
6276 clone: function ( uniforms_src ) {
6277
6278 var uniforms_dst = {};
6279
6280 for ( var u in uniforms_src ) {
6281
6282 uniforms_dst[ u ] = {};
6283
6284 for ( var p in uniforms_src[ u ] ) {
6285
6286 var parameter_src = uniforms_src[ u ][ p ];
6287
6288 if ( parameter_src && ( parameter_src.isColor ||
6289 parameter_src.isMatrix3 || parameter_src.isMatrix4 ||
6290 parameter_src.isVector2 || parameter_src.isVector3 || parameter_src.isVector4 ||
6291 parameter_src.isTexture ) ) {
6292
6293 uniforms_dst[ u ][ p ] = parameter_src.clone();
6294
6295 } else if ( Array.isArray( parameter_src ) ) {
6296
6297 uniforms_dst[ u ][ p ] = parameter_src.slice();
6298
6299 } else {
6300
6301 uniforms_dst[ u ][ p ] = parameter_src;
6302
6303 }
6304
6305 }
6306
6307 }
6308
6309 return uniforms_dst;
6310
6311 }
6312
6313 };
6314
6315 /**
6316 * @author mrdoob / http://mrdoob.com/
6317 */
6318
6319 var ColorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF,
6320 'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2,
6321 'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50,
6322 'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B,
6323 'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B,
6324 'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F,
6325 'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3,
6326 'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222,
6327 'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700,
6328 'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4,
6329 'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00,
6330 'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3,
6331 'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA,
6332 'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32,
6333 'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3,
6334 'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC,
6335 'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD,
6336 'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6,
6337 'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9,
6338 'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F,
6339 'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE,
6340 'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA,
6341 'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0,
6342 'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 };
6343
6344 function Color( r, g, b ) {
6345
6346 if ( g === undefined && b === undefined ) {
6347
6348 // r is THREE.Color, hex or string
6349 return this.set( r );
6350
6351 }
6352
6353 return this.setRGB( r, g, b );
6354
6355 }
6356
6357 Object.assign( Color.prototype, {
6358
6359 isColor: true,
6360
6361 r: 1, g: 1, b: 1,
6362
6363 set: function ( value ) {
6364
6365 if ( value && value.isColor ) {
6366
6367 this.copy( value );
6368
6369 } else if ( typeof value === 'number' ) {
6370
6371 this.setHex( value );
6372
6373 } else if ( typeof value === 'string' ) {
6374
6375 this.setStyle( value );
6376
6377 }
6378
6379 return this;
6380
6381 },
6382
6383 setScalar: function ( scalar ) {
6384
6385 this.r = scalar;
6386 this.g = scalar;
6387 this.b = scalar;
6388
6389 return this;
6390
6391 },
6392
6393 setHex: function ( hex ) {
6394
6395 hex = Math.floor( hex );
6396
6397 this.r = ( hex >> 16 & 255 ) / 255;
6398 this.g = ( hex >> 8 & 255 ) / 255;
6399 this.b = ( hex & 255 ) / 255;
6400
6401 return this;
6402
6403 },
6404
6405 setRGB: function ( r, g, b ) {
6406
6407 this.r = r;
6408 this.g = g;
6409 this.b = b;
6410
6411 return this;
6412
6413 },
6414
6415 setHSL: function () {
6416
6417 function hue2rgb( p, q, t ) {
6418
6419 if ( t < 0 ) t += 1;
6420 if ( t > 1 ) t -= 1;
6421 if ( t < 1 / 6 ) return p + ( q - p ) * 6 * t;
6422 if ( t < 1 / 2 ) return q;
6423 if ( t < 2 / 3 ) return p + ( q - p ) * 6 * ( 2 / 3 - t );
6424 return p;
6425
6426 }
6427
6428 return function setHSL( h, s, l ) {
6429
6430 // h,s,l ranges are in 0.0 - 1.0
6431 h = _Math.euclideanModulo( h, 1 );
6432 s = _Math.clamp( s, 0, 1 );
6433 l = _Math.clamp( l, 0, 1 );
6434
6435 if ( s === 0 ) {
6436
6437 this.r = this.g = this.b = l;
6438
6439 } else {
6440
6441 var p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s );
6442 var q = ( 2 * l ) - p;
6443
6444 this.r = hue2rgb( q, p, h + 1 / 3 );
6445 this.g = hue2rgb( q, p, h );
6446 this.b = hue2rgb( q, p, h - 1 / 3 );
6447
6448 }
6449
6450 return this;
6451
6452 };
6453
6454 }(),
6455
6456 setStyle: function ( style ) {
6457
6458 function handleAlpha( string ) {
6459
6460 if ( string === undefined ) return;
6461
6462 if ( parseFloat( string ) < 1 ) {
6463
6464 console.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' );
6465
6466 }
6467
6468 }
6469
6470
6471 var m;
6472
6473 if ( m = /^((?:rgb|hsl)a?)\(\s*([^\)]*)\)/.exec( style ) ) {
6474
6475 // rgb / hsl
6476
6477 var color;
6478 var name = m[ 1 ];
6479 var components = m[ 2 ];
6480
6481 switch ( name ) {
6482
6483 case 'rgb':
6484 case 'rgba':
6485
6486 if ( color = /^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) {
6487
6488 // rgb(255,0,0) rgba(255,0,0,0.5)
6489 this.r = Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255;
6490 this.g = Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255;
6491 this.b = Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255;
6492
6493 handleAlpha( color[ 5 ] );
6494
6495 return this;
6496
6497 }
6498
6499 if ( color = /^(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) {
6500
6501 // rgb(100%,0%,0%) rgba(100%,0%,0%,0.5)
6502 this.r = Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100;
6503 this.g = Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100;
6504 this.b = Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100;
6505
6506 handleAlpha( color[ 5 ] );
6507
6508 return this;
6509
6510 }
6511
6512 break;
6513
6514 case 'hsl':
6515 case 'hsla':
6516
6517 if ( color = /^([0-9]*\.?[0-9]+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) {
6518
6519 // hsl(120,50%,50%) hsla(120,50%,50%,0.5)
6520 var h = parseFloat( color[ 1 ] ) / 360;
6521 var s = parseInt( color[ 2 ], 10 ) / 100;
6522 var l = parseInt( color[ 3 ], 10 ) / 100;
6523
6524 handleAlpha( color[ 5 ] );
6525
6526 return this.setHSL( h, s, l );
6527
6528 }
6529
6530 break;
6531
6532 }
6533
6534 } else if ( m = /^\#([A-Fa-f0-9]+)$/.exec( style ) ) {
6535
6536 // hex color
6537
6538 var hex = m[ 1 ];
6539 var size = hex.length;
6540
6541 if ( size === 3 ) {
6542
6543 // #ff0
6544 this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 0 ), 16 ) / 255;
6545 this.g = parseInt( hex.charAt( 1 ) + hex.charAt( 1 ), 16 ) / 255;
6546 this.b = parseInt( hex.charAt( 2 ) + hex.charAt( 2 ), 16 ) / 255;
6547
6548 return this;
6549
6550 } else if ( size === 6 ) {
6551
6552 // #ff0000
6553 this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 1 ), 16 ) / 255;
6554 this.g = parseInt( hex.charAt( 2 ) + hex.charAt( 3 ), 16 ) / 255;
6555 this.b = parseInt( hex.charAt( 4 ) + hex.charAt( 5 ), 16 ) / 255;
6556
6557 return this;
6558
6559 }
6560
6561 }
6562
6563 if ( style && style.length > 0 ) {
6564
6565 // color keywords
6566 var hex = ColorKeywords[ style ];
6567
6568 if ( hex !== undefined ) {
6569
6570 // red
6571 this.setHex( hex );
6572
6573 } else {
6574
6575 // unknown color
6576 console.warn( 'THREE.Color: Unknown color ' + style );
6577
6578 }
6579
6580 }
6581
6582 return this;
6583
6584 },
6585
6586 clone: function () {
6587
6588 return new this.constructor( this.r, this.g, this.b );
6589
6590 },
6591
6592 copy: function ( color ) {
6593
6594 this.r = color.r;
6595 this.g = color.g;
6596 this.b = color.b;
6597
6598 return this;
6599
6600 },
6601
6602 copyGammaToLinear: function ( color, gammaFactor ) {
6603
6604 if ( gammaFactor === undefined ) gammaFactor = 2.0;
6605
6606 this.r = Math.pow( color.r, gammaFactor );
6607 this.g = Math.pow( color.g, gammaFactor );
6608 this.b = Math.pow( color.b, gammaFactor );
6609
6610 return this;
6611
6612 },
6613
6614 copyLinearToGamma: function ( color, gammaFactor ) {
6615
6616 if ( gammaFactor === undefined ) gammaFactor = 2.0;
6617
6618 var safeInverse = ( gammaFactor > 0 ) ? ( 1.0 / gammaFactor ) : 1.0;
6619
6620 this.r = Math.pow( color.r, safeInverse );
6621 this.g = Math.pow( color.g, safeInverse );
6622 this.b = Math.pow( color.b, safeInverse );
6623
6624 return this;
6625
6626 },
6627
6628 convertGammaToLinear: function () {
6629
6630 var r = this.r, g = this.g, b = this.b;
6631
6632 this.r = r * r;
6633 this.g = g * g;
6634 this.b = b * b;
6635
6636 return this;
6637
6638 },
6639
6640 convertLinearToGamma: function () {
6641
6642 this.r = Math.sqrt( this.r );
6643 this.g = Math.sqrt( this.g );
6644 this.b = Math.sqrt( this.b );
6645
6646 return this;
6647
6648 },
6649
6650 getHex: function () {
6651
6652 return ( this.r * 255 ) << 16 ^ ( this.g * 255 ) << 8 ^ ( this.b * 255 ) << 0;
6653
6654 },
6655
6656 getHexString: function () {
6657
6658 return ( '000000' + this.getHex().toString( 16 ) ).slice( - 6 );
6659
6660 },
6661
6662 getHSL: function ( target ) {
6663
6664 // h,s,l ranges are in 0.0 - 1.0
6665
6666 if ( target === undefined ) {
6667
6668 console.warn( 'THREE.Color: .getHSL() target is now required' );
6669 target = { h: 0, s: 0, l: 0 };
6670
6671 }
6672
6673 var r = this.r, g = this.g, b = this.b;
6674
6675 var max = Math.max( r, g, b );
6676 var min = Math.min( r, g, b );
6677
6678 var hue, saturation;
6679 var lightness = ( min + max ) / 2.0;
6680
6681 if ( min === max ) {
6682
6683 hue = 0;
6684 saturation = 0;
6685
6686 } else {
6687
6688 var delta = max - min;
6689
6690 saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min );
6691
6692 switch ( max ) {
6693
6694 case r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break;
6695 case g: hue = ( b - r ) / delta + 2; break;
6696 case b: hue = ( r - g ) / delta + 4; break;
6697
6698 }
6699
6700 hue /= 6;
6701
6702 }
6703
6704 target.h = hue;
6705 target.s = saturation;
6706 target.l = lightness;
6707
6708 return target;
6709
6710 },
6711
6712 getStyle: function () {
6713
6714 return 'rgb(' + ( ( this.r * 255 ) | 0 ) + ',' + ( ( this.g * 255 ) | 0 ) + ',' + ( ( this.b * 255 ) | 0 ) + ')';
6715
6716 },
6717
6718 offsetHSL: function () {
6719
6720 var hsl = {};
6721
6722 return function ( h, s, l ) {
6723
6724 this.getHSL( hsl );
6725
6726 hsl.h += h; hsl.s += s; hsl.l += l;
6727
6728 this.setHSL( hsl.h, hsl.s, hsl.l );
6729
6730 return this;
6731
6732 };
6733
6734 }(),
6735
6736 add: function ( color ) {
6737
6738 this.r += color.r;
6739 this.g += color.g;
6740 this.b += color.b;
6741
6742 return this;
6743
6744 },
6745
6746 addColors: function ( color1, color2 ) {
6747
6748 this.r = color1.r + color2.r;
6749 this.g = color1.g + color2.g;
6750 this.b = color1.b + color2.b;
6751
6752 return this;
6753
6754 },
6755
6756 addScalar: function ( s ) {
6757
6758 this.r += s;
6759 this.g += s;
6760 this.b += s;
6761
6762 return this;
6763
6764 },
6765
6766 sub: function ( color ) {
6767
6768 this.r = Math.max( 0, this.r - color.r );
6769 this.g = Math.max( 0, this.g - color.g );
6770 this.b = Math.max( 0, this.b - color.b );
6771
6772 return this;
6773
6774 },
6775
6776 multiply: function ( color ) {
6777
6778 this.r *= color.r;
6779 this.g *= color.g;
6780 this.b *= color.b;
6781
6782 return this;
6783
6784 },
6785
6786 multiplyScalar: function ( s ) {
6787
6788 this.r *= s;
6789 this.g *= s;
6790 this.b *= s;
6791
6792 return this;
6793
6794 },
6795
6796 lerp: function ( color, alpha ) {
6797
6798 this.r += ( color.r - this.r ) * alpha;
6799 this.g += ( color.g - this.g ) * alpha;
6800 this.b += ( color.b - this.b ) * alpha;
6801
6802 return this;
6803
6804 },
6805
6806 equals: function ( c ) {
6807
6808 return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b );
6809
6810 },
6811
6812 fromArray: function ( array, offset ) {
6813
6814 if ( offset === undefined ) offset = 0;
6815
6816 this.r = array[ offset ];
6817 this.g = array[ offset + 1 ];
6818 this.b = array[ offset + 2 ];
6819
6820 return this;
6821
6822 },
6823
6824 toArray: function ( array, offset ) {
6825
6826 if ( array === undefined ) array = [];
6827 if ( offset === undefined ) offset = 0;
6828
6829 array[ offset ] = this.r;
6830 array[ offset + 1 ] = this.g;
6831 array[ offset + 2 ] = this.b;
6832
6833 return array;
6834
6835 },
6836
6837 toJSON: function () {
6838
6839 return this.getHex();
6840
6841 }
6842
6843 } );
6844
6845 /**
6846 * Uniforms library for shared webgl shaders
6847 */
6848
6849 var UniformsLib = {
6850
6851 common: {
6852
6853 diffuse: { value: new Color( 0xeeeeee ) },
6854 opacity: { value: 1.0 },
6855
6856 map: { value: null },
6857 uvTransform: { value: new Matrix3() },
6858
6859 alphaMap: { value: null },
6860
6861 },
6862
6863 specularmap: {
6864
6865 specularMap: { value: null },
6866
6867 },
6868
6869 envmap: {
6870
6871 envMap: { value: null },
6872 flipEnvMap: { value: - 1 },
6873 reflectivity: { value: 1.0 },
6874 refractionRatio: { value: 0.98 },
6875 maxMipLevel: { value: 0 }
6876
6877 },
6878
6879 aomap: {
6880
6881 aoMap: { value: null },
6882 aoMapIntensity: { value: 1 }
6883
6884 },
6885
6886 lightmap: {
6887
6888 lightMap: { value: null },
6889 lightMapIntensity: { value: 1 }
6890
6891 },
6892
6893 emissivemap: {
6894
6895 emissiveMap: { value: null }
6896
6897 },
6898
6899 bumpmap: {
6900
6901 bumpMap: { value: null },
6902 bumpScale: { value: 1 }
6903
6904 },
6905
6906 normalmap: {
6907
6908 normalMap: { value: null },
6909 normalScale: { value: new Vector2( 1, 1 ) }
6910
6911 },
6912
6913 displacementmap: {
6914
6915 displacementMap: { value: null },
6916 displacementScale: { value: 1 },
6917 displacementBias: { value: 0 }
6918
6919 },
6920
6921 roughnessmap: {
6922
6923 roughnessMap: { value: null }
6924
6925 },
6926
6927 metalnessmap: {
6928
6929 metalnessMap: { value: null }
6930
6931 },
6932
6933 gradientmap: {
6934
6935 gradientMap: { value: null }
6936
6937 },
6938
6939 fog: {
6940
6941 fogDensity: { value: 0.00025 },
6942 fogNear: { value: 1 },
6943 fogFar: { value: 2000 },
6944 fogColor: { value: new Color( 0xffffff ) }
6945
6946 },
6947
6948 lights: {
6949
6950 ambientLightColor: { value: [] },
6951
6952 directionalLights: { value: [], properties: {
6953 direction: {},
6954 color: {},
6955
6956 shadow: {},
6957 shadowBias: {},
6958 shadowRadius: {},
6959 shadowMapSize: {}
6960 } },
6961
6962 directionalShadowMap: { value: [] },
6963 directionalShadowMatrix: { value: [] },
6964
6965 spotLights: { value: [], properties: {
6966 color: {},
6967 position: {},
6968 direction: {},
6969 distance: {},
6970 coneCos: {},
6971 penumbraCos: {},
6972 decay: {},
6973
6974 shadow: {},
6975 shadowBias: {},
6976 shadowRadius: {},
6977 shadowMapSize: {}
6978 } },
6979
6980 spotShadowMap: { value: [] },
6981 spotShadowMatrix: { value: [] },
6982
6983 pointLights: { value: [], properties: {
6984 color: {},
6985 position: {},
6986 decay: {},
6987 distance: {},
6988
6989 shadow: {},
6990 shadowBias: {},
6991 shadowRadius: {},
6992 shadowMapSize: {},
6993 shadowCameraNear: {},
6994 shadowCameraFar: {}
6995 } },
6996
6997 pointShadowMap: { value: [] },
6998 pointShadowMatrix: { value: [] },
6999
7000 hemisphereLights: { value: [], properties: {
7001 direction: {},
7002 skyColor: {},
7003 groundColor: {}
7004 } },
7005
7006 // TODO (abelnation): RectAreaLight BRDF data needs to be moved from example to main src
7007 rectAreaLights: { value: [], properties: {
7008 color: {},
7009 position: {},
7010 width: {},
7011 height: {}
7012 } }
7013
7014 },
7015
7016 points: {
7017
7018 diffuse: { value: new Color( 0xeeeeee ) },
7019 opacity: { value: 1.0 },
7020 size: { value: 1.0 },
7021 scale: { value: 1.0 },
7022 map: { value: null },
7023 uvTransform: { value: new Matrix3() }
7024
7025 }
7026
7027 };
7028
7029 /**
7030 * @author alteredq / http://alteredqualia.com/
7031 * @author mrdoob / http://mrdoob.com/
7032 * @author mikael emtinger / http://gomo.se/
7033 */
7034
7035 var ShaderLib = {
7036
7037 basic: {
7038
7039 uniforms: UniformsUtils.merge( [
7040 UniformsLib.common,
7041 UniformsLib.specularmap,
7042 UniformsLib.envmap,
7043 UniformsLib.aomap,
7044 UniformsLib.lightmap,
7045 UniformsLib.fog
7046 ] ),
7047
7048 vertexShader: ShaderChunk.meshbasic_vert,
7049 fragmentShader: ShaderChunk.meshbasic_frag
7050
7051 },
7052
7053 lambert: {
7054
7055 uniforms: UniformsUtils.merge( [
7056 UniformsLib.common,
7057 UniformsLib.specularmap,
7058 UniformsLib.envmap,
7059 UniformsLib.aomap,
7060 UniformsLib.lightmap,
7061 UniformsLib.emissivemap,
7062 UniformsLib.fog,
7063 UniformsLib.lights,
7064 {
7065 emissive: { value: new Color( 0x000000 ) }
7066 }
7067 ] ),
7068
7069 vertexShader: ShaderChunk.meshlambert_vert,
7070 fragmentShader: ShaderChunk.meshlambert_frag
7071
7072 },
7073
7074 phong: {
7075
7076 uniforms: UniformsUtils.merge( [
7077 UniformsLib.common,
7078 UniformsLib.specularmap,
7079 UniformsLib.envmap,
7080 UniformsLib.aomap,
7081 UniformsLib.lightmap,
7082 UniformsLib.emissivemap,
7083 UniformsLib.bumpmap,
7084 UniformsLib.normalmap,
7085 UniformsLib.displacementmap,
7086 UniformsLib.gradientmap,
7087 UniformsLib.fog,
7088 UniformsLib.lights,
7089 {
7090 emissive: { value: new Color( 0x000000 ) },
7091 specular: { value: new Color( 0x111111 ) },
7092 shininess: { value: 30 }
7093 }
7094 ] ),
7095
7096 vertexShader: ShaderChunk.meshphong_vert,
7097 fragmentShader: ShaderChunk.meshphong_frag
7098
7099 },
7100
7101 standard: {
7102
7103 uniforms: UniformsUtils.merge( [
7104 UniformsLib.common,
7105 UniformsLib.envmap,
7106 UniformsLib.aomap,
7107 UniformsLib.lightmap,
7108 UniformsLib.emissivemap,
7109 UniformsLib.bumpmap,
7110 UniformsLib.normalmap,
7111 UniformsLib.displacementmap,
7112 UniformsLib.roughnessmap,
7113 UniformsLib.metalnessmap,
7114 UniformsLib.fog,
7115 UniformsLib.lights,
7116 {
7117 emissive: { value: new Color( 0x000000 ) },
7118 roughness: { value: 0.5 },
7119 metalness: { value: 0.5 },
7120 envMapIntensity: { value: 1 } // temporary
7121 }
7122 ] ),
7123
7124 vertexShader: ShaderChunk.meshphysical_vert,
7125 fragmentShader: ShaderChunk.meshphysical_frag
7126
7127 },
7128
7129 points: {
7130
7131 uniforms: UniformsUtils.merge( [
7132 UniformsLib.points,
7133 UniformsLib.fog
7134 ] ),
7135
7136 vertexShader: ShaderChunk.points_vert,
7137 fragmentShader: ShaderChunk.points_frag
7138
7139 },
7140
7141 dashed: {
7142
7143 uniforms: UniformsUtils.merge( [
7144 UniformsLib.common,
7145 UniformsLib.fog,
7146 {
7147 scale: { value: 1 },
7148 dashSize: { value: 1 },
7149 totalSize: { value: 2 }
7150 }
7151 ] ),
7152
7153 vertexShader: ShaderChunk.linedashed_vert,
7154 fragmentShader: ShaderChunk.linedashed_frag
7155
7156 },
7157
7158 depth: {
7159
7160 uniforms: UniformsUtils.merge( [
7161 UniformsLib.common,
7162 UniformsLib.displacementmap
7163 ] ),
7164
7165 vertexShader: ShaderChunk.depth_vert,
7166 fragmentShader: ShaderChunk.depth_frag
7167
7168 },
7169
7170 normal: {
7171
7172 uniforms: UniformsUtils.merge( [
7173 UniformsLib.common,
7174 UniformsLib.bumpmap,
7175 UniformsLib.normalmap,
7176 UniformsLib.displacementmap,
7177 {
7178 opacity: { value: 1.0 }
7179 }
7180 ] ),
7181
7182 vertexShader: ShaderChunk.normal_vert,
7183 fragmentShader: ShaderChunk.normal_frag
7184
7185 },
7186
7187 /* -------------------------------------------------------------------------
7188 // Cube map shader
7189 ------------------------------------------------------------------------- */
7190
7191 cube: {
7192
7193 uniforms: {
7194 tCube: { value: null },
7195 tFlip: { value: - 1 },
7196 opacity: { value: 1.0 }
7197 },
7198
7199 vertexShader: ShaderChunk.cube_vert,
7200 fragmentShader: ShaderChunk.cube_frag
7201
7202 },
7203
7204 equirect: {
7205
7206 uniforms: {
7207 tEquirect: { value: null },
7208 },
7209
7210 vertexShader: ShaderChunk.equirect_vert,
7211 fragmentShader: ShaderChunk.equirect_frag
7212
7213 },
7214
7215 distanceRGBA: {
7216
7217 uniforms: UniformsUtils.merge( [
7218 UniformsLib.common,
7219 UniformsLib.displacementmap,
7220 {
7221 referencePosition: { value: new Vector3() },
7222 nearDistance: { value: 1 },
7223 farDistance: { value: 1000 }
7224 }
7225 ] ),
7226
7227 vertexShader: ShaderChunk.distanceRGBA_vert,
7228 fragmentShader: ShaderChunk.distanceRGBA_frag
7229
7230 },
7231
7232 shadow: {
7233
7234 uniforms: UniformsUtils.merge( [
7235 UniformsLib.lights,
7236 UniformsLib.fog,
7237 {
7238 color: { value: new Color( 0x00000 ) },
7239 opacity: { value: 1.0 }
7240 },
7241 ] ),
7242
7243 vertexShader: ShaderChunk.shadow_vert,
7244 fragmentShader: ShaderChunk.shadow_frag
7245
7246 }
7247
7248 };
7249
7250 ShaderLib.physical = {
7251
7252 uniforms: UniformsUtils.merge( [
7253 ShaderLib.standard.uniforms,
7254 {
7255 clearCoat: { value: 0 },
7256 clearCoatRoughness: { value: 0 }
7257 }
7258 ] ),
7259
7260 vertexShader: ShaderChunk.meshphysical_vert,
7261 fragmentShader: ShaderChunk.meshphysical_frag
7262
7263 };
7264
7265 /**
7266 * @author mrdoob / http://mrdoob.com/
7267 */
7268
7269 function WebGLAttributes( gl ) {
7270
7271 var buffers = new WeakMap();
7272
7273 function createBuffer( attribute, bufferType ) {
7274
7275 var array = attribute.array;
7276 var usage = attribute.dynamic ? gl.DYNAMIC_DRAW : gl.STATIC_DRAW;
7277
7278 var buffer = gl.createBuffer();
7279
7280 gl.bindBuffer( bufferType, buffer );
7281 gl.bufferData( bufferType, array, usage );
7282
7283 attribute.onUploadCallback();
7284
7285 var type = gl.FLOAT;
7286
7287 if ( array instanceof Float32Array ) {
7288
7289 type = gl.FLOAT;
7290
7291 } else if ( array instanceof Float64Array ) {
7292
7293 console.warn( 'THREE.WebGLAttributes: Unsupported data buffer format: Float64Array.' );
7294
7295 } else if ( array instanceof Uint16Array ) {
7296
7297 type = gl.UNSIGNED_SHORT;
7298
7299 } else if ( array instanceof Int16Array ) {
7300
7301 type = gl.SHORT;
7302
7303 } else if ( array instanceof Uint32Array ) {
7304
7305 type = gl.UNSIGNED_INT;
7306
7307 } else if ( array instanceof Int32Array ) {
7308
7309 type = gl.INT;
7310
7311 } else if ( array instanceof Int8Array ) {
7312
7313 type = gl.BYTE;
7314
7315 } else if ( array instanceof Uint8Array ) {
7316
7317 type = gl.UNSIGNED_BYTE;
7318
7319 }
7320
7321 return {
7322 buffer: buffer,
7323 type: type,
7324 bytesPerElement: array.BYTES_PER_ELEMENT,
7325 version: attribute.version
7326 };
7327
7328 }
7329
7330 function updateBuffer( buffer, attribute, bufferType ) {
7331
7332 var array = attribute.array;
7333 var updateRange = attribute.updateRange;
7334
7335 gl.bindBuffer( bufferType, buffer );
7336
7337 if ( attribute.dynamic === false ) {
7338
7339 gl.bufferData( bufferType, array, gl.STATIC_DRAW );
7340
7341 } else if ( updateRange.count === - 1 ) {
7342
7343 // Not using update ranges
7344
7345 gl.bufferSubData( bufferType, 0, array );
7346
7347 } else if ( updateRange.count === 0 ) {
7348
7349 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.' );
7350
7351 } else {
7352
7353 gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT,
7354 array.subarray( updateRange.offset, updateRange.offset + updateRange.count ) );
7355
7356 updateRange.count = - 1; // reset range
7357
7358 }
7359
7360 }
7361
7362 //
7363
7364 function get( attribute ) {
7365
7366 if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
7367
7368 return buffers.get( attribute );
7369
7370 }
7371
7372 function remove( attribute ) {
7373
7374 if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
7375
7376 var data = buffers.get( attribute );
7377
7378 if ( data ) {
7379
7380 gl.deleteBuffer( data.buffer );
7381
7382 buffers.delete( attribute );
7383
7384 }
7385
7386 }
7387
7388 function update( attribute, bufferType ) {
7389
7390 if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
7391
7392 var data = buffers.get( attribute );
7393
7394 if ( data === undefined ) {
7395
7396 buffers.set( attribute, createBuffer( attribute, bufferType ) );
7397
7398 } else if ( data.version < attribute.version ) {
7399
7400 updateBuffer( data.buffer, attribute, bufferType );
7401
7402 data.version = attribute.version;
7403
7404 }
7405
7406 }
7407
7408 return {
7409
7410 get: get,
7411 remove: remove,
7412 update: update
7413
7414 };
7415
7416 }
7417
7418 /**
7419 * @author mrdoob / http://mrdoob.com/
7420 * @author WestLangley / http://github.com/WestLangley
7421 * @author bhouston / http://clara.io
7422 */
7423
7424 function Euler( x, y, z, order ) {
7425
7426 this._x = x || 0;
7427 this._y = y || 0;
7428 this._z = z || 0;
7429 this._order = order || Euler.DefaultOrder;
7430
7431 }
7432
7433 Euler.RotationOrders = [ 'XYZ', 'YZX', 'ZXY', 'XZY', 'YXZ', 'ZYX' ];
7434
7435 Euler.DefaultOrder = 'XYZ';
7436
7437 Object.defineProperties( Euler.prototype, {
7438
7439 x: {
7440
7441 get: function () {
7442
7443 return this._x;
7444
7445 },
7446
7447 set: function ( value ) {
7448
7449 this._x = value;
7450 this.onChangeCallback();
7451
7452 }
7453
7454 },
7455
7456 y: {
7457
7458 get: function () {
7459
7460 return this._y;
7461
7462 },
7463
7464 set: function ( value ) {
7465
7466 this._y = value;
7467 this.onChangeCallback();
7468
7469 }
7470
7471 },
7472
7473 z: {
7474
7475 get: function () {
7476
7477 return this._z;
7478
7479 },
7480
7481 set: function ( value ) {
7482
7483 this._z = value;
7484 this.onChangeCallback();
7485
7486 }
7487
7488 },
7489
7490 order: {
7491
7492 get: function () {
7493
7494 return this._order;
7495
7496 },
7497
7498 set: function ( value ) {
7499
7500 this._order = value;
7501 this.onChangeCallback();
7502
7503 }
7504
7505 }
7506
7507 } );
7508
7509 Object.assign( Euler.prototype, {
7510
7511 isEuler: true,
7512
7513 set: function ( x, y, z, order ) {
7514
7515 this._x = x;
7516 this._y = y;
7517 this._z = z;
7518 this._order = order || this._order;
7519
7520 this.onChangeCallback();
7521
7522 return this;
7523
7524 },
7525
7526 clone: function () {
7527
7528 return new this.constructor( this._x, this._y, this._z, this._order );
7529
7530 },
7531
7532 copy: function ( euler ) {
7533
7534 this._x = euler._x;
7535 this._y = euler._y;
7536 this._z = euler._z;
7537 this._order = euler._order;
7538
7539 this.onChangeCallback();
7540
7541 return this;
7542
7543 },
7544
7545 setFromRotationMatrix: function ( m, order, update ) {
7546
7547 var clamp = _Math.clamp;
7548
7549 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
7550
7551 var te = m.elements;
7552 var m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ];
7553 var m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ];
7554 var m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
7555
7556 order = order || this._order;
7557
7558 if ( order === 'XYZ' ) {
7559
7560 this._y = Math.asin( clamp( m13, - 1, 1 ) );
7561
7562 if ( Math.abs( m13 ) < 0.99999 ) {
7563
7564 this._x = Math.atan2( - m23, m33 );
7565 this._z = Math.atan2( - m12, m11 );
7566
7567 } else {
7568
7569 this._x = Math.atan2( m32, m22 );
7570 this._z = 0;
7571
7572 }
7573
7574 } else if ( order === 'YXZ' ) {
7575
7576 this._x = Math.asin( - clamp( m23, - 1, 1 ) );
7577
7578 if ( Math.abs( m23 ) < 0.99999 ) {
7579
7580 this._y = Math.atan2( m13, m33 );
7581 this._z = Math.atan2( m21, m22 );
7582
7583 } else {
7584
7585 this._y = Math.atan2( - m31, m11 );
7586 this._z = 0;
7587
7588 }
7589
7590 } else if ( order === 'ZXY' ) {
7591
7592 this._x = Math.asin( clamp( m32, - 1, 1 ) );
7593
7594 if ( Math.abs( m32 ) < 0.99999 ) {
7595
7596 this._y = Math.atan2( - m31, m33 );
7597 this._z = Math.atan2( - m12, m22 );
7598
7599 } else {
7600
7601 this._y = 0;
7602 this._z = Math.atan2( m21, m11 );
7603
7604 }
7605
7606 } else if ( order === 'ZYX' ) {
7607
7608 this._y = Math.asin( - clamp( m31, - 1, 1 ) );
7609
7610 if ( Math.abs( m31 ) < 0.99999 ) {
7611
7612 this._x = Math.atan2( m32, m33 );
7613 this._z = Math.atan2( m21, m11 );
7614
7615 } else {
7616
7617 this._x = 0;
7618 this._z = Math.atan2( - m12, m22 );
7619
7620 }
7621
7622 } else if ( order === 'YZX' ) {
7623
7624 this._z = Math.asin( clamp( m21, - 1, 1 ) );
7625
7626 if ( Math.abs( m21 ) < 0.99999 ) {
7627
7628 this._x = Math.atan2( - m23, m22 );
7629 this._y = Math.atan2( - m31, m11 );
7630
7631 } else {
7632
7633 this._x = 0;
7634 this._y = Math.atan2( m13, m33 );
7635
7636 }
7637
7638 } else if ( order === 'XZY' ) {
7639
7640 this._z = Math.asin( - clamp( m12, - 1, 1 ) );
7641
7642 if ( Math.abs( m12 ) < 0.99999 ) {
7643
7644 this._x = Math.atan2( m32, m22 );
7645 this._y = Math.atan2( m13, m11 );
7646
7647 } else {
7648
7649 this._x = Math.atan2( - m23, m33 );
7650 this._y = 0;
7651
7652 }
7653
7654 } else {
7655
7656 console.warn( 'THREE.Euler: .setFromRotationMatrix() given unsupported order: ' + order );
7657
7658 }
7659
7660 this._order = order;
7661
7662 if ( update !== false ) this.onChangeCallback();
7663
7664 return this;
7665
7666 },
7667
7668 setFromQuaternion: function () {
7669
7670 var matrix = new Matrix4();
7671
7672 return function setFromQuaternion( q, order, update ) {
7673
7674 matrix.makeRotationFromQuaternion( q );
7675
7676 return this.setFromRotationMatrix( matrix, order, update );
7677
7678 };
7679
7680 }(),
7681
7682 setFromVector3: function ( v, order ) {
7683
7684 return this.set( v.x, v.y, v.z, order || this._order );
7685
7686 },
7687
7688 reorder: function () {
7689
7690 // WARNING: this discards revolution information -bhouston
7691
7692 var q = new Quaternion();
7693
7694 return function reorder( newOrder ) {
7695
7696 q.setFromEuler( this );
7697
7698 return this.setFromQuaternion( q, newOrder );
7699
7700 };
7701
7702 }(),
7703
7704 equals: function ( euler ) {
7705
7706 return ( euler._x === this._x ) && ( euler._y === this._y ) && ( euler._z === this._z ) && ( euler._order === this._order );
7707
7708 },
7709
7710 fromArray: function ( array ) {
7711
7712 this._x = array[ 0 ];
7713 this._y = array[ 1 ];
7714 this._z = array[ 2 ];
7715 if ( array[ 3 ] !== undefined ) this._order = array[ 3 ];
7716
7717 this.onChangeCallback();
7718
7719 return this;
7720
7721 },
7722
7723 toArray: function ( array, offset ) {
7724
7725 if ( array === undefined ) array = [];
7726 if ( offset === undefined ) offset = 0;
7727
7728 array[ offset ] = this._x;
7729 array[ offset + 1 ] = this._y;
7730 array[ offset + 2 ] = this._z;
7731 array[ offset + 3 ] = this._order;
7732
7733 return array;
7734
7735 },
7736
7737 toVector3: function ( optionalResult ) {
7738
7739 if ( optionalResult ) {
7740
7741 return optionalResult.set( this._x, this._y, this._z );
7742
7743 } else {
7744
7745 return new Vector3( this._x, this._y, this._z );
7746
7747 }
7748
7749 },
7750
7751 onChange: function ( callback ) {
7752
7753 this.onChangeCallback = callback;
7754
7755 return this;
7756
7757 },
7758
7759 onChangeCallback: function () {}
7760
7761 } );
7762
7763 /**
7764 * @author mrdoob / http://mrdoob.com/
7765 */
7766
7767 function Layers() {
7768
7769 this.mask = 1 | 0;
7770
7771 }
7772
7773 Object.assign( Layers.prototype, {
7774
7775 set: function ( channel ) {
7776
7777 this.mask = 1 << channel | 0;
7778
7779 },
7780
7781 enable: function ( channel ) {
7782
7783 this.mask |= 1 << channel | 0;
7784
7785 },
7786
7787 toggle: function ( channel ) {
7788
7789 this.mask ^= 1 << channel | 0;
7790
7791 },
7792
7793 disable: function ( channel ) {
7794
7795 this.mask &= ~ ( 1 << channel | 0 );
7796
7797 },
7798
7799 test: function ( layers ) {
7800
7801 return ( this.mask & layers.mask ) !== 0;
7802
7803 }
7804
7805 } );
7806
7807 /**
7808 * @author mrdoob / http://mrdoob.com/
7809 * @author mikael emtinger / http://gomo.se/
7810 * @author alteredq / http://alteredqualia.com/
7811 * @author WestLangley / http://github.com/WestLangley
7812 * @author elephantatwork / www.elephantatwork.ch
7813 */
7814
7815 var object3DId = 0;
7816
7817 function Object3D() {
7818
7819 Object.defineProperty( this, 'id', { value: object3DId ++ } );
7820
7821 this.uuid = _Math.generateUUID();
7822
7823 this.name = '';
7824 this.type = 'Object3D';
7825
7826 this.parent = null;
7827 this.children = [];
7828
7829 this.up = Object3D.DefaultUp.clone();
7830
7831 var position = new Vector3();
7832 var rotation = new Euler();
7833 var quaternion = new Quaternion();
7834 var scale = new Vector3( 1, 1, 1 );
7835
7836 function onRotationChange() {
7837
7838 quaternion.setFromEuler( rotation, false );
7839
7840 }
7841
7842 function onQuaternionChange() {
7843
7844 rotation.setFromQuaternion( quaternion, undefined, false );
7845
7846 }
7847
7848 rotation.onChange( onRotationChange );
7849 quaternion.onChange( onQuaternionChange );
7850
7851 Object.defineProperties( this, {
7852 position: {
7853 enumerable: true,
7854 value: position
7855 },
7856 rotation: {
7857 enumerable: true,
7858 value: rotation
7859 },
7860 quaternion: {
7861 enumerable: true,
7862 value: quaternion
7863 },
7864 scale: {
7865 enumerable: true,
7866 value: scale
7867 },
7868 modelViewMatrix: {
7869 value: new Matrix4()
7870 },
7871 normalMatrix: {
7872 value: new Matrix3()
7873 }
7874 } );
7875
7876 this.matrix = new Matrix4();
7877 this.matrixWorld = new Matrix4();
7878
7879 this.matrixAutoUpdate = Object3D.DefaultMatrixAutoUpdate;
7880 this.matrixWorldNeedsUpdate = false;
7881
7882 this.layers = new Layers();
7883 this.visible = true;
7884
7885 this.castShadow = false;
7886 this.receiveShadow = false;
7887
7888 this.frustumCulled = true;
7889 this.renderOrder = 0;
7890
7891 this.userData = {};
7892
7893 }
7894
7895 Object3D.DefaultUp = new Vector3( 0, 1, 0 );
7896 Object3D.DefaultMatrixAutoUpdate = true;
7897
7898 Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
7899
7900 constructor: Object3D,
7901
7902 isObject3D: true,
7903
7904 onBeforeRender: function () {},
7905 onAfterRender: function () {},
7906
7907 applyMatrix: function ( matrix ) {
7908
7909 this.matrix.multiplyMatrices( matrix, this.matrix );
7910
7911 this.matrix.decompose( this.position, this.quaternion, this.scale );
7912
7913 },
7914
7915 applyQuaternion: function ( q ) {
7916
7917 this.quaternion.premultiply( q );
7918
7919 return this;
7920
7921 },
7922
7923 setRotationFromAxisAngle: function ( axis, angle ) {
7924
7925 // assumes axis is normalized
7926
7927 this.quaternion.setFromAxisAngle( axis, angle );
7928
7929 },
7930
7931 setRotationFromEuler: function ( euler ) {
7932
7933 this.quaternion.setFromEuler( euler, true );
7934
7935 },
7936
7937 setRotationFromMatrix: function ( m ) {
7938
7939 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
7940
7941 this.quaternion.setFromRotationMatrix( m );
7942
7943 },
7944
7945 setRotationFromQuaternion: function ( q ) {
7946
7947 // assumes q is normalized
7948
7949 this.quaternion.copy( q );
7950
7951 },
7952
7953 rotateOnAxis: function () {
7954
7955 // rotate object on axis in object space
7956 // axis is assumed to be normalized
7957
7958 var q1 = new Quaternion();
7959
7960 return function rotateOnAxis( axis, angle ) {
7961
7962 q1.setFromAxisAngle( axis, angle );
7963
7964 this.quaternion.multiply( q1 );
7965
7966 return this;
7967
7968 };
7969
7970 }(),
7971
7972 rotateOnWorldAxis: function () {
7973
7974 // rotate object on axis in world space
7975 // axis is assumed to be normalized
7976 // method assumes no rotated parent
7977
7978 var q1 = new Quaternion();
7979
7980 return function rotateOnWorldAxis( axis, angle ) {
7981
7982 q1.setFromAxisAngle( axis, angle );
7983
7984 this.quaternion.premultiply( q1 );
7985
7986 return this;
7987
7988 };
7989
7990 }(),
7991
7992 rotateX: function () {
7993
7994 var v1 = new Vector3( 1, 0, 0 );
7995
7996 return function rotateX( angle ) {
7997
7998 return this.rotateOnAxis( v1, angle );
7999
8000 };
8001
8002 }(),
8003
8004 rotateY: function () {
8005
8006 var v1 = new Vector3( 0, 1, 0 );
8007
8008 return function rotateY( angle ) {
8009
8010 return this.rotateOnAxis( v1, angle );
8011
8012 };
8013
8014 }(),
8015
8016 rotateZ: function () {
8017
8018 var v1 = new Vector3( 0, 0, 1 );
8019
8020 return function rotateZ( angle ) {
8021
8022 return this.rotateOnAxis( v1, angle );
8023
8024 };
8025
8026 }(),
8027
8028 translateOnAxis: function () {
8029
8030 // translate object by distance along axis in object space
8031 // axis is assumed to be normalized
8032
8033 var v1 = new Vector3();
8034
8035 return function translateOnAxis( axis, distance ) {
8036
8037 v1.copy( axis ).applyQuaternion( this.quaternion );
8038
8039 this.position.add( v1.multiplyScalar( distance ) );
8040
8041 return this;
8042
8043 };
8044
8045 }(),
8046
8047 translateX: function () {
8048
8049 var v1 = new Vector3( 1, 0, 0 );
8050
8051 return function translateX( distance ) {
8052
8053 return this.translateOnAxis( v1, distance );
8054
8055 };
8056
8057 }(),
8058
8059 translateY: function () {
8060
8061 var v1 = new Vector3( 0, 1, 0 );
8062
8063 return function translateY( distance ) {
8064
8065 return this.translateOnAxis( v1, distance );
8066
8067 };
8068
8069 }(),
8070
8071 translateZ: function () {
8072
8073 var v1 = new Vector3( 0, 0, 1 );
8074
8075 return function translateZ( distance ) {
8076
8077 return this.translateOnAxis( v1, distance );
8078
8079 };
8080
8081 }(),
8082
8083 localToWorld: function ( vector ) {
8084
8085 return vector.applyMatrix4( this.matrixWorld );
8086
8087 },
8088
8089 worldToLocal: function () {
8090
8091 var m1 = new Matrix4();
8092
8093 return function worldToLocal( vector ) {
8094
8095 return vector.applyMatrix4( m1.getInverse( this.matrixWorld ) );
8096
8097 };
8098
8099 }(),
8100
8101 lookAt: function () {
8102
8103 // This method does not support objects with rotated and/or translated parent(s)
8104
8105 var m1 = new Matrix4();
8106 var vector = new Vector3();
8107
8108 return function lookAt( x, y, z ) {
8109
8110 if ( x.isVector3 ) {
8111
8112 vector.copy( x );
8113
8114 } else {
8115
8116 vector.set( x, y, z );
8117
8118 }
8119
8120 if ( this.isCamera ) {
8121
8122 m1.lookAt( this.position, vector, this.up );
8123
8124 } else {
8125
8126 m1.lookAt( vector, this.position, this.up );
8127
8128 }
8129
8130 this.quaternion.setFromRotationMatrix( m1 );
8131
8132 };
8133
8134 }(),
8135
8136 add: function ( object ) {
8137
8138 if ( arguments.length > 1 ) {
8139
8140 for ( var i = 0; i < arguments.length; i ++ ) {
8141
8142 this.add( arguments[ i ] );
8143
8144 }
8145
8146 return this;
8147
8148 }
8149
8150 if ( object === this ) {
8151
8152 console.error( "THREE.Object3D.add: object can't be added as a child of itself.", object );
8153 return this;
8154
8155 }
8156
8157 if ( ( object && object.isObject3D ) ) {
8158
8159 if ( object.parent !== null ) {
8160
8161 object.parent.remove( object );
8162
8163 }
8164
8165 object.parent = this;
8166 object.dispatchEvent( { type: 'added' } );
8167
8168 this.children.push( object );
8169
8170 } else {
8171
8172 console.error( "THREE.Object3D.add: object not an instance of THREE.Object3D.", object );
8173
8174 }
8175
8176 return this;
8177
8178 },
8179
8180 remove: function ( object ) {
8181
8182 if ( arguments.length > 1 ) {
8183
8184 for ( var i = 0; i < arguments.length; i ++ ) {
8185
8186 this.remove( arguments[ i ] );
8187
8188 }
8189
8190 return this;
8191
8192 }
8193
8194 var index = this.children.indexOf( object );
8195
8196 if ( index !== - 1 ) {
8197
8198 object.parent = null;
8199
8200 object.dispatchEvent( { type: 'removed' } );
8201
8202 this.children.splice( index, 1 );
8203
8204 }
8205
8206 return this;
8207
8208 },
8209
8210 getObjectById: function ( id ) {
8211
8212 return this.getObjectByProperty( 'id', id );
8213
8214 },
8215
8216 getObjectByName: function ( name ) {
8217
8218 return this.getObjectByProperty( 'name', name );
8219
8220 },
8221
8222 getObjectByProperty: function ( name, value ) {
8223
8224 if ( this[ name ] === value ) return this;
8225
8226 for ( var i = 0, l = this.children.length; i < l; i ++ ) {
8227
8228 var child = this.children[ i ];
8229 var object = child.getObjectByProperty( name, value );
8230
8231 if ( object !== undefined ) {
8232
8233 return object;
8234
8235 }
8236
8237 }
8238
8239 return undefined;
8240
8241 },
8242
8243 getWorldPosition: function ( target ) {
8244
8245 if ( target === undefined ) {
8246
8247 console.warn( 'THREE.Object3D: .getWorldPosition() target is now required' );
8248 target = new Vector3();
8249
8250 }
8251
8252 this.updateMatrixWorld( true );
8253
8254 return target.setFromMatrixPosition( this.matrixWorld );
8255
8256 },
8257
8258 getWorldQuaternion: function () {
8259
8260 var position = new Vector3();
8261 var scale = new Vector3();
8262
8263 return function getWorldQuaternion( target ) {
8264
8265 if ( target === undefined ) {
8266
8267 console.warn( 'THREE.Object3D: .getWorldQuaternion() target is now required' );
8268 target = new Quaternion();
8269
8270 }
8271
8272 this.updateMatrixWorld( true );
8273
8274 this.matrixWorld.decompose( position, target, scale );
8275
8276 return target;
8277
8278 };
8279
8280 }(),
8281
8282 getWorldScale: function () {
8283
8284 var position = new Vector3();
8285 var quaternion = new Quaternion();
8286
8287 return function getWorldScale( target ) {
8288
8289 if ( target === undefined ) {
8290
8291 console.warn( 'THREE.Object3D: .getWorldScale() target is now required' );
8292 target = new Vector3();
8293
8294 }
8295
8296 this.updateMatrixWorld( true );
8297
8298 this.matrixWorld.decompose( position, quaternion, target );
8299
8300 return target;
8301
8302 };
8303
8304 }(),
8305
8306 getWorldDirection: function () {
8307
8308 var quaternion = new Quaternion();
8309
8310 return function getWorldDirection( target ) {
8311
8312 if ( target === undefined ) {
8313
8314 console.warn( 'THREE.Object3D: .getWorldDirection() target is now required' );
8315 target = new Vector3();
8316
8317 }
8318
8319 this.getWorldQuaternion( quaternion );
8320
8321 return target.set( 0, 0, 1 ).applyQuaternion( quaternion );
8322
8323 };
8324
8325 }(),
8326
8327 raycast: function () {},
8328
8329 traverse: function ( callback ) {
8330
8331 callback( this );
8332
8333 var children = this.children;
8334
8335 for ( var i = 0, l = children.length; i < l; i ++ ) {
8336
8337 children[ i ].traverse( callback );
8338
8339 }
8340
8341 },
8342
8343 traverseVisible: function ( callback ) {
8344
8345 if ( this.visible === false ) return;
8346
8347 callback( this );
8348
8349 var children = this.children;
8350
8351 for ( var i = 0, l = children.length; i < l; i ++ ) {
8352
8353 children[ i ].traverseVisible( callback );
8354
8355 }
8356
8357 },
8358
8359 traverseAncestors: function ( callback ) {
8360
8361 var parent = this.parent;
8362
8363 if ( parent !== null ) {
8364
8365 callback( parent );
8366
8367 parent.traverseAncestors( callback );
8368
8369 }
8370
8371 },
8372
8373 updateMatrix: function () {
8374
8375 this.matrix.compose( this.position, this.quaternion, this.scale );
8376
8377 this.matrixWorldNeedsUpdate = true;
8378
8379 },
8380
8381 updateMatrixWorld: function ( force ) {
8382
8383 if ( this.matrixAutoUpdate ) this.updateMatrix();
8384
8385 if ( this.matrixWorldNeedsUpdate || force ) {
8386
8387 if ( this.parent === null ) {
8388
8389 this.matrixWorld.copy( this.matrix );
8390
8391 } else {
8392
8393 this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
8394
8395 }
8396
8397 this.matrixWorldNeedsUpdate = false;
8398
8399 force = true;
8400
8401 }
8402
8403 // update children
8404
8405 var children = this.children;
8406
8407 for ( var i = 0, l = children.length; i < l; i ++ ) {
8408
8409 children[ i ].updateMatrixWorld( force );
8410
8411 }
8412
8413 },
8414
8415 toJSON: function ( meta ) {
8416
8417 // meta is a string when called from JSON.stringify
8418 var isRootObject = ( meta === undefined || typeof meta === 'string' );
8419
8420 var output = {};
8421
8422 // meta is a hash used to collect geometries, materials.
8423 // not providing it implies that this is the root object
8424 // being serialized.
8425 if ( isRootObject ) {
8426
8427 // initialize meta obj
8428 meta = {
8429 geometries: {},
8430 materials: {},
8431 textures: {},
8432 images: {},
8433 shapes: {}
8434 };
8435
8436 output.metadata = {
8437 version: 4.5,
8438 type: 'Object',
8439 generator: 'Object3D.toJSON'
8440 };
8441
8442 }
8443
8444 // standard Object3D serialization
8445
8446 var object = {};
8447
8448 object.uuid = this.uuid;
8449 object.type = this.type;
8450
8451 if ( this.name !== '' ) object.name = this.name;
8452 if ( this.castShadow === true ) object.castShadow = true;
8453 if ( this.receiveShadow === true ) object.receiveShadow = true;
8454 if ( this.visible === false ) object.visible = false;
8455 if ( this.frustumCulled === false ) object.frustumCulled = false;
8456 if ( this.renderOrder !== 0 ) object.renderOrder = this.renderOrder;
8457 if ( JSON.stringify( this.userData ) !== '{}' ) object.userData = this.userData;
8458
8459 object.matrix = this.matrix.toArray();
8460
8461 if ( this.matrixAutoUpdate === false ) object.matrixAutoUpdate = false;
8462
8463 //
8464
8465 function serialize( library, element ) {
8466
8467 if ( library[ element.uuid ] === undefined ) {
8468
8469 library[ element.uuid ] = element.toJSON( meta );
8470
8471 }
8472
8473 return element.uuid;
8474
8475 }
8476
8477 if ( this.geometry !== undefined ) {
8478
8479 object.geometry = serialize( meta.geometries, this.geometry );
8480
8481 var parameters = this.geometry.parameters;
8482
8483 if ( parameters !== undefined && parameters.shapes !== undefined ) {
8484
8485 var shapes = parameters.shapes;
8486
8487 if ( Array.isArray( shapes ) ) {
8488
8489 for ( var i = 0, l = shapes.length; i < l; i ++ ) {
8490
8491 var shape = shapes[ i ];
8492
8493 serialize( meta.shapes, shape );
8494
8495 }
8496
8497 } else {
8498
8499 serialize( meta.shapes, shapes );
8500
8501 }
8502
8503 }
8504
8505 }
8506
8507 if ( this.material !== undefined ) {
8508
8509 if ( Array.isArray( this.material ) ) {
8510
8511 var uuids = [];
8512
8513 for ( var i = 0, l = this.material.length; i < l; i ++ ) {
8514
8515 uuids.push( serialize( meta.materials, this.material[ i ] ) );
8516
8517 }
8518
8519 object.material = uuids;
8520
8521 } else {
8522
8523 object.material = serialize( meta.materials, this.material );
8524
8525 }
8526
8527 }
8528
8529 //
8530
8531 if ( this.children.length > 0 ) {
8532
8533 object.children = [];
8534
8535 for ( var i = 0; i < this.children.length; i ++ ) {
8536
8537 object.children.push( this.children[ i ].toJSON( meta ).object );
8538
8539 }
8540
8541 }
8542
8543 if ( isRootObject ) {
8544
8545 var geometries = extractFromCache( meta.geometries );
8546 var materials = extractFromCache( meta.materials );
8547 var textures = extractFromCache( meta.textures );
8548 var images = extractFromCache( meta.images );
8549 var shapes = extractFromCache( meta.shapes );
8550
8551 if ( geometries.length > 0 ) output.geometries = geometries;
8552 if ( materials.length > 0 ) output.materials = materials;
8553 if ( textures.length > 0 ) output.textures = textures;
8554 if ( images.length > 0 ) output.images = images;
8555 if ( shapes.length > 0 ) output.shapes = shapes;
8556
8557 }
8558
8559 output.object = object;
8560
8561 return output;
8562
8563 // extract data from the cache hash
8564 // remove metadata on each item
8565 // and return as array
8566 function extractFromCache( cache ) {
8567
8568 var values = [];
8569 for ( var key in cache ) {
8570
8571 var data = cache[ key ];
8572 delete data.metadata;
8573 values.push( data );
8574
8575 }
8576 return values;
8577
8578 }
8579
8580 },
8581
8582 clone: function ( recursive ) {
8583
8584 return new this.constructor().copy( this, recursive );
8585
8586 },
8587
8588 copy: function ( source, recursive ) {
8589
8590 if ( recursive === undefined ) recursive = true;
8591
8592 this.name = source.name;
8593
8594 this.up.copy( source.up );
8595
8596 this.position.copy( source.position );
8597 this.quaternion.copy( source.quaternion );
8598 this.scale.copy( source.scale );
8599
8600 this.matrix.copy( source.matrix );
8601 this.matrixWorld.copy( source.matrixWorld );
8602
8603 this.matrixAutoUpdate = source.matrixAutoUpdate;
8604 this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate;
8605
8606 this.layers.mask = source.layers.mask;
8607 this.visible = source.visible;
8608
8609 this.castShadow = source.castShadow;
8610 this.receiveShadow = source.receiveShadow;
8611
8612 this.frustumCulled = source.frustumCulled;
8613 this.renderOrder = source.renderOrder;
8614
8615 this.userData = JSON.parse( JSON.stringify( source.userData ) );
8616
8617 if ( recursive === true ) {
8618
8619 for ( var i = 0; i < source.children.length; i ++ ) {
8620
8621 var child = source.children[ i ];
8622 this.add( child.clone() );
8623
8624 }
8625
8626 }
8627
8628 return this;
8629
8630 }
8631
8632 } );
8633
8634 /**
8635 * @author mrdoob / http://mrdoob.com/
8636 * @author mikael emtinger / http://gomo.se/
8637 * @author WestLangley / http://github.com/WestLangley
8638 */
8639
8640 function Camera() {
8641
8642 Object3D.call( this );
8643
8644 this.type = 'Camera';
8645
8646 this.matrixWorldInverse = new Matrix4();
8647 this.projectionMatrix = new Matrix4();
8648
8649 }
8650
8651 Camera.prototype = Object.assign( Object.create( Object3D.prototype ), {
8652
8653 constructor: Camera,
8654
8655 isCamera: true,
8656
8657 copy: function ( source, recursive ) {
8658
8659 Object3D.prototype.copy.call( this, source, recursive );
8660
8661 this.matrixWorldInverse.copy( source.matrixWorldInverse );
8662 this.projectionMatrix.copy( source.projectionMatrix );
8663
8664 return this;
8665
8666 },
8667
8668 getWorldDirection: function () {
8669
8670 var quaternion = new Quaternion();
8671
8672 return function getWorldDirection( target ) {
8673
8674 if ( target === undefined ) {
8675
8676 console.warn( 'THREE.Camera: .getWorldDirection() target is now required' );
8677 target = new Vector3();
8678
8679 }
8680
8681 this.getWorldQuaternion( quaternion );
8682
8683 return target.set( 0, 0, - 1 ).applyQuaternion( quaternion );
8684
8685 };
8686
8687 }(),
8688
8689 updateMatrixWorld: function ( force ) {
8690
8691 Object3D.prototype.updateMatrixWorld.call( this, force );
8692
8693 this.matrixWorldInverse.getInverse( this.matrixWorld );
8694
8695 },
8696
8697 clone: function () {
8698
8699 return new this.constructor().copy( this );
8700
8701 }
8702
8703 } );
8704
8705 /**
8706 * @author alteredq / http://alteredqualia.com/
8707 * @author arose / http://github.com/arose
8708 */
8709
8710 function OrthographicCamera( left, right, top, bottom, near, far ) {
8711
8712 Camera.call( this );
8713
8714 this.type = 'OrthographicCamera';
8715
8716 this.zoom = 1;
8717 this.view = null;
8718
8719 this.left = left;
8720 this.right = right;
8721 this.top = top;
8722 this.bottom = bottom;
8723
8724 this.near = ( near !== undefined ) ? near : 0.1;
8725 this.far = ( far !== undefined ) ? far : 2000;
8726
8727 this.updateProjectionMatrix();
8728
8729 }
8730
8731 OrthographicCamera.prototype = Object.assign( Object.create( Camera.prototype ), {
8732
8733 constructor: OrthographicCamera,
8734
8735 isOrthographicCamera: true,
8736
8737 copy: function ( source, recursive ) {
8738
8739 Camera.prototype.copy.call( this, source, recursive );
8740
8741 this.left = source.left;
8742 this.right = source.right;
8743 this.top = source.top;
8744 this.bottom = source.bottom;
8745 this.near = source.near;
8746 this.far = source.far;
8747
8748 this.zoom = source.zoom;
8749 this.view = source.view === null ? null : Object.assign( {}, source.view );
8750
8751 return this;
8752
8753 },
8754
8755 setViewOffset: function ( fullWidth, fullHeight, x, y, width, height ) {
8756
8757 if ( this.view === null ) {
8758
8759 this.view = {
8760 enabled: true,
8761 fullWidth: 1,
8762 fullHeight: 1,
8763 offsetX: 0,
8764 offsetY: 0,
8765 width: 1,
8766 height: 1
8767 };
8768
8769 }
8770
8771 this.view.enabled = true;
8772 this.view.fullWidth = fullWidth;
8773 this.view.fullHeight = fullHeight;
8774 this.view.offsetX = x;
8775 this.view.offsetY = y;
8776 this.view.width = width;
8777 this.view.height = height;
8778
8779 this.updateProjectionMatrix();
8780
8781 },
8782
8783 clearViewOffset: function () {
8784
8785 if ( this.view !== null ) {
8786
8787 this.view.enabled = false;
8788
8789 }
8790
8791 this.updateProjectionMatrix();
8792
8793 },
8794
8795 updateProjectionMatrix: function () {
8796
8797 var dx = ( this.right - this.left ) / ( 2 * this.zoom );
8798 var dy = ( this.top - this.bottom ) / ( 2 * this.zoom );
8799 var cx = ( this.right + this.left ) / 2;
8800 var cy = ( this.top + this.bottom ) / 2;
8801
8802 var left = cx - dx;
8803 var right = cx + dx;
8804 var top = cy + dy;
8805 var bottom = cy - dy;
8806
8807 if ( this.view !== null && this.view.enabled ) {
8808
8809 var zoomW = this.zoom / ( this.view.width / this.view.fullWidth );
8810 var zoomH = this.zoom / ( this.view.height / this.view.fullHeight );
8811 var scaleW = ( this.right - this.left ) / this.view.width;
8812 var scaleH = ( this.top - this.bottom ) / this.view.height;
8813
8814 left += scaleW * ( this.view.offsetX / zoomW );
8815 right = left + scaleW * ( this.view.width / zoomW );
8816 top -= scaleH * ( this.view.offsetY / zoomH );
8817 bottom = top - scaleH * ( this.view.height / zoomH );
8818
8819 }
8820
8821 this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far );
8822
8823 },
8824
8825 toJSON: function ( meta ) {
8826
8827 var data = Object3D.prototype.toJSON.call( this, meta );
8828
8829 data.object.zoom = this.zoom;
8830 data.object.left = this.left;
8831 data.object.right = this.right;
8832 data.object.top = this.top;
8833 data.object.bottom = this.bottom;
8834 data.object.near = this.near;
8835 data.object.far = this.far;
8836
8837 if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
8838
8839 return data;
8840
8841 }
8842
8843 } );
8844
8845 /**
8846 * @author mrdoob / http://mrdoob.com/
8847 * @author alteredq / http://alteredqualia.com/
8848 */
8849
8850 function Face3( a, b, c, normal, color, materialIndex ) {
8851
8852 this.a = a;
8853 this.b = b;
8854 this.c = c;
8855
8856 this.normal = ( normal && normal.isVector3 ) ? normal : new Vector3();
8857 this.vertexNormals = Array.isArray( normal ) ? normal : [];
8858
8859 this.color = ( color && color.isColor ) ? color : new Color();
8860 this.vertexColors = Array.isArray( color ) ? color : [];
8861
8862 this.materialIndex = materialIndex !== undefined ? materialIndex : 0;
8863
8864 }
8865
8866 Object.assign( Face3.prototype, {
8867
8868 clone: function () {
8869
8870 return new this.constructor().copy( this );
8871
8872 },
8873
8874 copy: function ( source ) {
8875
8876 this.a = source.a;
8877 this.b = source.b;
8878 this.c = source.c;
8879
8880 this.normal.copy( source.normal );
8881 this.color.copy( source.color );
8882
8883 this.materialIndex = source.materialIndex;
8884
8885 for ( var i = 0, il = source.vertexNormals.length; i < il; i ++ ) {
8886
8887 this.vertexNormals[ i ] = source.vertexNormals[ i ].clone();
8888
8889 }
8890
8891 for ( var i = 0, il = source.vertexColors.length; i < il; i ++ ) {
8892
8893 this.vertexColors[ i ] = source.vertexColors[ i ].clone();
8894
8895 }
8896
8897 return this;
8898
8899 }
8900
8901 } );
8902
8903 /**
8904 * @author mrdoob / http://mrdoob.com/
8905 * @author kile / http://kile.stravaganza.org/
8906 * @author alteredq / http://alteredqualia.com/
8907 * @author mikael emtinger / http://gomo.se/
8908 * @author zz85 / http://www.lab4games.net/zz85/blog
8909 * @author bhouston / http://clara.io
8910 */
8911
8912 var geometryId = 0; // Geometry uses even numbers as Id
8913
8914 function Geometry() {
8915
8916 Object.defineProperty( this, 'id', { value: geometryId += 2 } );
8917
8918 this.uuid = _Math.generateUUID();
8919
8920 this.name = '';
8921 this.type = 'Geometry';
8922
8923 this.vertices = [];
8924 this.colors = [];
8925 this.faces = [];
8926 this.faceVertexUvs = [[]];
8927
8928 this.morphTargets = [];
8929 this.morphNormals = [];
8930
8931 this.skinWeights = [];
8932 this.skinIndices = [];
8933
8934 this.lineDistances = [];
8935
8936 this.boundingBox = null;
8937 this.boundingSphere = null;
8938
8939 // update flags
8940
8941 this.elementsNeedUpdate = false;
8942 this.verticesNeedUpdate = false;
8943 this.uvsNeedUpdate = false;
8944 this.normalsNeedUpdate = false;
8945 this.colorsNeedUpdate = false;
8946 this.lineDistancesNeedUpdate = false;
8947 this.groupsNeedUpdate = false;
8948
8949 }
8950
8951 Geometry.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
8952
8953 constructor: Geometry,
8954
8955 isGeometry: true,
8956
8957 applyMatrix: function ( matrix ) {
8958
8959 var normalMatrix = new Matrix3().getNormalMatrix( matrix );
8960
8961 for ( var i = 0, il = this.vertices.length; i < il; i ++ ) {
8962
8963 var vertex = this.vertices[ i ];
8964 vertex.applyMatrix4( matrix );
8965
8966 }
8967
8968 for ( var i = 0, il = this.faces.length; i < il; i ++ ) {
8969
8970 var face = this.faces[ i ];
8971 face.normal.applyMatrix3( normalMatrix ).normalize();
8972
8973 for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {
8974
8975 face.vertexNormals[ j ].applyMatrix3( normalMatrix ).normalize();
8976
8977 }
8978
8979 }
8980
8981 if ( this.boundingBox !== null ) {
8982
8983 this.computeBoundingBox();
8984
8985 }
8986
8987 if ( this.boundingSphere !== null ) {
8988
8989 this.computeBoundingSphere();
8990
8991 }
8992
8993 this.verticesNeedUpdate = true;
8994 this.normalsNeedUpdate = true;
8995
8996 return this;
8997
8998 },
8999
9000 rotateX: function () {
9001
9002 // rotate geometry around world x-axis
9003
9004 var m1 = new Matrix4();
9005
9006 return function rotateX( angle ) {
9007
9008 m1.makeRotationX( angle );
9009
9010 this.applyMatrix( m1 );
9011
9012 return this;
9013
9014 };
9015
9016 }(),
9017
9018 rotateY: function () {
9019
9020 // rotate geometry around world y-axis
9021
9022 var m1 = new Matrix4();
9023
9024 return function rotateY( angle ) {
9025
9026 m1.makeRotationY( angle );
9027
9028 this.applyMatrix( m1 );
9029
9030 return this;
9031
9032 };
9033
9034 }(),
9035
9036 rotateZ: function () {
9037
9038 // rotate geometry around world z-axis
9039
9040 var m1 = new Matrix4();
9041
9042 return function rotateZ( angle ) {
9043
9044 m1.makeRotationZ( angle );
9045
9046 this.applyMatrix( m1 );
9047
9048 return this;
9049
9050 };
9051
9052 }(),
9053
9054 translate: function () {
9055
9056 // translate geometry
9057
9058 var m1 = new Matrix4();
9059
9060 return function translate( x, y, z ) {
9061
9062 m1.makeTranslation( x, y, z );
9063
9064 this.applyMatrix( m1 );
9065
9066 return this;
9067
9068 };
9069
9070 }(),
9071
9072 scale: function () {
9073
9074 // scale geometry
9075
9076 var m1 = new Matrix4();
9077
9078 return function scale( x, y, z ) {
9079
9080 m1.makeScale( x, y, z );
9081
9082 this.applyMatrix( m1 );
9083
9084 return this;
9085
9086 };
9087
9088 }(),
9089
9090 lookAt: function () {
9091
9092 var obj = new Object3D();
9093
9094 return function lookAt( vector ) {
9095
9096 obj.lookAt( vector );
9097
9098 obj.updateMatrix();
9099
9100 this.applyMatrix( obj.matrix );
9101
9102 };
9103
9104 }(),
9105
9106 fromBufferGeometry: function ( geometry ) {
9107
9108 var scope = this;
9109
9110 var indices = geometry.index !== null ? geometry.index.array : undefined;
9111 var attributes = geometry.attributes;
9112
9113 var positions = attributes.position.array;
9114 var normals = attributes.normal !== undefined ? attributes.normal.array : undefined;
9115 var colors = attributes.color !== undefined ? attributes.color.array : undefined;
9116 var uvs = attributes.uv !== undefined ? attributes.uv.array : undefined;
9117 var uvs2 = attributes.uv2 !== undefined ? attributes.uv2.array : undefined;
9118
9119 if ( uvs2 !== undefined ) this.faceVertexUvs[ 1 ] = [];
9120
9121 var tempNormals = [];
9122 var tempUVs = [];
9123 var tempUVs2 = [];
9124
9125 for ( var i = 0, j = 0; i < positions.length; i += 3, j += 2 ) {
9126
9127 scope.vertices.push( new Vector3( positions[ i ], positions[ i + 1 ], positions[ i + 2 ] ) );
9128
9129 if ( normals !== undefined ) {
9130
9131 tempNormals.push( new Vector3( normals[ i ], normals[ i + 1 ], normals[ i + 2 ] ) );
9132
9133 }
9134
9135 if ( colors !== undefined ) {
9136
9137 scope.colors.push( new Color( colors[ i ], colors[ i + 1 ], colors[ i + 2 ] ) );
9138
9139 }
9140
9141 if ( uvs !== undefined ) {
9142
9143 tempUVs.push( new Vector2( uvs[ j ], uvs[ j + 1 ] ) );
9144
9145 }
9146
9147 if ( uvs2 !== undefined ) {
9148
9149 tempUVs2.push( new Vector2( uvs2[ j ], uvs2[ j + 1 ] ) );
9150
9151 }
9152
9153 }
9154
9155 function addFace( a, b, c, materialIndex ) {
9156
9157 var vertexNormals = normals !== undefined ? [ tempNormals[ a ].clone(), tempNormals[ b ].clone(), tempNormals[ c ].clone() ] : [];
9158 var vertexColors = colors !== undefined ? [ scope.colors[ a ].clone(), scope.colors[ b ].clone(), scope.colors[ c ].clone() ] : [];
9159
9160 var face = new Face3( a, b, c, vertexNormals, vertexColors, materialIndex );
9161
9162 scope.faces.push( face );
9163
9164 if ( uvs !== undefined ) {
9165
9166 scope.faceVertexUvs[ 0 ].push( [ tempUVs[ a ].clone(), tempUVs[ b ].clone(), tempUVs[ c ].clone() ] );
9167
9168 }
9169
9170 if ( uvs2 !== undefined ) {
9171
9172 scope.faceVertexUvs[ 1 ].push( [ tempUVs2[ a ].clone(), tempUVs2[ b ].clone(), tempUVs2[ c ].clone() ] );
9173
9174 }
9175
9176 }
9177
9178 var groups = geometry.groups;
9179
9180 if ( groups.length > 0 ) {
9181
9182 for ( var i = 0; i < groups.length; i ++ ) {
9183
9184 var group = groups[ i ];
9185
9186 var start = group.start;
9187 var count = group.count;
9188
9189 for ( var j = start, jl = start + count; j < jl; j += 3 ) {
9190
9191 if ( indices !== undefined ) {
9192
9193 addFace( indices[ j ], indices[ j + 1 ], indices[ j + 2 ], group.materialIndex );
9194
9195 } else {
9196
9197 addFace( j, j + 1, j + 2, group.materialIndex );
9198
9199 }
9200
9201 }
9202
9203 }
9204
9205 } else {
9206
9207 if ( indices !== undefined ) {
9208
9209 for ( var i = 0; i < indices.length; i += 3 ) {
9210
9211 addFace( indices[ i ], indices[ i + 1 ], indices[ i + 2 ] );
9212
9213 }
9214
9215 } else {
9216
9217 for ( var i = 0; i < positions.length / 3; i += 3 ) {
9218
9219 addFace( i, i + 1, i + 2 );
9220
9221 }
9222
9223 }
9224
9225 }
9226
9227 this.computeFaceNormals();
9228
9229 if ( geometry.boundingBox !== null ) {
9230
9231 this.boundingBox = geometry.boundingBox.clone();
9232
9233 }
9234
9235 if ( geometry.boundingSphere !== null ) {
9236
9237 this.boundingSphere = geometry.boundingSphere.clone();
9238
9239 }
9240
9241 return this;
9242
9243 },
9244
9245 center: function () {
9246
9247 var offset = new Vector3();
9248
9249 return function center() {
9250
9251 this.computeBoundingBox();
9252
9253 this.boundingBox.getCenter( offset ).negate();
9254
9255 this.translate( offset.x, offset.y, offset.z );
9256
9257 return this;
9258
9259 };
9260
9261 }(),
9262
9263 normalize: function () {
9264
9265 this.computeBoundingSphere();
9266
9267 var center = this.boundingSphere.center;
9268 var radius = this.boundingSphere.radius;
9269
9270 var s = radius === 0 ? 1 : 1.0 / radius;
9271
9272 var matrix = new Matrix4();
9273 matrix.set(
9274 s, 0, 0, - s * center.x,
9275 0, s, 0, - s * center.y,
9276 0, 0, s, - s * center.z,
9277 0, 0, 0, 1
9278 );
9279
9280 this.applyMatrix( matrix );
9281
9282 return this;
9283
9284 },
9285
9286 computeFaceNormals: function () {
9287
9288 var cb = new Vector3(), ab = new Vector3();
9289
9290 for ( var f = 0, fl = this.faces.length; f < fl; f ++ ) {
9291
9292 var face = this.faces[ f ];
9293
9294 var vA = this.vertices[ face.a ];
9295 var vB = this.vertices[ face.b ];
9296 var vC = this.vertices[ face.c ];
9297
9298 cb.subVectors( vC, vB );
9299 ab.subVectors( vA, vB );
9300 cb.cross( ab );
9301
9302 cb.normalize();
9303
9304 face.normal.copy( cb );
9305
9306 }
9307
9308 },
9309
9310 computeVertexNormals: function ( areaWeighted ) {
9311
9312 if ( areaWeighted === undefined ) areaWeighted = true;
9313
9314 var v, vl, f, fl, face, vertices;
9315
9316 vertices = new Array( this.vertices.length );
9317
9318 for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
9319
9320 vertices[ v ] = new Vector3();
9321
9322 }
9323
9324 if ( areaWeighted ) {
9325
9326 // vertex normals weighted by triangle areas
9327 // http://www.iquilezles.org/www/articles/normals/normals.htm
9328
9329 var vA, vB, vC;
9330 var cb = new Vector3(), ab = new Vector3();
9331
9332 for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
9333
9334 face = this.faces[ f ];
9335
9336 vA = this.vertices[ face.a ];
9337 vB = this.vertices[ face.b ];
9338 vC = this.vertices[ face.c ];
9339
9340 cb.subVectors( vC, vB );
9341 ab.subVectors( vA, vB );
9342 cb.cross( ab );
9343
9344 vertices[ face.a ].add( cb );
9345 vertices[ face.b ].add( cb );
9346 vertices[ face.c ].add( cb );
9347
9348 }
9349
9350 } else {
9351
9352 this.computeFaceNormals();
9353
9354 for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
9355
9356 face = this.faces[ f ];
9357
9358 vertices[ face.a ].add( face.normal );
9359 vertices[ face.b ].add( face.normal );
9360 vertices[ face.c ].add( face.normal );
9361
9362 }
9363
9364 }
9365
9366 for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
9367
9368 vertices[ v ].normalize();
9369
9370 }
9371
9372 for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
9373
9374 face = this.faces[ f ];
9375
9376 var vertexNormals = face.vertexNormals;
9377
9378 if ( vertexNormals.length === 3 ) {
9379
9380 vertexNormals[ 0 ].copy( vertices[ face.a ] );
9381 vertexNormals[ 1 ].copy( vertices[ face.b ] );
9382 vertexNormals[ 2 ].copy( vertices[ face.c ] );
9383
9384 } else {
9385
9386 vertexNormals[ 0 ] = vertices[ face.a ].clone();
9387 vertexNormals[ 1 ] = vertices[ face.b ].clone();
9388 vertexNormals[ 2 ] = vertices[ face.c ].clone();
9389
9390 }
9391
9392 }
9393
9394 if ( this.faces.length > 0 ) {
9395
9396 this.normalsNeedUpdate = true;
9397
9398 }
9399
9400 },
9401
9402 computeFlatVertexNormals: function () {
9403
9404 var f, fl, face;
9405
9406 this.computeFaceNormals();
9407
9408 for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
9409
9410 face = this.faces[ f ];
9411
9412 var vertexNormals = face.vertexNormals;
9413
9414 if ( vertexNormals.length === 3 ) {
9415
9416 vertexNormals[ 0 ].copy( face.normal );
9417 vertexNormals[ 1 ].copy( face.normal );
9418 vertexNormals[ 2 ].copy( face.normal );
9419
9420 } else {
9421
9422 vertexNormals[ 0 ] = face.normal.clone();
9423 vertexNormals[ 1 ] = face.normal.clone();
9424 vertexNormals[ 2 ] = face.normal.clone();
9425
9426 }
9427
9428 }
9429
9430 if ( this.faces.length > 0 ) {
9431
9432 this.normalsNeedUpdate = true;
9433
9434 }
9435
9436 },
9437
9438 computeMorphNormals: function () {
9439
9440 var i, il, f, fl, face;
9441
9442 // save original normals
9443 // - create temp variables on first access
9444 // otherwise just copy (for faster repeated calls)
9445
9446 for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
9447
9448 face = this.faces[ f ];
9449
9450 if ( ! face.__originalFaceNormal ) {
9451
9452 face.__originalFaceNormal = face.normal.clone();
9453
9454 } else {
9455
9456 face.__originalFaceNormal.copy( face.normal );
9457
9458 }
9459
9460 if ( ! face.__originalVertexNormals ) face.__originalVertexNormals = [];
9461
9462 for ( i = 0, il = face.vertexNormals.length; i < il; i ++ ) {
9463
9464 if ( ! face.__originalVertexNormals[ i ] ) {
9465
9466 face.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone();
9467
9468 } else {
9469
9470 face.__originalVertexNormals[ i ].copy( face.vertexNormals[ i ] );
9471
9472 }
9473
9474 }
9475
9476 }
9477
9478 // use temp geometry to compute face and vertex normals for each morph
9479
9480 var tmpGeo = new Geometry();
9481 tmpGeo.faces = this.faces;
9482
9483 for ( i = 0, il = this.morphTargets.length; i < il; i ++ ) {
9484
9485 // create on first access
9486
9487 if ( ! this.morphNormals[ i ] ) {
9488
9489 this.morphNormals[ i ] = {};
9490 this.morphNormals[ i ].faceNormals = [];
9491 this.morphNormals[ i ].vertexNormals = [];
9492
9493 var dstNormalsFace = this.morphNormals[ i ].faceNormals;
9494 var dstNormalsVertex = this.morphNormals[ i ].vertexNormals;
9495
9496 var faceNormal, vertexNormals;
9497
9498 for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
9499
9500 faceNormal = new Vector3();
9501 vertexNormals = { a: new Vector3(), b: new Vector3(), c: new Vector3() };
9502
9503 dstNormalsFace.push( faceNormal );
9504 dstNormalsVertex.push( vertexNormals );
9505
9506 }
9507
9508 }
9509
9510 var morphNormals = this.morphNormals[ i ];
9511
9512 // set vertices to morph target
9513
9514 tmpGeo.vertices = this.morphTargets[ i ].vertices;
9515
9516 // compute morph normals
9517
9518 tmpGeo.computeFaceNormals();
9519 tmpGeo.computeVertexNormals();
9520
9521 // store morph normals
9522
9523 var faceNormal, vertexNormals;
9524
9525 for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
9526
9527 face = this.faces[ f ];
9528
9529 faceNormal = morphNormals.faceNormals[ f ];
9530 vertexNormals = morphNormals.vertexNormals[ f ];
9531
9532 faceNormal.copy( face.normal );
9533
9534 vertexNormals.a.copy( face.vertexNormals[ 0 ] );
9535 vertexNormals.b.copy( face.vertexNormals[ 1 ] );
9536 vertexNormals.c.copy( face.vertexNormals[ 2 ] );
9537
9538 }
9539
9540 }
9541
9542 // restore original normals
9543
9544 for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
9545
9546 face = this.faces[ f ];
9547
9548 face.normal = face.__originalFaceNormal;
9549 face.vertexNormals = face.__originalVertexNormals;
9550
9551 }
9552
9553 },
9554
9555 computeBoundingBox: function () {
9556
9557 if ( this.boundingBox === null ) {
9558
9559 this.boundingBox = new Box3();
9560
9561 }
9562
9563 this.boundingBox.setFromPoints( this.vertices );
9564
9565 },
9566
9567 computeBoundingSphere: function () {
9568
9569 if ( this.boundingSphere === null ) {
9570
9571 this.boundingSphere = new Sphere();
9572
9573 }
9574
9575 this.boundingSphere.setFromPoints( this.vertices );
9576
9577 },
9578
9579 merge: function ( geometry, matrix, materialIndexOffset ) {
9580
9581 if ( ! ( geometry && geometry.isGeometry ) ) {
9582
9583 console.error( 'THREE.Geometry.merge(): geometry not an instance of THREE.Geometry.', geometry );
9584 return;
9585
9586 }
9587
9588 var normalMatrix,
9589 vertexOffset = this.vertices.length,
9590 vertices1 = this.vertices,
9591 vertices2 = geometry.vertices,
9592 faces1 = this.faces,
9593 faces2 = geometry.faces,
9594 uvs1 = this.faceVertexUvs[ 0 ],
9595 uvs2 = geometry.faceVertexUvs[ 0 ],
9596 colors1 = this.colors,
9597 colors2 = geometry.colors;
9598
9599 if ( materialIndexOffset === undefined ) materialIndexOffset = 0;
9600
9601 if ( matrix !== undefined ) {
9602
9603 normalMatrix = new Matrix3().getNormalMatrix( matrix );
9604
9605 }
9606
9607 // vertices
9608
9609 for ( var i = 0, il = vertices2.length; i < il; i ++ ) {
9610
9611 var vertex = vertices2[ i ];
9612
9613 var vertexCopy = vertex.clone();
9614
9615 if ( matrix !== undefined ) vertexCopy.applyMatrix4( matrix );
9616
9617 vertices1.push( vertexCopy );
9618
9619 }
9620
9621 // colors
9622
9623 for ( var i = 0, il = colors2.length; i < il; i ++ ) {
9624
9625 colors1.push( colors2[ i ].clone() );
9626
9627 }
9628
9629 // faces
9630
9631 for ( i = 0, il = faces2.length; i < il; i ++ ) {
9632
9633 var face = faces2[ i ], faceCopy, normal, color,
9634 faceVertexNormals = face.vertexNormals,
9635 faceVertexColors = face.vertexColors;
9636
9637 faceCopy = new Face3( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset );
9638 faceCopy.normal.copy( face.normal );
9639
9640 if ( normalMatrix !== undefined ) {
9641
9642 faceCopy.normal.applyMatrix3( normalMatrix ).normalize();
9643
9644 }
9645
9646 for ( var j = 0, jl = faceVertexNormals.length; j < jl; j ++ ) {
9647
9648 normal = faceVertexNormals[ j ].clone();
9649
9650 if ( normalMatrix !== undefined ) {
9651
9652 normal.applyMatrix3( normalMatrix ).normalize();
9653
9654 }
9655
9656 faceCopy.vertexNormals.push( normal );
9657
9658 }
9659
9660 faceCopy.color.copy( face.color );
9661
9662 for ( var j = 0, jl = faceVertexColors.length; j < jl; j ++ ) {
9663
9664 color = faceVertexColors[ j ];
9665 faceCopy.vertexColors.push( color.clone() );
9666
9667 }
9668
9669 faceCopy.materialIndex = face.materialIndex + materialIndexOffset;
9670
9671 faces1.push( faceCopy );
9672
9673 }
9674
9675 // uvs
9676
9677 for ( i = 0, il = uvs2.length; i < il; i ++ ) {
9678
9679 var uv = uvs2[ i ], uvCopy = [];
9680
9681 if ( uv === undefined ) {
9682
9683 continue;
9684
9685 }
9686
9687 for ( var j = 0, jl = uv.length; j < jl; j ++ ) {
9688
9689 uvCopy.push( uv[ j ].clone() );
9690
9691 }
9692
9693 uvs1.push( uvCopy );
9694
9695 }
9696
9697 },
9698
9699 mergeMesh: function ( mesh ) {
9700
9701 if ( ! ( mesh && mesh.isMesh ) ) {
9702
9703 console.error( 'THREE.Geometry.mergeMesh(): mesh not an instance of THREE.Mesh.', mesh );
9704 return;
9705
9706 }
9707
9708 if ( mesh.matrixAutoUpdate ) mesh.updateMatrix();
9709
9710 this.merge( mesh.geometry, mesh.matrix );
9711
9712 },
9713
9714 /*
9715 * Checks for duplicate vertices with hashmap.
9716 * Duplicated vertices are removed
9717 * and faces' vertices are updated.
9718 */
9719
9720 mergeVertices: function () {
9721
9722 var verticesMap = {}; // Hashmap for looking up vertices by position coordinates (and making sure they are unique)
9723 var unique = [], changes = [];
9724
9725 var v, key;
9726 var precisionPoints = 4; // number of decimal points, e.g. 4 for epsilon of 0.0001
9727 var precision = Math.pow( 10, precisionPoints );
9728 var i, il, face;
9729 var indices, j, jl;
9730
9731 for ( i = 0, il = this.vertices.length; i < il; i ++ ) {
9732
9733 v = this.vertices[ i ];
9734 key = Math.round( v.x * precision ) + '_' + Math.round( v.y * precision ) + '_' + Math.round( v.z * precision );
9735
9736 if ( verticesMap[ key ] === undefined ) {
9737
9738 verticesMap[ key ] = i;
9739 unique.push( this.vertices[ i ] );
9740 changes[ i ] = unique.length - 1;
9741
9742 } else {
9743
9744 //console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]);
9745 changes[ i ] = changes[ verticesMap[ key ] ];
9746
9747 }
9748
9749 }
9750
9751
9752 // if faces are completely degenerate after merging vertices, we
9753 // have to remove them from the geometry.
9754 var faceIndicesToRemove = [];
9755
9756 for ( i = 0, il = this.faces.length; i < il; i ++ ) {
9757
9758 face = this.faces[ i ];
9759
9760 face.a = changes[ face.a ];
9761 face.b = changes[ face.b ];
9762 face.c = changes[ face.c ];
9763
9764 indices = [ face.a, face.b, face.c ];
9765
9766 // if any duplicate vertices are found in a Face3
9767 // we have to remove the face as nothing can be saved
9768 for ( var n = 0; n < 3; n ++ ) {
9769
9770 if ( indices[ n ] === indices[ ( n + 1 ) % 3 ] ) {
9771
9772 faceIndicesToRemove.push( i );
9773 break;
9774
9775 }
9776
9777 }
9778
9779 }
9780
9781 for ( i = faceIndicesToRemove.length - 1; i >= 0; i -- ) {
9782
9783 var idx = faceIndicesToRemove[ i ];
9784
9785 this.faces.splice( idx, 1 );
9786
9787 for ( j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) {
9788
9789 this.faceVertexUvs[ j ].splice( idx, 1 );
9790
9791 }
9792
9793 }
9794
9795 // Use unique set of vertices
9796
9797 var diff = this.vertices.length - unique.length;
9798 this.vertices = unique;
9799 return diff;
9800
9801 },
9802
9803 setFromPoints: function ( points ) {
9804
9805 this.vertices = [];
9806
9807 for ( var i = 0, l = points.length; i < l; i ++ ) {
9808
9809 var point = points[ i ];
9810 this.vertices.push( new Vector3( point.x, point.y, point.z || 0 ) );
9811
9812 }
9813
9814 return this;
9815
9816 },
9817
9818 sortFacesByMaterialIndex: function () {
9819
9820 var faces = this.faces;
9821 var length = faces.length;
9822
9823 // tag faces
9824
9825 for ( var i = 0; i < length; i ++ ) {
9826
9827 faces[ i ]._id = i;
9828
9829 }
9830
9831 // sort faces
9832
9833 function materialIndexSort( a, b ) {
9834
9835 return a.materialIndex - b.materialIndex;
9836
9837 }
9838
9839 faces.sort( materialIndexSort );
9840
9841 // sort uvs
9842
9843 var uvs1 = this.faceVertexUvs[ 0 ];
9844 var uvs2 = this.faceVertexUvs[ 1 ];
9845
9846 var newUvs1, newUvs2;
9847
9848 if ( uvs1 && uvs1.length === length ) newUvs1 = [];
9849 if ( uvs2 && uvs2.length === length ) newUvs2 = [];
9850
9851 for ( var i = 0; i < length; i ++ ) {
9852
9853 var id = faces[ i ]._id;
9854
9855 if ( newUvs1 ) newUvs1.push( uvs1[ id ] );
9856 if ( newUvs2 ) newUvs2.push( uvs2[ id ] );
9857
9858 }
9859
9860 if ( newUvs1 ) this.faceVertexUvs[ 0 ] = newUvs1;
9861 if ( newUvs2 ) this.faceVertexUvs[ 1 ] = newUvs2;
9862
9863 },
9864
9865 toJSON: function () {
9866
9867 var data = {
9868 metadata: {
9869 version: 4.5,
9870 type: 'Geometry',
9871 generator: 'Geometry.toJSON'
9872 }
9873 };
9874
9875 // standard Geometry serialization
9876
9877 data.uuid = this.uuid;
9878 data.type = this.type;
9879 if ( this.name !== '' ) data.name = this.name;
9880
9881 if ( this.parameters !== undefined ) {
9882
9883 var parameters = this.parameters;
9884
9885 for ( var key in parameters ) {
9886
9887 if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ];
9888
9889 }
9890
9891 return data;
9892
9893 }
9894
9895 var vertices = [];
9896
9897 for ( var i = 0; i < this.vertices.length; i ++ ) {
9898
9899 var vertex = this.vertices[ i ];
9900 vertices.push( vertex.x, vertex.y, vertex.z );
9901
9902 }
9903
9904 var faces = [];
9905 var normals = [];
9906 var normalsHash = {};
9907 var colors = [];
9908 var colorsHash = {};
9909 var uvs = [];
9910 var uvsHash = {};
9911
9912 for ( var i = 0; i < this.faces.length; i ++ ) {
9913
9914 var face = this.faces[ i ];
9915
9916 var hasMaterial = true;
9917 var hasFaceUv = false; // deprecated
9918 var hasFaceVertexUv = this.faceVertexUvs[ 0 ][ i ] !== undefined;
9919 var hasFaceNormal = face.normal.length() > 0;
9920 var hasFaceVertexNormal = face.vertexNormals.length > 0;
9921 var hasFaceColor = face.color.r !== 1 || face.color.g !== 1 || face.color.b !== 1;
9922 var hasFaceVertexColor = face.vertexColors.length > 0;
9923
9924 var faceType = 0;
9925
9926 faceType = setBit( faceType, 0, 0 ); // isQuad
9927 faceType = setBit( faceType, 1, hasMaterial );
9928 faceType = setBit( faceType, 2, hasFaceUv );
9929 faceType = setBit( faceType, 3, hasFaceVertexUv );
9930 faceType = setBit( faceType, 4, hasFaceNormal );
9931 faceType = setBit( faceType, 5, hasFaceVertexNormal );
9932 faceType = setBit( faceType, 6, hasFaceColor );
9933 faceType = setBit( faceType, 7, hasFaceVertexColor );
9934
9935 faces.push( faceType );
9936 faces.push( face.a, face.b, face.c );
9937 faces.push( face.materialIndex );
9938
9939 if ( hasFaceVertexUv ) {
9940
9941 var faceVertexUvs = this.faceVertexUvs[ 0 ][ i ];
9942
9943 faces.push(
9944 getUvIndex( faceVertexUvs[ 0 ] ),
9945 getUvIndex( faceVertexUvs[ 1 ] ),
9946 getUvIndex( faceVertexUvs[ 2 ] )
9947 );
9948
9949 }
9950
9951 if ( hasFaceNormal ) {
9952
9953 faces.push( getNormalIndex( face.normal ) );
9954
9955 }
9956
9957 if ( hasFaceVertexNormal ) {
9958
9959 var vertexNormals = face.vertexNormals;
9960
9961 faces.push(
9962 getNormalIndex( vertexNormals[ 0 ] ),
9963 getNormalIndex( vertexNormals[ 1 ] ),
9964 getNormalIndex( vertexNormals[ 2 ] )
9965 );
9966
9967 }
9968
9969 if ( hasFaceColor ) {
9970
9971 faces.push( getColorIndex( face.color ) );
9972
9973 }
9974
9975 if ( hasFaceVertexColor ) {
9976
9977 var vertexColors = face.vertexColors;
9978
9979 faces.push(
9980 getColorIndex( vertexColors[ 0 ] ),
9981 getColorIndex( vertexColors[ 1 ] ),
9982 getColorIndex( vertexColors[ 2 ] )
9983 );
9984
9985 }
9986
9987 }
9988
9989 function setBit( value, position, enabled ) {
9990
9991 return enabled ? value | ( 1 << position ) : value & ( ~ ( 1 << position ) );
9992
9993 }
9994
9995 function getNormalIndex( normal ) {
9996
9997 var hash = normal.x.toString() + normal.y.toString() + normal.z.toString();
9998
9999 if ( normalsHash[ hash ] !== undefined ) {
10000
10001 return normalsHash[ hash ];
10002
10003 }
10004
10005 normalsHash[ hash ] = normals.length / 3;
10006 normals.push( normal.x, normal.y, normal.z );
10007
10008 return normalsHash[ hash ];
10009
10010 }
10011
10012 function getColorIndex( color ) {
10013
10014 var hash = color.r.toString() + color.g.toString() + color.b.toString();
10015
10016 if ( colorsHash[ hash ] !== undefined ) {
10017
10018 return colorsHash[ hash ];
10019
10020 }
10021
10022 colorsHash[ hash ] = colors.length;
10023 colors.push( color.getHex() );
10024
10025 return colorsHash[ hash ];
10026
10027 }
10028
10029 function getUvIndex( uv ) {
10030
10031 var hash = uv.x.toString() + uv.y.toString();
10032
10033 if ( uvsHash[ hash ] !== undefined ) {
10034
10035 return uvsHash[ hash ];
10036
10037 }
10038
10039 uvsHash[ hash ] = uvs.length / 2;
10040 uvs.push( uv.x, uv.y );
10041
10042 return uvsHash[ hash ];
10043
10044 }
10045
10046 data.data = {};
10047
10048 data.data.vertices = vertices;
10049 data.data.normals = normals;
10050 if ( colors.length > 0 ) data.data.colors = colors;
10051 if ( uvs.length > 0 ) data.data.uvs = [ uvs ]; // temporal backward compatibility
10052 data.data.faces = faces;
10053
10054 return data;
10055
10056 },
10057
10058 clone: function () {
10059
10060 /*
10061 // Handle primitives
10062
10063 var parameters = this.parameters;
10064
10065 if ( parameters !== undefined ) {
10066
10067 var values = [];
10068
10069 for ( var key in parameters ) {
10070
10071 values.push( parameters[ key ] );
10072
10073 }
10074
10075 var geometry = Object.create( this.constructor.prototype );
10076 this.constructor.apply( geometry, values );
10077 return geometry;
10078
10079 }
10080
10081 return new this.constructor().copy( this );
10082 */
10083
10084 return new Geometry().copy( this );
10085
10086 },
10087
10088 copy: function ( source ) {
10089
10090 var i, il, j, jl, k, kl;
10091
10092 // reset
10093
10094 this.vertices = [];
10095 this.colors = [];
10096 this.faces = [];
10097 this.faceVertexUvs = [[]];
10098 this.morphTargets = [];
10099 this.morphNormals = [];
10100 this.skinWeights = [];
10101 this.skinIndices = [];
10102 this.lineDistances = [];
10103 this.boundingBox = null;
10104 this.boundingSphere = null;
10105
10106 // name
10107
10108 this.name = source.name;
10109
10110 // vertices
10111
10112 var vertices = source.vertices;
10113
10114 for ( i = 0, il = vertices.length; i < il; i ++ ) {
10115
10116 this.vertices.push( vertices[ i ].clone() );
10117
10118 }
10119
10120 // colors
10121
10122 var colors = source.colors;
10123
10124 for ( i = 0, il = colors.length; i < il; i ++ ) {
10125
10126 this.colors.push( colors[ i ].clone() );
10127
10128 }
10129
10130 // faces
10131
10132 var faces = source.faces;
10133
10134 for ( i = 0, il = faces.length; i < il; i ++ ) {
10135
10136 this.faces.push( faces[ i ].clone() );
10137
10138 }
10139
10140 // face vertex uvs
10141
10142 for ( i = 0, il = source.faceVertexUvs.length; i < il; i ++ ) {
10143
10144 var faceVertexUvs = source.faceVertexUvs[ i ];
10145
10146 if ( this.faceVertexUvs[ i ] === undefined ) {
10147
10148 this.faceVertexUvs[ i ] = [];
10149
10150 }
10151
10152 for ( j = 0, jl = faceVertexUvs.length; j < jl; j ++ ) {
10153
10154 var uvs = faceVertexUvs[ j ], uvsCopy = [];
10155
10156 for ( k = 0, kl = uvs.length; k < kl; k ++ ) {
10157
10158 var uv = uvs[ k ];
10159
10160 uvsCopy.push( uv.clone() );
10161
10162 }
10163
10164 this.faceVertexUvs[ i ].push( uvsCopy );
10165
10166 }
10167
10168 }
10169
10170 // morph targets
10171
10172 var morphTargets = source.morphTargets;
10173
10174 for ( i = 0, il = morphTargets.length; i < il; i ++ ) {
10175
10176 var morphTarget = {};
10177 morphTarget.name = morphTargets[ i ].name;
10178
10179 // vertices
10180
10181 if ( morphTargets[ i ].vertices !== undefined ) {
10182
10183 morphTarget.vertices = [];
10184
10185 for ( j = 0, jl = morphTargets[ i ].vertices.length; j < jl; j ++ ) {
10186
10187 morphTarget.vertices.push( morphTargets[ i ].vertices[ j ].clone() );
10188
10189 }
10190
10191 }
10192
10193 // normals
10194
10195 if ( morphTargets[ i ].normals !== undefined ) {
10196
10197 morphTarget.normals = [];
10198
10199 for ( j = 0, jl = morphTargets[ i ].normals.length; j < jl; j ++ ) {
10200
10201 morphTarget.normals.push( morphTargets[ i ].normals[ j ].clone() );
10202
10203 }
10204
10205 }
10206
10207 this.morphTargets.push( morphTarget );
10208
10209 }
10210
10211 // morph normals
10212
10213 var morphNormals = source.morphNormals;
10214
10215 for ( i = 0, il = morphNormals.length; i < il; i ++ ) {
10216
10217 var morphNormal = {};
10218
10219 // vertex normals
10220
10221 if ( morphNormals[ i ].vertexNormals !== undefined ) {
10222
10223 morphNormal.vertexNormals = [];
10224
10225 for ( j = 0, jl = morphNormals[ i ].vertexNormals.length; j < jl; j ++ ) {
10226
10227 var srcVertexNormal = morphNormals[ i ].vertexNormals[ j ];
10228 var destVertexNormal = {};
10229
10230 destVertexNormal.a = srcVertexNormal.a.clone();
10231 destVertexNormal.b = srcVertexNormal.b.clone();
10232 destVertexNormal.c = srcVertexNormal.c.clone();
10233
10234 morphNormal.vertexNormals.push( destVertexNormal );
10235
10236 }
10237
10238 }
10239
10240 // face normals
10241
10242 if ( morphNormals[ i ].faceNormals !== undefined ) {
10243
10244 morphNormal.faceNormals = [];
10245
10246 for ( j = 0, jl = morphNormals[ i ].faceNormals.length; j < jl; j ++ ) {
10247
10248 morphNormal.faceNormals.push( morphNormals[ i ].faceNormals[ j ].clone() );
10249
10250 }
10251
10252 }
10253
10254 this.morphNormals.push( morphNormal );
10255
10256 }
10257
10258 // skin weights
10259
10260 var skinWeights = source.skinWeights;
10261
10262 for ( i = 0, il = skinWeights.length; i < il; i ++ ) {
10263
10264 this.skinWeights.push( skinWeights[ i ].clone() );
10265
10266 }
10267
10268 // skin indices
10269
10270 var skinIndices = source.skinIndices;
10271
10272 for ( i = 0, il = skinIndices.length; i < il; i ++ ) {
10273
10274 this.skinIndices.push( skinIndices[ i ].clone() );
10275
10276 }
10277
10278 // line distances
10279
10280 var lineDistances = source.lineDistances;
10281
10282 for ( i = 0, il = lineDistances.length; i < il; i ++ ) {
10283
10284 this.lineDistances.push( lineDistances[ i ] );
10285
10286 }
10287
10288 // bounding box
10289
10290 var boundingBox = source.boundingBox;
10291
10292 if ( boundingBox !== null ) {
10293
10294 this.boundingBox = boundingBox.clone();
10295
10296 }
10297
10298 // bounding sphere
10299
10300 var boundingSphere = source.boundingSphere;
10301
10302 if ( boundingSphere !== null ) {
10303
10304 this.boundingSphere = boundingSphere.clone();
10305
10306 }
10307
10308 // update flags
10309
10310 this.elementsNeedUpdate = source.elementsNeedUpdate;
10311 this.verticesNeedUpdate = source.verticesNeedUpdate;
10312 this.uvsNeedUpdate = source.uvsNeedUpdate;
10313 this.normalsNeedUpdate = source.normalsNeedUpdate;
10314 this.colorsNeedUpdate = source.colorsNeedUpdate;
10315 this.lineDistancesNeedUpdate = source.lineDistancesNeedUpdate;
10316 this.groupsNeedUpdate = source.groupsNeedUpdate;
10317
10318 return this;
10319
10320 },
10321
10322 dispose: function () {
10323
10324 this.dispatchEvent( { type: 'dispose' } );
10325
10326 }
10327
10328 } );
10329
10330 /**
10331 * @author mrdoob / http://mrdoob.com/
10332 */
10333
10334 function BufferAttribute( array, itemSize, normalized ) {
10335
10336 if ( Array.isArray( array ) ) {
10337
10338 throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' );
10339
10340 }
10341
10342 this.name = '';
10343
10344 this.array = array;
10345 this.itemSize = itemSize;
10346 this.count = array !== undefined ? array.length / itemSize : 0;
10347 this.normalized = normalized === true;
10348
10349 this.dynamic = false;
10350 this.updateRange = { offset: 0, count: - 1 };
10351
10352 this.version = 0;
10353
10354 }
10355
10356 Object.defineProperty( BufferAttribute.prototype, 'needsUpdate', {
10357
10358 set: function ( value ) {
10359
10360 if ( value === true ) this.version ++;
10361
10362 }
10363
10364 } );
10365
10366 Object.assign( BufferAttribute.prototype, {
10367
10368 isBufferAttribute: true,
10369
10370 onUploadCallback: function () {},
10371
10372 setArray: function ( array ) {
10373
10374 if ( Array.isArray( array ) ) {
10375
10376 throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' );
10377
10378 }
10379
10380 this.count = array !== undefined ? array.length / this.itemSize : 0;
10381 this.array = array;
10382
10383 return this;
10384
10385 },
10386
10387 setDynamic: function ( value ) {
10388
10389 this.dynamic = value;
10390
10391 return this;
10392
10393 },
10394
10395 copy: function ( source ) {
10396
10397 this.name = source.name;
10398 this.array = new source.array.constructor( source.array );
10399 this.itemSize = source.itemSize;
10400 this.count = source.count;
10401 this.normalized = source.normalized;
10402
10403 this.dynamic = source.dynamic;
10404
10405 return this;
10406
10407 },
10408
10409 copyAt: function ( index1, attribute, index2 ) {
10410
10411 index1 *= this.itemSize;
10412 index2 *= attribute.itemSize;
10413
10414 for ( var i = 0, l = this.itemSize; i < l; i ++ ) {
10415
10416 this.array[ index1 + i ] = attribute.array[ index2 + i ];
10417
10418 }
10419
10420 return this;
10421
10422 },
10423
10424 copyArray: function ( array ) {
10425
10426 this.array.set( array );
10427
10428 return this;
10429
10430 },
10431
10432 copyColorsArray: function ( colors ) {
10433
10434 var array = this.array, offset = 0;
10435
10436 for ( var i = 0, l = colors.length; i < l; i ++ ) {
10437
10438 var color = colors[ i ];
10439
10440 if ( color === undefined ) {
10441
10442 console.warn( 'THREE.BufferAttribute.copyColorsArray(): color is undefined', i );
10443 color = new Color();
10444
10445 }
10446
10447 array[ offset ++ ] = color.r;
10448 array[ offset ++ ] = color.g;
10449 array[ offset ++ ] = color.b;
10450
10451 }
10452
10453 return this;
10454
10455 },
10456
10457 copyVector2sArray: function ( vectors ) {
10458
10459 var array = this.array, offset = 0;
10460
10461 for ( var i = 0, l = vectors.length; i < l; i ++ ) {
10462
10463 var vector = vectors[ i ];
10464
10465 if ( vector === undefined ) {
10466
10467 console.warn( 'THREE.BufferAttribute.copyVector2sArray(): vector is undefined', i );
10468 vector = new Vector2();
10469
10470 }
10471
10472 array[ offset ++ ] = vector.x;
10473 array[ offset ++ ] = vector.y;
10474
10475 }
10476
10477 return this;
10478
10479 },
10480
10481 copyVector3sArray: function ( vectors ) {
10482
10483 var array = this.array, offset = 0;
10484
10485 for ( var i = 0, l = vectors.length; i < l; i ++ ) {
10486
10487 var vector = vectors[ i ];
10488
10489 if ( vector === undefined ) {
10490
10491 console.warn( 'THREE.BufferAttribute.copyVector3sArray(): vector is undefined', i );
10492 vector = new Vector3();
10493
10494 }
10495
10496 array[ offset ++ ] = vector.x;
10497 array[ offset ++ ] = vector.y;
10498 array[ offset ++ ] = vector.z;
10499
10500 }
10501
10502 return this;
10503
10504 },
10505
10506 copyVector4sArray: function ( vectors ) {
10507
10508 var array = this.array, offset = 0;
10509
10510 for ( var i = 0, l = vectors.length; i < l; i ++ ) {
10511
10512 var vector = vectors[ i ];
10513
10514 if ( vector === undefined ) {
10515
10516 console.warn( 'THREE.BufferAttribute.copyVector4sArray(): vector is undefined', i );
10517 vector = new Vector4();
10518
10519 }
10520
10521 array[ offset ++ ] = vector.x;
10522 array[ offset ++ ] = vector.y;
10523 array[ offset ++ ] = vector.z;
10524 array[ offset ++ ] = vector.w;
10525
10526 }
10527
10528 return this;
10529
10530 },
10531
10532 set: function ( value, offset ) {
10533
10534 if ( offset === undefined ) offset = 0;
10535
10536 this.array.set( value, offset );
10537
10538 return this;
10539
10540 },
10541
10542 getX: function ( index ) {
10543
10544 return this.array[ index * this.itemSize ];
10545
10546 },
10547
10548 setX: function ( index, x ) {
10549
10550 this.array[ index * this.itemSize ] = x;
10551
10552 return this;
10553
10554 },
10555
10556 getY: function ( index ) {
10557
10558 return this.array[ index * this.itemSize + 1 ];
10559
10560 },
10561
10562 setY: function ( index, y ) {
10563
10564 this.array[ index * this.itemSize + 1 ] = y;
10565
10566 return this;
10567
10568 },
10569
10570 getZ: function ( index ) {
10571
10572 return this.array[ index * this.itemSize + 2 ];
10573
10574 },
10575
10576 setZ: function ( index, z ) {
10577
10578 this.array[ index * this.itemSize + 2 ] = z;
10579
10580 return this;
10581
10582 },
10583
10584 getW: function ( index ) {
10585
10586 return this.array[ index * this.itemSize + 3 ];
10587
10588 },
10589
10590 setW: function ( index, w ) {
10591
10592 this.array[ index * this.itemSize + 3 ] = w;
10593
10594 return this;
10595
10596 },
10597
10598 setXY: function ( index, x, y ) {
10599
10600 index *= this.itemSize;
10601
10602 this.array[ index + 0 ] = x;
10603 this.array[ index + 1 ] = y;
10604
10605 return this;
10606
10607 },
10608
10609 setXYZ: function ( index, x, y, z ) {
10610
10611 index *= this.itemSize;
10612
10613 this.array[ index + 0 ] = x;
10614 this.array[ index + 1 ] = y;
10615 this.array[ index + 2 ] = z;
10616
10617 return this;
10618
10619 },
10620
10621 setXYZW: function ( index, x, y, z, w ) {
10622
10623 index *= this.itemSize;
10624
10625 this.array[ index + 0 ] = x;
10626 this.array[ index + 1 ] = y;
10627 this.array[ index + 2 ] = z;
10628 this.array[ index + 3 ] = w;
10629
10630 return this;
10631
10632 },
10633
10634 onUpload: function ( callback ) {
10635
10636 this.onUploadCallback = callback;
10637
10638 return this;
10639
10640 },
10641
10642 clone: function () {
10643
10644 return new this.constructor( this.array, this.itemSize ).copy( this );
10645
10646 }
10647
10648 } );
10649
10650 //
10651
10652 function Int8BufferAttribute( array, itemSize, normalized ) {
10653
10654 BufferAttribute.call( this, new Int8Array( array ), itemSize, normalized );
10655
10656 }
10657
10658 Int8BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
10659 Int8BufferAttribute.prototype.constructor = Int8BufferAttribute;
10660
10661
10662 function Uint8BufferAttribute( array, itemSize, normalized ) {
10663
10664 BufferAttribute.call( this, new Uint8Array( array ), itemSize, normalized );
10665
10666 }
10667
10668 Uint8BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
10669 Uint8BufferAttribute.prototype.constructor = Uint8BufferAttribute;
10670
10671
10672 function Uint8ClampedBufferAttribute( array, itemSize, normalized ) {
10673
10674 BufferAttribute.call( this, new Uint8ClampedArray( array ), itemSize, normalized );
10675
10676 }
10677
10678 Uint8ClampedBufferAttribute.prototype = Object.create( BufferAttribute.prototype );
10679 Uint8ClampedBufferAttribute.prototype.constructor = Uint8ClampedBufferAttribute;
10680
10681
10682 function Int16BufferAttribute( array, itemSize, normalized ) {
10683
10684 BufferAttribute.call( this, new Int16Array( array ), itemSize, normalized );
10685
10686 }
10687
10688 Int16BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
10689 Int16BufferAttribute.prototype.constructor = Int16BufferAttribute;
10690
10691
10692 function Uint16BufferAttribute( array, itemSize, normalized ) {
10693
10694 BufferAttribute.call( this, new Uint16Array( array ), itemSize, normalized );
10695
10696 }
10697
10698 Uint16BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
10699 Uint16BufferAttribute.prototype.constructor = Uint16BufferAttribute;
10700
10701
10702 function Int32BufferAttribute( array, itemSize, normalized ) {
10703
10704 BufferAttribute.call( this, new Int32Array( array ), itemSize, normalized );
10705
10706 }
10707
10708 Int32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
10709 Int32BufferAttribute.prototype.constructor = Int32BufferAttribute;
10710
10711
10712 function Uint32BufferAttribute( array, itemSize, normalized ) {
10713
10714 BufferAttribute.call( this, new Uint32Array( array ), itemSize, normalized );
10715
10716 }
10717
10718 Uint32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
10719 Uint32BufferAttribute.prototype.constructor = Uint32BufferAttribute;
10720
10721
10722 function Float32BufferAttribute( array, itemSize, normalized ) {
10723
10724 BufferAttribute.call( this, new Float32Array( array ), itemSize, normalized );
10725
10726 }
10727
10728 Float32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
10729 Float32BufferAttribute.prototype.constructor = Float32BufferAttribute;
10730
10731
10732 function Float64BufferAttribute( array, itemSize, normalized ) {
10733
10734 BufferAttribute.call( this, new Float64Array( array ), itemSize, normalized );
10735
10736 }
10737
10738 Float64BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
10739 Float64BufferAttribute.prototype.constructor = Float64BufferAttribute;
10740
10741 /**
10742 * @author mrdoob / http://mrdoob.com/
10743 */
10744
10745 function DirectGeometry() {
10746
10747 this.vertices = [];
10748 this.normals = [];
10749 this.colors = [];
10750 this.uvs = [];
10751 this.uvs2 = [];
10752
10753 this.groups = [];
10754
10755 this.morphTargets = {};
10756
10757 this.skinWeights = [];
10758 this.skinIndices = [];
10759
10760 // this.lineDistances = [];
10761
10762 this.boundingBox = null;
10763 this.boundingSphere = null;
10764
10765 // update flags
10766
10767 this.verticesNeedUpdate = false;
10768 this.normalsNeedUpdate = false;
10769 this.colorsNeedUpdate = false;
10770 this.uvsNeedUpdate = false;
10771 this.groupsNeedUpdate = false;
10772
10773 }
10774
10775 Object.assign( DirectGeometry.prototype, {
10776
10777 computeGroups: function ( geometry ) {
10778
10779 var group;
10780 var groups = [];
10781 var materialIndex = undefined;
10782
10783 var faces = geometry.faces;
10784
10785 for ( var i = 0; i < faces.length; i ++ ) {
10786
10787 var face = faces[ i ];
10788
10789 // materials
10790
10791 if ( face.materialIndex !== materialIndex ) {
10792
10793 materialIndex = face.materialIndex;
10794
10795 if ( group !== undefined ) {
10796
10797 group.count = ( i * 3 ) - group.start;
10798 groups.push( group );
10799
10800 }
10801
10802 group = {
10803 start: i * 3,
10804 materialIndex: materialIndex
10805 };
10806
10807 }
10808
10809 }
10810
10811 if ( group !== undefined ) {
10812
10813 group.count = ( i * 3 ) - group.start;
10814 groups.push( group );
10815
10816 }
10817
10818 this.groups = groups;
10819
10820 },
10821
10822 fromGeometry: function ( geometry ) {
10823
10824 var faces = geometry.faces;
10825 var vertices = geometry.vertices;
10826 var faceVertexUvs = geometry.faceVertexUvs;
10827
10828 var hasFaceVertexUv = faceVertexUvs[ 0 ] && faceVertexUvs[ 0 ].length > 0;
10829 var hasFaceVertexUv2 = faceVertexUvs[ 1 ] && faceVertexUvs[ 1 ].length > 0;
10830
10831 // morphs
10832
10833 var morphTargets = geometry.morphTargets;
10834 var morphTargetsLength = morphTargets.length;
10835
10836 var morphTargetsPosition;
10837
10838 if ( morphTargetsLength > 0 ) {
10839
10840 morphTargetsPosition = [];
10841
10842 for ( var i = 0; i < morphTargetsLength; i ++ ) {
10843
10844 morphTargetsPosition[ i ] = [];
10845
10846 }
10847
10848 this.morphTargets.position = morphTargetsPosition;
10849
10850 }
10851
10852 var morphNormals = geometry.morphNormals;
10853 var morphNormalsLength = morphNormals.length;
10854
10855 var morphTargetsNormal;
10856
10857 if ( morphNormalsLength > 0 ) {
10858
10859 morphTargetsNormal = [];
10860
10861 for ( var i = 0; i < morphNormalsLength; i ++ ) {
10862
10863 morphTargetsNormal[ i ] = [];
10864
10865 }
10866
10867 this.morphTargets.normal = morphTargetsNormal;
10868
10869 }
10870
10871 // skins
10872
10873 var skinIndices = geometry.skinIndices;
10874 var skinWeights = geometry.skinWeights;
10875
10876 var hasSkinIndices = skinIndices.length === vertices.length;
10877 var hasSkinWeights = skinWeights.length === vertices.length;
10878
10879 //
10880
10881 for ( var i = 0; i < faces.length; i ++ ) {
10882
10883 var face = faces[ i ];
10884
10885 this.vertices.push( vertices[ face.a ], vertices[ face.b ], vertices[ face.c ] );
10886
10887 var vertexNormals = face.vertexNormals;
10888
10889 if ( vertexNormals.length === 3 ) {
10890
10891 this.normals.push( vertexNormals[ 0 ], vertexNormals[ 1 ], vertexNormals[ 2 ] );
10892
10893 } else {
10894
10895 var normal = face.normal;
10896
10897 this.normals.push( normal, normal, normal );
10898
10899 }
10900
10901 var vertexColors = face.vertexColors;
10902
10903 if ( vertexColors.length === 3 ) {
10904
10905 this.colors.push( vertexColors[ 0 ], vertexColors[ 1 ], vertexColors[ 2 ] );
10906
10907 } else {
10908
10909 var color = face.color;
10910
10911 this.colors.push( color, color, color );
10912
10913 }
10914
10915 if ( hasFaceVertexUv === true ) {
10916
10917 var vertexUvs = faceVertexUvs[ 0 ][ i ];
10918
10919 if ( vertexUvs !== undefined ) {
10920
10921 this.uvs.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] );
10922
10923 } else {
10924
10925 console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv ', i );
10926
10927 this.uvs.push( new Vector2(), new Vector2(), new Vector2() );
10928
10929 }
10930
10931 }
10932
10933 if ( hasFaceVertexUv2 === true ) {
10934
10935 var vertexUvs = faceVertexUvs[ 1 ][ i ];
10936
10937 if ( vertexUvs !== undefined ) {
10938
10939 this.uvs2.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] );
10940
10941 } else {
10942
10943 console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv2 ', i );
10944
10945 this.uvs2.push( new Vector2(), new Vector2(), new Vector2() );
10946
10947 }
10948
10949 }
10950
10951 // morphs
10952
10953 for ( var j = 0; j < morphTargetsLength; j ++ ) {
10954
10955 var morphTarget = morphTargets[ j ].vertices;
10956
10957 morphTargetsPosition[ j ].push( morphTarget[ face.a ], morphTarget[ face.b ], morphTarget[ face.c ] );
10958
10959 }
10960
10961 for ( var j = 0; j < morphNormalsLength; j ++ ) {
10962
10963 var morphNormal = morphNormals[ j ].vertexNormals[ i ];
10964
10965 morphTargetsNormal[ j ].push( morphNormal.a, morphNormal.b, morphNormal.c );
10966
10967 }
10968
10969 // skins
10970
10971 if ( hasSkinIndices ) {
10972
10973 this.skinIndices.push( skinIndices[ face.a ], skinIndices[ face.b ], skinIndices[ face.c ] );
10974
10975 }
10976
10977 if ( hasSkinWeights ) {
10978
10979 this.skinWeights.push( skinWeights[ face.a ], skinWeights[ face.b ], skinWeights[ face.c ] );
10980
10981 }
10982
10983 }
10984
10985 this.computeGroups( geometry );
10986
10987 this.verticesNeedUpdate = geometry.verticesNeedUpdate;
10988 this.normalsNeedUpdate = geometry.normalsNeedUpdate;
10989 this.colorsNeedUpdate = geometry.colorsNeedUpdate;
10990 this.uvsNeedUpdate = geometry.uvsNeedUpdate;
10991 this.groupsNeedUpdate = geometry.groupsNeedUpdate;
10992
10993 return this;
10994
10995 }
10996
10997 } );
10998
10999 /**
11000 * @author mrdoob / http://mrdoob.com/
11001 */
11002
11003 function arrayMax( array ) {
11004
11005 if ( array.length === 0 ) return - Infinity;
11006
11007 var max = array[ 0 ];
11008
11009 for ( var i = 1, l = array.length; i < l; ++ i ) {
11010
11011 if ( array[ i ] > max ) max = array[ i ];
11012
11013 }
11014
11015 return max;
11016
11017 }
11018
11019 /**
11020 * @author alteredq / http://alteredqualia.com/
11021 * @author mrdoob / http://mrdoob.com/
11022 */
11023
11024 var bufferGeometryId = 1; // BufferGeometry uses odd numbers as Id
11025
11026 function BufferGeometry() {
11027
11028 Object.defineProperty( this, 'id', { value: bufferGeometryId += 2 } );
11029
11030 this.uuid = _Math.generateUUID();
11031
11032 this.name = '';
11033 this.type = 'BufferGeometry';
11034
11035 this.index = null;
11036 this.attributes = {};
11037
11038 this.morphAttributes = {};
11039
11040 this.groups = [];
11041
11042 this.boundingBox = null;
11043 this.boundingSphere = null;
11044
11045 this.drawRange = { start: 0, count: Infinity };
11046
11047 }
11048
11049 BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
11050
11051 constructor: BufferGeometry,
11052
11053 isBufferGeometry: true,
11054
11055 getIndex: function () {
11056
11057 return this.index;
11058
11059 },
11060
11061 setIndex: function ( index ) {
11062
11063 if ( Array.isArray( index ) ) {
11064
11065 this.index = new ( arrayMax( index ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 );
11066
11067 } else {
11068
11069 this.index = index;
11070
11071 }
11072
11073 },
11074
11075 addAttribute: function ( name, attribute ) {
11076
11077 if ( ! ( attribute && attribute.isBufferAttribute ) && ! ( attribute && attribute.isInterleavedBufferAttribute ) ) {
11078
11079 console.warn( 'THREE.BufferGeometry: .addAttribute() now expects ( name, attribute ).' );
11080
11081 this.addAttribute( name, new BufferAttribute( arguments[ 1 ], arguments[ 2 ] ) );
11082
11083 return;
11084
11085 }
11086
11087 if ( name === 'index' ) {
11088
11089 console.warn( 'THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute.' );
11090 this.setIndex( attribute );
11091
11092 return;
11093
11094 }
11095
11096 this.attributes[ name ] = attribute;
11097
11098 return this;
11099
11100 },
11101
11102 getAttribute: function ( name ) {
11103
11104 return this.attributes[ name ];
11105
11106 },
11107
11108 removeAttribute: function ( name ) {
11109
11110 delete this.attributes[ name ];
11111
11112 return this;
11113
11114 },
11115
11116 addGroup: function ( start, count, materialIndex ) {
11117
11118 this.groups.push( {
11119
11120 start: start,
11121 count: count,
11122 materialIndex: materialIndex !== undefined ? materialIndex : 0
11123
11124 } );
11125
11126 },
11127
11128 clearGroups: function () {
11129
11130 this.groups = [];
11131
11132 },
11133
11134 setDrawRange: function ( start, count ) {
11135
11136 this.drawRange.start = start;
11137 this.drawRange.count = count;
11138
11139 },
11140
11141 applyMatrix: function ( matrix ) {
11142
11143 var position = this.attributes.position;
11144
11145 if ( position !== undefined ) {
11146
11147 matrix.applyToBufferAttribute( position );
11148 position.needsUpdate = true;
11149
11150 }
11151
11152 var normal = this.attributes.normal;
11153
11154 if ( normal !== undefined ) {
11155
11156 var normalMatrix = new Matrix3().getNormalMatrix( matrix );
11157
11158 normalMatrix.applyToBufferAttribute( normal );
11159 normal.needsUpdate = true;
11160
11161 }
11162
11163 if ( this.boundingBox !== null ) {
11164
11165 this.computeBoundingBox();
11166
11167 }
11168
11169 if ( this.boundingSphere !== null ) {
11170
11171 this.computeBoundingSphere();
11172
11173 }
11174
11175 return this;
11176
11177 },
11178
11179 rotateX: function () {
11180
11181 // rotate geometry around world x-axis
11182
11183 var m1 = new Matrix4();
11184
11185 return function rotateX( angle ) {
11186
11187 m1.makeRotationX( angle );
11188
11189 this.applyMatrix( m1 );
11190
11191 return this;
11192
11193 };
11194
11195 }(),
11196
11197 rotateY: function () {
11198
11199 // rotate geometry around world y-axis
11200
11201 var m1 = new Matrix4();
11202
11203 return function rotateY( angle ) {
11204
11205 m1.makeRotationY( angle );
11206
11207 this.applyMatrix( m1 );
11208
11209 return this;
11210
11211 };
11212
11213 }(),
11214
11215 rotateZ: function () {
11216
11217 // rotate geometry around world z-axis
11218
11219 var m1 = new Matrix4();
11220
11221 return function rotateZ( angle ) {
11222
11223 m1.makeRotationZ( angle );
11224
11225 this.applyMatrix( m1 );
11226
11227 return this;
11228
11229 };
11230
11231 }(),
11232
11233 translate: function () {
11234
11235 // translate geometry
11236
11237 var m1 = new Matrix4();
11238
11239 return function translate( x, y, z ) {
11240
11241 m1.makeTranslation( x, y, z );
11242
11243 this.applyMatrix( m1 );
11244
11245 return this;
11246
11247 };
11248
11249 }(),
11250
11251 scale: function () {
11252
11253 // scale geometry
11254
11255 var m1 = new Matrix4();
11256
11257 return function scale( x, y, z ) {
11258
11259 m1.makeScale( x, y, z );
11260
11261 this.applyMatrix( m1 );
11262
11263 return this;
11264
11265 };
11266
11267 }(),
11268
11269 lookAt: function () {
11270
11271 var obj = new Object3D();
11272
11273 return function lookAt( vector ) {
11274
11275 obj.lookAt( vector );
11276
11277 obj.updateMatrix();
11278
11279 this.applyMatrix( obj.matrix );
11280
11281 };
11282
11283 }(),
11284
11285 center: function () {
11286
11287 var offset = new Vector3();
11288
11289 return function center() {
11290
11291 this.computeBoundingBox();
11292
11293 this.boundingBox.getCenter( offset ).negate();
11294
11295 this.translate( offset.x, offset.y, offset.z );
11296
11297 return this;
11298
11299 };
11300
11301 }(),
11302
11303 setFromObject: function ( object ) {
11304
11305 // console.log( 'THREE.BufferGeometry.setFromObject(). Converting', object, this );
11306
11307 var geometry = object.geometry;
11308
11309 if ( object.isPoints || object.isLine ) {
11310
11311 var positions = new Float32BufferAttribute( geometry.vertices.length * 3, 3 );
11312 var colors = new Float32BufferAttribute( geometry.colors.length * 3, 3 );
11313
11314 this.addAttribute( 'position', positions.copyVector3sArray( geometry.vertices ) );
11315 this.addAttribute( 'color', colors.copyColorsArray( geometry.colors ) );
11316
11317 if ( geometry.lineDistances && geometry.lineDistances.length === geometry.vertices.length ) {
11318
11319 var lineDistances = new Float32BufferAttribute( geometry.lineDistances.length, 1 );
11320
11321 this.addAttribute( 'lineDistance', lineDistances.copyArray( geometry.lineDistances ) );
11322
11323 }
11324
11325 if ( geometry.boundingSphere !== null ) {
11326
11327 this.boundingSphere = geometry.boundingSphere.clone();
11328
11329 }
11330
11331 if ( geometry.boundingBox !== null ) {
11332
11333 this.boundingBox = geometry.boundingBox.clone();
11334
11335 }
11336
11337 } else if ( object.isMesh ) {
11338
11339 if ( geometry && geometry.isGeometry ) {
11340
11341 this.fromGeometry( geometry );
11342
11343 }
11344
11345 }
11346
11347 return this;
11348
11349 },
11350
11351 setFromPoints: function ( points ) {
11352
11353 var position = [];
11354
11355 for ( var i = 0, l = points.length; i < l; i ++ ) {
11356
11357 var point = points[ i ];
11358 position.push( point.x, point.y, point.z || 0 );
11359
11360 }
11361
11362 this.addAttribute( 'position', new Float32BufferAttribute( position, 3 ) );
11363
11364 return this;
11365
11366 },
11367
11368 updateFromObject: function ( object ) {
11369
11370 var geometry = object.geometry;
11371
11372 if ( object.isMesh ) {
11373
11374 var direct = geometry.__directGeometry;
11375
11376 if ( geometry.elementsNeedUpdate === true ) {
11377
11378 direct = undefined;
11379 geometry.elementsNeedUpdate = false;
11380
11381 }
11382
11383 if ( direct === undefined ) {
11384
11385 return this.fromGeometry( geometry );
11386
11387 }
11388
11389 direct.verticesNeedUpdate = geometry.verticesNeedUpdate;
11390 direct.normalsNeedUpdate = geometry.normalsNeedUpdate;
11391 direct.colorsNeedUpdate = geometry.colorsNeedUpdate;
11392 direct.uvsNeedUpdate = geometry.uvsNeedUpdate;
11393 direct.groupsNeedUpdate = geometry.groupsNeedUpdate;
11394
11395 geometry.verticesNeedUpdate = false;
11396 geometry.normalsNeedUpdate = false;
11397 geometry.colorsNeedUpdate = false;
11398 geometry.uvsNeedUpdate = false;
11399 geometry.groupsNeedUpdate = false;
11400
11401 geometry = direct;
11402
11403 }
11404
11405 var attribute;
11406
11407 if ( geometry.verticesNeedUpdate === true ) {
11408
11409 attribute = this.attributes.position;
11410
11411 if ( attribute !== undefined ) {
11412
11413 attribute.copyVector3sArray( geometry.vertices );
11414 attribute.needsUpdate = true;
11415
11416 }
11417
11418 geometry.verticesNeedUpdate = false;
11419
11420 }
11421
11422 if ( geometry.normalsNeedUpdate === true ) {
11423
11424 attribute = this.attributes.normal;
11425
11426 if ( attribute !== undefined ) {
11427
11428 attribute.copyVector3sArray( geometry.normals );
11429 attribute.needsUpdate = true;
11430
11431 }
11432
11433 geometry.normalsNeedUpdate = false;
11434
11435 }
11436
11437 if ( geometry.colorsNeedUpdate === true ) {
11438
11439 attribute = this.attributes.color;
11440
11441 if ( attribute !== undefined ) {
11442
11443 attribute.copyColorsArray( geometry.colors );
11444 attribute.needsUpdate = true;
11445
11446 }
11447
11448 geometry.colorsNeedUpdate = false;
11449
11450 }
11451
11452 if ( geometry.uvsNeedUpdate ) {
11453
11454 attribute = this.attributes.uv;
11455
11456 if ( attribute !== undefined ) {
11457
11458 attribute.copyVector2sArray( geometry.uvs );
11459 attribute.needsUpdate = true;
11460
11461 }
11462
11463 geometry.uvsNeedUpdate = false;
11464
11465 }
11466
11467 if ( geometry.lineDistancesNeedUpdate ) {
11468
11469 attribute = this.attributes.lineDistance;
11470
11471 if ( attribute !== undefined ) {
11472
11473 attribute.copyArray( geometry.lineDistances );
11474 attribute.needsUpdate = true;
11475
11476 }
11477
11478 geometry.lineDistancesNeedUpdate = false;
11479
11480 }
11481
11482 if ( geometry.groupsNeedUpdate ) {
11483
11484 geometry.computeGroups( object.geometry );
11485 this.groups = geometry.groups;
11486
11487 geometry.groupsNeedUpdate = false;
11488
11489 }
11490
11491 return this;
11492
11493 },
11494
11495 fromGeometry: function ( geometry ) {
11496
11497 geometry.__directGeometry = new DirectGeometry().fromGeometry( geometry );
11498
11499 return this.fromDirectGeometry( geometry.__directGeometry );
11500
11501 },
11502
11503 fromDirectGeometry: function ( geometry ) {
11504
11505 var positions = new Float32Array( geometry.vertices.length * 3 );
11506 this.addAttribute( 'position', new BufferAttribute( positions, 3 ).copyVector3sArray( geometry.vertices ) );
11507
11508 if ( geometry.normals.length > 0 ) {
11509
11510 var normals = new Float32Array( geometry.normals.length * 3 );
11511 this.addAttribute( 'normal', new BufferAttribute( normals, 3 ).copyVector3sArray( geometry.normals ) );
11512
11513 }
11514
11515 if ( geometry.colors.length > 0 ) {
11516
11517 var colors = new Float32Array( geometry.colors.length * 3 );
11518 this.addAttribute( 'color', new BufferAttribute( colors, 3 ).copyColorsArray( geometry.colors ) );
11519
11520 }
11521
11522 if ( geometry.uvs.length > 0 ) {
11523
11524 var uvs = new Float32Array( geometry.uvs.length * 2 );
11525 this.addAttribute( 'uv', new BufferAttribute( uvs, 2 ).copyVector2sArray( geometry.uvs ) );
11526
11527 }
11528
11529 if ( geometry.uvs2.length > 0 ) {
11530
11531 var uvs2 = new Float32Array( geometry.uvs2.length * 2 );
11532 this.addAttribute( 'uv2', new BufferAttribute( uvs2, 2 ).copyVector2sArray( geometry.uvs2 ) );
11533
11534 }
11535
11536 // groups
11537
11538 this.groups = geometry.groups;
11539
11540 // morphs
11541
11542 for ( var name in geometry.morphTargets ) {
11543
11544 var array = [];
11545 var morphTargets = geometry.morphTargets[ name ];
11546
11547 for ( var i = 0, l = morphTargets.length; i < l; i ++ ) {
11548
11549 var morphTarget = morphTargets[ i ];
11550
11551 var attribute = new Float32BufferAttribute( morphTarget.length * 3, 3 );
11552
11553 array.push( attribute.copyVector3sArray( morphTarget ) );
11554
11555 }
11556
11557 this.morphAttributes[ name ] = array;
11558
11559 }
11560
11561 // skinning
11562
11563 if ( geometry.skinIndices.length > 0 ) {
11564
11565 var skinIndices = new Float32BufferAttribute( geometry.skinIndices.length * 4, 4 );
11566 this.addAttribute( 'skinIndex', skinIndices.copyVector4sArray( geometry.skinIndices ) );
11567
11568 }
11569
11570 if ( geometry.skinWeights.length > 0 ) {
11571
11572 var skinWeights = new Float32BufferAttribute( geometry.skinWeights.length * 4, 4 );
11573 this.addAttribute( 'skinWeight', skinWeights.copyVector4sArray( geometry.skinWeights ) );
11574
11575 }
11576
11577 //
11578
11579 if ( geometry.boundingSphere !== null ) {
11580
11581 this.boundingSphere = geometry.boundingSphere.clone();
11582
11583 }
11584
11585 if ( geometry.boundingBox !== null ) {
11586
11587 this.boundingBox = geometry.boundingBox.clone();
11588
11589 }
11590
11591 return this;
11592
11593 },
11594
11595 computeBoundingBox: function () {
11596
11597 if ( this.boundingBox === null ) {
11598
11599 this.boundingBox = new Box3();
11600
11601 }
11602
11603 var position = this.attributes.position;
11604
11605 if ( position !== undefined ) {
11606
11607 this.boundingBox.setFromBufferAttribute( position );
11608
11609 } else {
11610
11611 this.boundingBox.makeEmpty();
11612
11613 }
11614
11615 if ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) {
11616
11617 console.error( 'THREE.BufferGeometry.computeBoundingBox: Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this );
11618
11619 }
11620
11621 },
11622
11623 computeBoundingSphere: function () {
11624
11625 var box = new Box3();
11626 var vector = new Vector3();
11627
11628 return function computeBoundingSphere() {
11629
11630 if ( this.boundingSphere === null ) {
11631
11632 this.boundingSphere = new Sphere();
11633
11634 }
11635
11636 var position = this.attributes.position;
11637
11638 if ( position ) {
11639
11640 var center = this.boundingSphere.center;
11641
11642 box.setFromBufferAttribute( position );
11643 box.getCenter( center );
11644
11645 // hoping to find a boundingSphere with a radius smaller than the
11646 // boundingSphere of the boundingBox: sqrt(3) smaller in the best case
11647
11648 var maxRadiusSq = 0;
11649
11650 for ( var i = 0, il = position.count; i < il; i ++ ) {
11651
11652 vector.x = position.getX( i );
11653 vector.y = position.getY( i );
11654 vector.z = position.getZ( i );
11655 maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( vector ) );
11656
11657 }
11658
11659 this.boundingSphere.radius = Math.sqrt( maxRadiusSq );
11660
11661 if ( isNaN( this.boundingSphere.radius ) ) {
11662
11663 console.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this );
11664
11665 }
11666
11667 }
11668
11669 };
11670
11671 }(),
11672
11673 computeFaceNormals: function () {
11674
11675 // backwards compatibility
11676
11677 },
11678
11679 computeVertexNormals: function () {
11680
11681 var index = this.index;
11682 var attributes = this.attributes;
11683 var groups = this.groups;
11684
11685 if ( attributes.position ) {
11686
11687 var positions = attributes.position.array;
11688
11689 if ( attributes.normal === undefined ) {
11690
11691 this.addAttribute( 'normal', new BufferAttribute( new Float32Array( positions.length ), 3 ) );
11692
11693 } else {
11694
11695 // reset existing normals to zero
11696
11697 var array = attributes.normal.array;
11698
11699 for ( var i = 0, il = array.length; i < il; i ++ ) {
11700
11701 array[ i ] = 0;
11702
11703 }
11704
11705 }
11706
11707 var normals = attributes.normal.array;
11708
11709 var vA, vB, vC;
11710 var pA = new Vector3(), pB = new Vector3(), pC = new Vector3();
11711 var cb = new Vector3(), ab = new Vector3();
11712
11713 // indexed elements
11714
11715 if ( index ) {
11716
11717 var indices = index.array;
11718
11719 if ( groups.length === 0 ) {
11720
11721 this.addGroup( 0, indices.length );
11722
11723 }
11724
11725 for ( var j = 0, jl = groups.length; j < jl; ++ j ) {
11726
11727 var group = groups[ j ];
11728
11729 var start = group.start;
11730 var count = group.count;
11731
11732 for ( var i = start, il = start + count; i < il; i += 3 ) {
11733
11734 vA = indices[ i + 0 ] * 3;
11735 vB = indices[ i + 1 ] * 3;
11736 vC = indices[ i + 2 ] * 3;
11737
11738 pA.fromArray( positions, vA );
11739 pB.fromArray( positions, vB );
11740 pC.fromArray( positions, vC );
11741
11742 cb.subVectors( pC, pB );
11743 ab.subVectors( pA, pB );
11744 cb.cross( ab );
11745
11746 normals[ vA ] += cb.x;
11747 normals[ vA + 1 ] += cb.y;
11748 normals[ vA + 2 ] += cb.z;
11749
11750 normals[ vB ] += cb.x;
11751 normals[ vB + 1 ] += cb.y;
11752 normals[ vB + 2 ] += cb.z;
11753
11754 normals[ vC ] += cb.x;
11755 normals[ vC + 1 ] += cb.y;
11756 normals[ vC + 2 ] += cb.z;
11757
11758 }
11759
11760 }
11761
11762 } else {
11763
11764 // non-indexed elements (unconnected triangle soup)
11765
11766 for ( var i = 0, il = positions.length; i < il; i += 9 ) {
11767
11768 pA.fromArray( positions, i );
11769 pB.fromArray( positions, i + 3 );
11770 pC.fromArray( positions, i + 6 );
11771
11772 cb.subVectors( pC, pB );
11773 ab.subVectors( pA, pB );
11774 cb.cross( ab );
11775
11776 normals[ i ] = cb.x;
11777 normals[ i + 1 ] = cb.y;
11778 normals[ i + 2 ] = cb.z;
11779
11780 normals[ i + 3 ] = cb.x;
11781 normals[ i + 4 ] = cb.y;
11782 normals[ i + 5 ] = cb.z;
11783
11784 normals[ i + 6 ] = cb.x;
11785 normals[ i + 7 ] = cb.y;
11786 normals[ i + 8 ] = cb.z;
11787
11788 }
11789
11790 }
11791
11792 this.normalizeNormals();
11793
11794 attributes.normal.needsUpdate = true;
11795
11796 }
11797
11798 },
11799
11800 merge: function ( geometry, offset ) {
11801
11802 if ( ! ( geometry && geometry.isBufferGeometry ) ) {
11803
11804 console.error( 'THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.', geometry );
11805 return;
11806
11807 }
11808
11809 if ( offset === undefined ) {
11810
11811 offset = 0;
11812
11813 console.warn(
11814 'THREE.BufferGeometry.merge(): Overwriting original geometry, starting at offset=0. '
11815 + 'Use BufferGeometryUtils.mergeBufferGeometries() for lossless merge.'
11816 );
11817
11818 }
11819
11820 var attributes = this.attributes;
11821
11822 for ( var key in attributes ) {
11823
11824 if ( geometry.attributes[ key ] === undefined ) continue;
11825
11826 var attribute1 = attributes[ key ];
11827 var attributeArray1 = attribute1.array;
11828
11829 var attribute2 = geometry.attributes[ key ];
11830 var attributeArray2 = attribute2.array;
11831
11832 var attributeSize = attribute2.itemSize;
11833
11834 for ( var i = 0, j = attributeSize * offset; i < attributeArray2.length; i ++, j ++ ) {
11835
11836 attributeArray1[ j ] = attributeArray2[ i ];
11837
11838 }
11839
11840 }
11841
11842 return this;
11843
11844 },
11845
11846 normalizeNormals: function () {
11847
11848 var vector = new Vector3();
11849
11850 return function normalizeNormals() {
11851
11852 var normals = this.attributes.normal;
11853
11854 for ( var i = 0, il = normals.count; i < il; i ++ ) {
11855
11856 vector.x = normals.getX( i );
11857 vector.y = normals.getY( i );
11858 vector.z = normals.getZ( i );
11859
11860 vector.normalize();
11861
11862 normals.setXYZ( i, vector.x, vector.y, vector.z );
11863
11864 }
11865
11866 };
11867
11868 }(),
11869
11870 toNonIndexed: function () {
11871
11872 if ( this.index === null ) {
11873
11874 console.warn( 'THREE.BufferGeometry.toNonIndexed(): Geometry is already non-indexed.' );
11875 return this;
11876
11877 }
11878
11879 var geometry2 = new BufferGeometry();
11880
11881 var indices = this.index.array;
11882 var attributes = this.attributes;
11883
11884 for ( var name in attributes ) {
11885
11886 var attribute = attributes[ name ];
11887
11888 var array = attribute.array;
11889 var itemSize = attribute.itemSize;
11890
11891 var array2 = new array.constructor( indices.length * itemSize );
11892
11893 var index = 0, index2 = 0;
11894
11895 for ( var i = 0, l = indices.length; i < l; i ++ ) {
11896
11897 index = indices[ i ] * itemSize;
11898
11899 for ( var j = 0; j < itemSize; j ++ ) {
11900
11901 array2[ index2 ++ ] = array[ index ++ ];
11902
11903 }
11904
11905 }
11906
11907 geometry2.addAttribute( name, new BufferAttribute( array2, itemSize ) );
11908
11909 }
11910
11911 var groups = this.groups;
11912
11913 for ( var i = 0, l = groups.length; i < l; i ++ ) {
11914
11915 var group = groups[ i ];
11916 geometry2.addGroup( group.start, group.count, group.materialIndex );
11917
11918 }
11919
11920 return geometry2;
11921
11922 },
11923
11924 toJSON: function () {
11925
11926 var data = {
11927 metadata: {
11928 version: 4.5,
11929 type: 'BufferGeometry',
11930 generator: 'BufferGeometry.toJSON'
11931 }
11932 };
11933
11934 // standard BufferGeometry serialization
11935
11936 data.uuid = this.uuid;
11937 data.type = this.type;
11938 if ( this.name !== '' ) data.name = this.name;
11939
11940 if ( this.parameters !== undefined ) {
11941
11942 var parameters = this.parameters;
11943
11944 for ( var key in parameters ) {
11945
11946 if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ];
11947
11948 }
11949
11950 return data;
11951
11952 }
11953
11954 data.data = { attributes: {} };
11955
11956 var index = this.index;
11957
11958 if ( index !== null ) {
11959
11960 var array = Array.prototype.slice.call( index.array );
11961
11962 data.data.index = {
11963 type: index.array.constructor.name,
11964 array: array
11965 };
11966
11967 }
11968
11969 var attributes = this.attributes;
11970
11971 for ( var key in attributes ) {
11972
11973 var attribute = attributes[ key ];
11974
11975 var array = Array.prototype.slice.call( attribute.array );
11976
11977 data.data.attributes[ key ] = {
11978 itemSize: attribute.itemSize,
11979 type: attribute.array.constructor.name,
11980 array: array,
11981 normalized: attribute.normalized
11982 };
11983
11984 }
11985
11986 var groups = this.groups;
11987
11988 if ( groups.length > 0 ) {
11989
11990 data.data.groups = JSON.parse( JSON.stringify( groups ) );
11991
11992 }
11993
11994 var boundingSphere = this.boundingSphere;
11995
11996 if ( boundingSphere !== null ) {
11997
11998 data.data.boundingSphere = {
11999 center: boundingSphere.center.toArray(),
12000 radius: boundingSphere.radius
12001 };
12002
12003 }
12004
12005 return data;
12006
12007 },
12008
12009 clone: function () {
12010
12011 /*
12012 // Handle primitives
12013
12014 var parameters = this.parameters;
12015
12016 if ( parameters !== undefined ) {
12017
12018 var values = [];
12019
12020 for ( var key in parameters ) {
12021
12022 values.push( parameters[ key ] );
12023
12024 }
12025
12026 var geometry = Object.create( this.constructor.prototype );
12027 this.constructor.apply( geometry, values );
12028 return geometry;
12029
12030 }
12031
12032 return new this.constructor().copy( this );
12033 */
12034
12035 return new BufferGeometry().copy( this );
12036
12037 },
12038
12039 copy: function ( source ) {
12040
12041 var name, i, l;
12042
12043 // reset
12044
12045 this.index = null;
12046 this.attributes = {};
12047 this.morphAttributes = {};
12048 this.groups = [];
12049 this.boundingBox = null;
12050 this.boundingSphere = null;
12051
12052 // name
12053
12054 this.name = source.name;
12055
12056 // index
12057
12058 var index = source.index;
12059
12060 if ( index !== null ) {
12061
12062 this.setIndex( index.clone() );
12063
12064 }
12065
12066 // attributes
12067
12068 var attributes = source.attributes;
12069
12070 for ( name in attributes ) {
12071
12072 var attribute = attributes[ name ];
12073 this.addAttribute( name, attribute.clone() );
12074
12075 }
12076
12077 // morph attributes
12078
12079 var morphAttributes = source.morphAttributes;
12080
12081 for ( name in morphAttributes ) {
12082
12083 var array = [];
12084 var morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes
12085
12086 for ( i = 0, l = morphAttribute.length; i < l; i ++ ) {
12087
12088 array.push( morphAttribute[ i ].clone() );
12089
12090 }
12091
12092 this.morphAttributes[ name ] = array;
12093
12094 }
12095
12096 // groups
12097
12098 var groups = source.groups;
12099
12100 for ( i = 0, l = groups.length; i < l; i ++ ) {
12101
12102 var group = groups[ i ];
12103 this.addGroup( group.start, group.count, group.materialIndex );
12104
12105 }
12106
12107 // bounding box
12108
12109 var boundingBox = source.boundingBox;
12110
12111 if ( boundingBox !== null ) {
12112
12113 this.boundingBox = boundingBox.clone();
12114
12115 }
12116
12117 // bounding sphere
12118
12119 var boundingSphere = source.boundingSphere;
12120
12121 if ( boundingSphere !== null ) {
12122
12123 this.boundingSphere = boundingSphere.clone();
12124
12125 }
12126
12127 // draw range
12128
12129 this.drawRange.start = source.drawRange.start;
12130 this.drawRange.count = source.drawRange.count;
12131
12132 return this;
12133
12134 },
12135
12136 dispose: function () {
12137
12138 this.dispatchEvent( { type: 'dispose' } );
12139
12140 }
12141
12142 } );
12143
12144 /**
12145 * @author mrdoob / http://mrdoob.com/
12146 * @author Mugen87 / https://github.com/Mugen87
12147 */
12148
12149 // BoxGeometry
12150
12151 function BoxGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) {
12152
12153 Geometry.call( this );
12154
12155 this.type = 'BoxGeometry';
12156
12157 this.parameters = {
12158 width: width,
12159 height: height,
12160 depth: depth,
12161 widthSegments: widthSegments,
12162 heightSegments: heightSegments,
12163 depthSegments: depthSegments
12164 };
12165
12166 this.fromBufferGeometry( new BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) );
12167 this.mergeVertices();
12168
12169 }
12170
12171 BoxGeometry.prototype = Object.create( Geometry.prototype );
12172 BoxGeometry.prototype.constructor = BoxGeometry;
12173
12174 // BoxBufferGeometry
12175
12176 function BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) {
12177
12178 BufferGeometry.call( this );
12179
12180 this.type = 'BoxBufferGeometry';
12181
12182 this.parameters = {
12183 width: width,
12184 height: height,
12185 depth: depth,
12186 widthSegments: widthSegments,
12187 heightSegments: heightSegments,
12188 depthSegments: depthSegments
12189 };
12190
12191 var scope = this;
12192
12193 width = width || 1;
12194 height = height || 1;
12195 depth = depth || 1;
12196
12197 // segments
12198
12199 widthSegments = Math.floor( widthSegments ) || 1;
12200 heightSegments = Math.floor( heightSegments ) || 1;
12201 depthSegments = Math.floor( depthSegments ) || 1;
12202
12203 // buffers
12204
12205 var indices = [];
12206 var vertices = [];
12207 var normals = [];
12208 var uvs = [];
12209
12210 // helper variables
12211
12212 var numberOfVertices = 0;
12213 var groupStart = 0;
12214
12215 // build each side of the box geometry
12216
12217 buildPlane( 'z', 'y', 'x', - 1, - 1, depth, height, width, depthSegments, heightSegments, 0 ); // px
12218 buildPlane( 'z', 'y', 'x', 1, - 1, depth, height, - width, depthSegments, heightSegments, 1 ); // nx
12219 buildPlane( 'x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2 ); // py
12220 buildPlane( 'x', 'z', 'y', 1, - 1, width, depth, - height, widthSegments, depthSegments, 3 ); // ny
12221 buildPlane( 'x', 'y', 'z', 1, - 1, width, height, depth, widthSegments, heightSegments, 4 ); // pz
12222 buildPlane( 'x', 'y', 'z', - 1, - 1, width, height, - depth, widthSegments, heightSegments, 5 ); // nz
12223
12224 // build geometry
12225
12226 this.setIndex( indices );
12227 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
12228 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
12229 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
12230
12231 function buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) {
12232
12233 var segmentWidth = width / gridX;
12234 var segmentHeight = height / gridY;
12235
12236 var widthHalf = width / 2;
12237 var heightHalf = height / 2;
12238 var depthHalf = depth / 2;
12239
12240 var gridX1 = gridX + 1;
12241 var gridY1 = gridY + 1;
12242
12243 var vertexCounter = 0;
12244 var groupCount = 0;
12245
12246 var ix, iy;
12247
12248 var vector = new Vector3();
12249
12250 // generate vertices, normals and uvs
12251
12252 for ( iy = 0; iy < gridY1; iy ++ ) {
12253
12254 var y = iy * segmentHeight - heightHalf;
12255
12256 for ( ix = 0; ix < gridX1; ix ++ ) {
12257
12258 var x = ix * segmentWidth - widthHalf;
12259
12260 // set values to correct vector component
12261
12262 vector[ u ] = x * udir;
12263 vector[ v ] = y * vdir;
12264 vector[ w ] = depthHalf;
12265
12266 // now apply vector to vertex buffer
12267
12268 vertices.push( vector.x, vector.y, vector.z );
12269
12270 // set values to correct vector component
12271
12272 vector[ u ] = 0;
12273 vector[ v ] = 0;
12274 vector[ w ] = depth > 0 ? 1 : - 1;
12275
12276 // now apply vector to normal buffer
12277
12278 normals.push( vector.x, vector.y, vector.z );
12279
12280 // uvs
12281
12282 uvs.push( ix / gridX );
12283 uvs.push( 1 - ( iy / gridY ) );
12284
12285 // counters
12286
12287 vertexCounter += 1;
12288
12289 }
12290
12291 }
12292
12293 // indices
12294
12295 // 1. you need three indices to draw a single face
12296 // 2. a single segment consists of two faces
12297 // 3. so we need to generate six (2*3) indices per segment
12298
12299 for ( iy = 0; iy < gridY; iy ++ ) {
12300
12301 for ( ix = 0; ix < gridX; ix ++ ) {
12302
12303 var a = numberOfVertices + ix + gridX1 * iy;
12304 var b = numberOfVertices + ix + gridX1 * ( iy + 1 );
12305 var c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 );
12306 var d = numberOfVertices + ( ix + 1 ) + gridX1 * iy;
12307
12308 // faces
12309
12310 indices.push( a, b, d );
12311 indices.push( b, c, d );
12312
12313 // increase counter
12314
12315 groupCount += 6;
12316
12317 }
12318
12319 }
12320
12321 // add a group to the geometry. this will ensure multi material support
12322
12323 scope.addGroup( groupStart, groupCount, materialIndex );
12324
12325 // calculate new start value for groups
12326
12327 groupStart += groupCount;
12328
12329 // update total number of vertices
12330
12331 numberOfVertices += vertexCounter;
12332
12333 }
12334
12335 }
12336
12337 BoxBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
12338 BoxBufferGeometry.prototype.constructor = BoxBufferGeometry;
12339
12340 /**
12341 * @author mrdoob / http://mrdoob.com/
12342 * @author Mugen87 / https://github.com/Mugen87
12343 */
12344
12345 // PlaneGeometry
12346
12347 function PlaneGeometry( width, height, widthSegments, heightSegments ) {
12348
12349 Geometry.call( this );
12350
12351 this.type = 'PlaneGeometry';
12352
12353 this.parameters = {
12354 width: width,
12355 height: height,
12356 widthSegments: widthSegments,
12357 heightSegments: heightSegments
12358 };
12359
12360 this.fromBufferGeometry( new PlaneBufferGeometry( width, height, widthSegments, heightSegments ) );
12361 this.mergeVertices();
12362
12363 }
12364
12365 PlaneGeometry.prototype = Object.create( Geometry.prototype );
12366 PlaneGeometry.prototype.constructor = PlaneGeometry;
12367
12368 // PlaneBufferGeometry
12369
12370 function PlaneBufferGeometry( width, height, widthSegments, heightSegments ) {
12371
12372 BufferGeometry.call( this );
12373
12374 this.type = 'PlaneBufferGeometry';
12375
12376 this.parameters = {
12377 width: width,
12378 height: height,
12379 widthSegments: widthSegments,
12380 heightSegments: heightSegments
12381 };
12382
12383 width = width || 1;
12384 height = height || 1;
12385
12386 var width_half = width / 2;
12387 var height_half = height / 2;
12388
12389 var gridX = Math.floor( widthSegments ) || 1;
12390 var gridY = Math.floor( heightSegments ) || 1;
12391
12392 var gridX1 = gridX + 1;
12393 var gridY1 = gridY + 1;
12394
12395 var segment_width = width / gridX;
12396 var segment_height = height / gridY;
12397
12398 var ix, iy;
12399
12400 // buffers
12401
12402 var indices = [];
12403 var vertices = [];
12404 var normals = [];
12405 var uvs = [];
12406
12407 // generate vertices, normals and uvs
12408
12409 for ( iy = 0; iy < gridY1; iy ++ ) {
12410
12411 var y = iy * segment_height - height_half;
12412
12413 for ( ix = 0; ix < gridX1; ix ++ ) {
12414
12415 var x = ix * segment_width - width_half;
12416
12417 vertices.push( x, - y, 0 );
12418
12419 normals.push( 0, 0, 1 );
12420
12421 uvs.push( ix / gridX );
12422 uvs.push( 1 - ( iy / gridY ) );
12423
12424 }
12425
12426 }
12427
12428 // indices
12429
12430 for ( iy = 0; iy < gridY; iy ++ ) {
12431
12432 for ( ix = 0; ix < gridX; ix ++ ) {
12433
12434 var a = ix + gridX1 * iy;
12435 var b = ix + gridX1 * ( iy + 1 );
12436 var c = ( ix + 1 ) + gridX1 * ( iy + 1 );
12437 var d = ( ix + 1 ) + gridX1 * iy;
12438
12439 // faces
12440
12441 indices.push( a, b, d );
12442 indices.push( b, c, d );
12443
12444 }
12445
12446 }
12447
12448 // build geometry
12449
12450 this.setIndex( indices );
12451 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
12452 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
12453 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
12454
12455 }
12456
12457 PlaneBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
12458 PlaneBufferGeometry.prototype.constructor = PlaneBufferGeometry;
12459
12460 /**
12461 * @author mrdoob / http://mrdoob.com/
12462 * @author alteredq / http://alteredqualia.com/
12463 */
12464
12465 var materialId = 0;
12466
12467 function Material() {
12468
12469 Object.defineProperty( this, 'id', { value: materialId ++ } );
12470
12471 this.uuid = _Math.generateUUID();
12472
12473 this.name = '';
12474 this.type = 'Material';
12475
12476 this.fog = true;
12477 this.lights = true;
12478
12479 this.blending = NormalBlending;
12480 this.side = FrontSide;
12481 this.flatShading = false;
12482 this.vertexColors = NoColors; // THREE.NoColors, THREE.VertexColors, THREE.FaceColors
12483
12484 this.opacity = 1;
12485 this.transparent = false;
12486
12487 this.blendSrc = SrcAlphaFactor;
12488 this.blendDst = OneMinusSrcAlphaFactor;
12489 this.blendEquation = AddEquation;
12490 this.blendSrcAlpha = null;
12491 this.blendDstAlpha = null;
12492 this.blendEquationAlpha = null;
12493
12494 this.depthFunc = LessEqualDepth;
12495 this.depthTest = true;
12496 this.depthWrite = true;
12497
12498 this.clippingPlanes = null;
12499 this.clipIntersection = false;
12500 this.clipShadows = false;
12501
12502 this.shadowSide = null;
12503
12504 this.colorWrite = true;
12505
12506 this.precision = null; // override the renderer's default precision for this material
12507
12508 this.polygonOffset = false;
12509 this.polygonOffsetFactor = 0;
12510 this.polygonOffsetUnits = 0;
12511
12512 this.dithering = false;
12513
12514 this.alphaTest = 0;
12515 this.premultipliedAlpha = false;
12516
12517 this.overdraw = 0; // Overdrawn pixels (typically between 0 and 1) for fixing antialiasing gaps in CanvasRenderer
12518
12519 this.visible = true;
12520
12521 this.userData = {};
12522
12523 this.needsUpdate = true;
12524
12525 }
12526
12527 Material.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
12528
12529 constructor: Material,
12530
12531 isMaterial: true,
12532
12533 onBeforeCompile: function () {},
12534
12535 setValues: function ( values ) {
12536
12537 if ( values === undefined ) return;
12538
12539 for ( var key in values ) {
12540
12541 var newValue = values[ key ];
12542
12543 if ( newValue === undefined ) {
12544
12545 console.warn( "THREE.Material: '" + key + "' parameter is undefined." );
12546 continue;
12547
12548 }
12549
12550 // for backward compatability if shading is set in the constructor
12551 if ( key === 'shading' ) {
12552
12553 console.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );
12554 this.flatShading = ( newValue === FlatShading ) ? true : false;
12555 continue;
12556
12557 }
12558
12559 var currentValue = this[ key ];
12560
12561 if ( currentValue === undefined ) {
12562
12563 console.warn( "THREE." + this.type + ": '" + key + "' is not a property of this material." );
12564 continue;
12565
12566 }
12567
12568 if ( currentValue && currentValue.isColor ) {
12569
12570 currentValue.set( newValue );
12571
12572 } else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) {
12573
12574 currentValue.copy( newValue );
12575
12576 } else if ( key === 'overdraw' ) {
12577
12578 // ensure overdraw is backwards-compatible with legacy boolean type
12579 this[ key ] = Number( newValue );
12580
12581 } else {
12582
12583 this[ key ] = newValue;
12584
12585 }
12586
12587 }
12588
12589 },
12590
12591 toJSON: function ( meta ) {
12592
12593 var isRoot = ( meta === undefined || typeof meta === 'string' );
12594
12595 if ( isRoot ) {
12596
12597 meta = {
12598 textures: {},
12599 images: {}
12600 };
12601
12602 }
12603
12604 var data = {
12605 metadata: {
12606 version: 4.5,
12607 type: 'Material',
12608 generator: 'Material.toJSON'
12609 }
12610 };
12611
12612 // standard Material serialization
12613 data.uuid = this.uuid;
12614 data.type = this.type;
12615
12616 if ( this.name !== '' ) data.name = this.name;
12617
12618 if ( this.color && this.color.isColor ) data.color = this.color.getHex();
12619
12620 if ( this.roughness !== undefined ) data.roughness = this.roughness;
12621 if ( this.metalness !== undefined ) data.metalness = this.metalness;
12622
12623 if ( this.emissive && this.emissive.isColor ) data.emissive = this.emissive.getHex();
12624 if ( this.emissiveIntensity !== 1 ) data.emissiveIntensity = this.emissiveIntensity;
12625
12626 if ( this.specular && this.specular.isColor ) data.specular = this.specular.getHex();
12627 if ( this.shininess !== undefined ) data.shininess = this.shininess;
12628 if ( this.clearCoat !== undefined ) data.clearCoat = this.clearCoat;
12629 if ( this.clearCoatRoughness !== undefined ) data.clearCoatRoughness = this.clearCoatRoughness;
12630
12631 if ( this.map && this.map.isTexture ) data.map = this.map.toJSON( meta ).uuid;
12632 if ( this.alphaMap && this.alphaMap.isTexture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid;
12633 if ( this.lightMap && this.lightMap.isTexture ) data.lightMap = this.lightMap.toJSON( meta ).uuid;
12634 if ( this.bumpMap && this.bumpMap.isTexture ) {
12635
12636 data.bumpMap = this.bumpMap.toJSON( meta ).uuid;
12637 data.bumpScale = this.bumpScale;
12638
12639 }
12640 if ( this.normalMap && this.normalMap.isTexture ) {
12641
12642 data.normalMap = this.normalMap.toJSON( meta ).uuid;
12643 data.normalScale = this.normalScale.toArray();
12644
12645 }
12646 if ( this.displacementMap && this.displacementMap.isTexture ) {
12647
12648 data.displacementMap = this.displacementMap.toJSON( meta ).uuid;
12649 data.displacementScale = this.displacementScale;
12650 data.displacementBias = this.displacementBias;
12651
12652 }
12653 if ( this.roughnessMap && this.roughnessMap.isTexture ) data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid;
12654 if ( this.metalnessMap && this.metalnessMap.isTexture ) data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid;
12655
12656 if ( this.emissiveMap && this.emissiveMap.isTexture ) data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid;
12657 if ( this.specularMap && this.specularMap.isTexture ) data.specularMap = this.specularMap.toJSON( meta ).uuid;
12658
12659 if ( this.envMap && this.envMap.isTexture ) {
12660
12661 data.envMap = this.envMap.toJSON( meta ).uuid;
12662 data.reflectivity = this.reflectivity; // Scale behind envMap
12663
12664 }
12665
12666 if ( this.gradientMap && this.gradientMap.isTexture ) {
12667
12668 data.gradientMap = this.gradientMap.toJSON( meta ).uuid;
12669
12670 }
12671
12672 if ( this.size !== undefined ) data.size = this.size;
12673 if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation;
12674
12675 if ( this.blending !== NormalBlending ) data.blending = this.blending;
12676 if ( this.flatShading === true ) data.flatShading = this.flatShading;
12677 if ( this.side !== FrontSide ) data.side = this.side;
12678 if ( this.vertexColors !== NoColors ) data.vertexColors = this.vertexColors;
12679
12680 if ( this.opacity < 1 ) data.opacity = this.opacity;
12681 if ( this.transparent === true ) data.transparent = this.transparent;
12682
12683 data.depthFunc = this.depthFunc;
12684 data.depthTest = this.depthTest;
12685 data.depthWrite = this.depthWrite;
12686
12687 // rotation (SpriteMaterial)
12688 if ( this.rotation !== 0 ) data.rotation = this.rotation;
12689
12690 if ( this.linewidth !== 1 ) data.linewidth = this.linewidth;
12691 if ( this.dashSize !== undefined ) data.dashSize = this.dashSize;
12692 if ( this.gapSize !== undefined ) data.gapSize = this.gapSize;
12693 if ( this.scale !== undefined ) data.scale = this.scale;
12694
12695 if ( this.dithering === true ) data.dithering = true;
12696
12697 if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest;
12698 if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = this.premultipliedAlpha;
12699
12700 if ( this.wireframe === true ) data.wireframe = this.wireframe;
12701 if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth;
12702 if ( this.wireframeLinecap !== 'round' ) data.wireframeLinecap = this.wireframeLinecap;
12703 if ( this.wireframeLinejoin !== 'round' ) data.wireframeLinejoin = this.wireframeLinejoin;
12704
12705 if ( this.morphTargets === true ) data.morphTargets = true;
12706 if ( this.skinning === true ) data.skinning = true;
12707
12708 if ( this.visible === false ) data.visible = false;
12709 if ( JSON.stringify( this.userData ) !== '{}' ) data.userData = this.userData;
12710
12711 // TODO: Copied from Object3D.toJSON
12712
12713 function extractFromCache( cache ) {
12714
12715 var values = [];
12716
12717 for ( var key in cache ) {
12718
12719 var data = cache[ key ];
12720 delete data.metadata;
12721 values.push( data );
12722
12723 }
12724
12725 return values;
12726
12727 }
12728
12729 if ( isRoot ) {
12730
12731 var textures = extractFromCache( meta.textures );
12732 var images = extractFromCache( meta.images );
12733
12734 if ( textures.length > 0 ) data.textures = textures;
12735 if ( images.length > 0 ) data.images = images;
12736
12737 }
12738
12739 return data;
12740
12741 },
12742
12743 clone: function () {
12744
12745 return new this.constructor().copy( this );
12746
12747 },
12748
12749 copy: function ( source ) {
12750
12751 this.name = source.name;
12752
12753 this.fog = source.fog;
12754 this.lights = source.lights;
12755
12756 this.blending = source.blending;
12757 this.side = source.side;
12758 this.flatShading = source.flatShading;
12759 this.vertexColors = source.vertexColors;
12760
12761 this.opacity = source.opacity;
12762 this.transparent = source.transparent;
12763
12764 this.blendSrc = source.blendSrc;
12765 this.blendDst = source.blendDst;
12766 this.blendEquation = source.blendEquation;
12767 this.blendSrcAlpha = source.blendSrcAlpha;
12768 this.blendDstAlpha = source.blendDstAlpha;
12769 this.blendEquationAlpha = source.blendEquationAlpha;
12770
12771 this.depthFunc = source.depthFunc;
12772 this.depthTest = source.depthTest;
12773 this.depthWrite = source.depthWrite;
12774
12775 this.colorWrite = source.colorWrite;
12776
12777 this.precision = source.precision;
12778
12779 this.polygonOffset = source.polygonOffset;
12780 this.polygonOffsetFactor = source.polygonOffsetFactor;
12781 this.polygonOffsetUnits = source.polygonOffsetUnits;
12782
12783 this.dithering = source.dithering;
12784
12785 this.alphaTest = source.alphaTest;
12786 this.premultipliedAlpha = source.premultipliedAlpha;
12787
12788 this.overdraw = source.overdraw;
12789
12790 this.visible = source.visible;
12791 this.userData = JSON.parse( JSON.stringify( source.userData ) );
12792
12793 this.clipShadows = source.clipShadows;
12794 this.clipIntersection = source.clipIntersection;
12795
12796 var srcPlanes = source.clippingPlanes,
12797 dstPlanes = null;
12798
12799 if ( srcPlanes !== null ) {
12800
12801 var n = srcPlanes.length;
12802 dstPlanes = new Array( n );
12803
12804 for ( var i = 0; i !== n; ++ i )
12805 dstPlanes[ i ] = srcPlanes[ i ].clone();
12806
12807 }
12808
12809 this.clippingPlanes = dstPlanes;
12810
12811 this.shadowSide = source.shadowSide;
12812
12813 return this;
12814
12815 },
12816
12817 dispose: function () {
12818
12819 this.dispatchEvent( { type: 'dispose' } );
12820
12821 }
12822
12823 } );
12824
12825 /**
12826 * @author mrdoob / http://mrdoob.com/
12827 * @author alteredq / http://alteredqualia.com/
12828 *
12829 * parameters = {
12830 * color: <hex>,
12831 * opacity: <float>,
12832 * map: new THREE.Texture( <Image> ),
12833 *
12834 * lightMap: new THREE.Texture( <Image> ),
12835 * lightMapIntensity: <float>
12836 *
12837 * aoMap: new THREE.Texture( <Image> ),
12838 * aoMapIntensity: <float>
12839 *
12840 * specularMap: new THREE.Texture( <Image> ),
12841 *
12842 * alphaMap: new THREE.Texture( <Image> ),
12843 *
12844 * envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
12845 * combine: THREE.Multiply,
12846 * reflectivity: <float>,
12847 * refractionRatio: <float>,
12848 *
12849 * depthTest: <bool>,
12850 * depthWrite: <bool>,
12851 *
12852 * wireframe: <boolean>,
12853 * wireframeLinewidth: <float>,
12854 *
12855 * skinning: <bool>,
12856 * morphTargets: <bool>
12857 * }
12858 */
12859
12860 function MeshBasicMaterial( parameters ) {
12861
12862 Material.call( this );
12863
12864 this.type = 'MeshBasicMaterial';
12865
12866 this.color = new Color( 0xffffff ); // emissive
12867
12868 this.map = null;
12869
12870 this.lightMap = null;
12871 this.lightMapIntensity = 1.0;
12872
12873 this.aoMap = null;
12874 this.aoMapIntensity = 1.0;
12875
12876 this.specularMap = null;
12877
12878 this.alphaMap = null;
12879
12880 this.envMap = null;
12881 this.combine = MultiplyOperation;
12882 this.reflectivity = 1;
12883 this.refractionRatio = 0.98;
12884
12885 this.wireframe = false;
12886 this.wireframeLinewidth = 1;
12887 this.wireframeLinecap = 'round';
12888 this.wireframeLinejoin = 'round';
12889
12890 this.skinning = false;
12891 this.morphTargets = false;
12892
12893 this.lights = false;
12894
12895 this.setValues( parameters );
12896
12897 }
12898
12899 MeshBasicMaterial.prototype = Object.create( Material.prototype );
12900 MeshBasicMaterial.prototype.constructor = MeshBasicMaterial;
12901
12902 MeshBasicMaterial.prototype.isMeshBasicMaterial = true;
12903
12904 MeshBasicMaterial.prototype.copy = function ( source ) {
12905
12906 Material.prototype.copy.call( this, source );
12907
12908 this.color.copy( source.color );
12909
12910 this.map = source.map;
12911
12912 this.lightMap = source.lightMap;
12913 this.lightMapIntensity = source.lightMapIntensity;
12914
12915 this.aoMap = source.aoMap;
12916 this.aoMapIntensity = source.aoMapIntensity;
12917
12918 this.specularMap = source.specularMap;
12919
12920 this.alphaMap = source.alphaMap;
12921
12922 this.envMap = source.envMap;
12923 this.combine = source.combine;
12924 this.reflectivity = source.reflectivity;
12925 this.refractionRatio = source.refractionRatio;
12926
12927 this.wireframe = source.wireframe;
12928 this.wireframeLinewidth = source.wireframeLinewidth;
12929 this.wireframeLinecap = source.wireframeLinecap;
12930 this.wireframeLinejoin = source.wireframeLinejoin;
12931
12932 this.skinning = source.skinning;
12933 this.morphTargets = source.morphTargets;
12934
12935 return this;
12936
12937 };
12938
12939 /**
12940 * @author alteredq / http://alteredqualia.com/
12941 *
12942 * parameters = {
12943 * defines: { "label" : "value" },
12944 * uniforms: { "parameter1": { value: 1.0 }, "parameter2": { value2: 2 } },
12945 *
12946 * fragmentShader: <string>,
12947 * vertexShader: <string>,
12948 *
12949 * wireframe: <boolean>,
12950 * wireframeLinewidth: <float>,
12951 *
12952 * lights: <bool>,
12953 *
12954 * skinning: <bool>,
12955 * morphTargets: <bool>,
12956 * morphNormals: <bool>
12957 * }
12958 */
12959
12960 function ShaderMaterial( parameters ) {
12961
12962 Material.call( this );
12963
12964 this.type = 'ShaderMaterial';
12965
12966 this.defines = {};
12967 this.uniforms = {};
12968
12969 this.vertexShader = 'void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}';
12970 this.fragmentShader = 'void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}';
12971
12972 this.linewidth = 1;
12973
12974 this.wireframe = false;
12975 this.wireframeLinewidth = 1;
12976
12977 this.fog = false; // set to use scene fog
12978 this.lights = false; // set to use scene lights
12979 this.clipping = false; // set to use user-defined clipping planes
12980
12981 this.skinning = false; // set to use skinning attribute streams
12982 this.morphTargets = false; // set to use morph targets
12983 this.morphNormals = false; // set to use morph normals
12984
12985 this.extensions = {
12986 derivatives: false, // set to use derivatives
12987 fragDepth: false, // set to use fragment depth values
12988 drawBuffers: false, // set to use draw buffers
12989 shaderTextureLOD: false // set to use shader texture LOD
12990 };
12991
12992 // When rendered geometry doesn't include these attributes but the material does,
12993 // use these default values in WebGL. This avoids errors when buffer data is missing.
12994 this.defaultAttributeValues = {
12995 'color': [ 1, 1, 1 ],
12996 'uv': [ 0, 0 ],
12997 'uv2': [ 0, 0 ]
12998 };
12999
13000 this.index0AttributeName = undefined;
13001 this.uniformsNeedUpdate = false;
13002
13003 if ( parameters !== undefined ) {
13004
13005 if ( parameters.attributes !== undefined ) {
13006
13007 console.error( 'THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead.' );
13008
13009 }
13010
13011 this.setValues( parameters );
13012
13013 }
13014
13015 }
13016
13017 ShaderMaterial.prototype = Object.create( Material.prototype );
13018 ShaderMaterial.prototype.constructor = ShaderMaterial;
13019
13020 ShaderMaterial.prototype.isShaderMaterial = true;
13021
13022 ShaderMaterial.prototype.copy = function ( source ) {
13023
13024 Material.prototype.copy.call( this, source );
13025
13026 this.fragmentShader = source.fragmentShader;
13027 this.vertexShader = source.vertexShader;
13028
13029 this.uniforms = UniformsUtils.clone( source.uniforms );
13030
13031 this.defines = Object.assign( {}, source.defines );
13032
13033 this.wireframe = source.wireframe;
13034 this.wireframeLinewidth = source.wireframeLinewidth;
13035
13036 this.lights = source.lights;
13037 this.clipping = source.clipping;
13038
13039 this.skinning = source.skinning;
13040
13041 this.morphTargets = source.morphTargets;
13042 this.morphNormals = source.morphNormals;
13043
13044 this.extensions = source.extensions;
13045
13046 return this;
13047
13048 };
13049
13050 ShaderMaterial.prototype.toJSON = function ( meta ) {
13051
13052 var data = Material.prototype.toJSON.call( this, meta );
13053
13054 data.uniforms = this.uniforms;
13055 data.vertexShader = this.vertexShader;
13056 data.fragmentShader = this.fragmentShader;
13057
13058 return data;
13059
13060 };
13061
13062 /**
13063 * @author bhouston / http://clara.io
13064 */
13065
13066 function Ray( origin, direction ) {
13067
13068 this.origin = ( origin !== undefined ) ? origin : new Vector3();
13069 this.direction = ( direction !== undefined ) ? direction : new Vector3();
13070
13071 }
13072
13073 Object.assign( Ray.prototype, {
13074
13075 set: function ( origin, direction ) {
13076
13077 this.origin.copy( origin );
13078 this.direction.copy( direction );
13079
13080 return this;
13081
13082 },
13083
13084 clone: function () {
13085
13086 return new this.constructor().copy( this );
13087
13088 },
13089
13090 copy: function ( ray ) {
13091
13092 this.origin.copy( ray.origin );
13093 this.direction.copy( ray.direction );
13094
13095 return this;
13096
13097 },
13098
13099 at: function ( t, target ) {
13100
13101 if ( target === undefined ) {
13102
13103 console.warn( 'THREE.Ray: .at() target is now required' );
13104 target = new Vector3();
13105
13106 }
13107
13108 return target.copy( this.direction ).multiplyScalar( t ).add( this.origin );
13109
13110 },
13111
13112 lookAt: function ( v ) {
13113
13114 this.direction.copy( v ).sub( this.origin ).normalize();
13115
13116 return this;
13117
13118 },
13119
13120 recast: function () {
13121
13122 var v1 = new Vector3();
13123
13124 return function recast( t ) {
13125
13126 this.origin.copy( this.at( t, v1 ) );
13127
13128 return this;
13129
13130 };
13131
13132 }(),
13133
13134 closestPointToPoint: function ( point, target ) {
13135
13136 if ( target === undefined ) {
13137
13138 console.warn( 'THREE.Ray: .closestPointToPoint() target is now required' );
13139 target = new Vector3();
13140
13141 }
13142
13143 target.subVectors( point, this.origin );
13144
13145 var directionDistance = target.dot( this.direction );
13146
13147 if ( directionDistance < 0 ) {
13148
13149 return target.copy( this.origin );
13150
13151 }
13152
13153 return target.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );
13154
13155 },
13156
13157 distanceToPoint: function ( point ) {
13158
13159 return Math.sqrt( this.distanceSqToPoint( point ) );
13160
13161 },
13162
13163 distanceSqToPoint: function () {
13164
13165 var v1 = new Vector3();
13166
13167 return function distanceSqToPoint( point ) {
13168
13169 var directionDistance = v1.subVectors( point, this.origin ).dot( this.direction );
13170
13171 // point behind the ray
13172
13173 if ( directionDistance < 0 ) {
13174
13175 return this.origin.distanceToSquared( point );
13176
13177 }
13178
13179 v1.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );
13180
13181 return v1.distanceToSquared( point );
13182
13183 };
13184
13185 }(),
13186
13187 distanceSqToSegment: function () {
13188
13189 var segCenter = new Vector3();
13190 var segDir = new Vector3();
13191 var diff = new Vector3();
13192
13193 return function distanceSqToSegment( v0, v1, optionalPointOnRay, optionalPointOnSegment ) {
13194
13195 // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteDistRaySegment.h
13196 // It returns the min distance between the ray and the segment
13197 // defined by v0 and v1
13198 // It can also set two optional targets :
13199 // - The closest point on the ray
13200 // - The closest point on the segment
13201
13202 segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 );
13203 segDir.copy( v1 ).sub( v0 ).normalize();
13204 diff.copy( this.origin ).sub( segCenter );
13205
13206 var segExtent = v0.distanceTo( v1 ) * 0.5;
13207 var a01 = - this.direction.dot( segDir );
13208 var b0 = diff.dot( this.direction );
13209 var b1 = - diff.dot( segDir );
13210 var c = diff.lengthSq();
13211 var det = Math.abs( 1 - a01 * a01 );
13212 var s0, s1, sqrDist, extDet;
13213
13214 if ( det > 0 ) {
13215
13216 // The ray and segment are not parallel.
13217
13218 s0 = a01 * b1 - b0;
13219 s1 = a01 * b0 - b1;
13220 extDet = segExtent * det;
13221
13222 if ( s0 >= 0 ) {
13223
13224 if ( s1 >= - extDet ) {
13225
13226 if ( s1 <= extDet ) {
13227
13228 // region 0
13229 // Minimum at interior points of ray and segment.
13230
13231 var invDet = 1 / det;
13232 s0 *= invDet;
13233 s1 *= invDet;
13234 sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c;
13235
13236 } else {
13237
13238 // region 1
13239
13240 s1 = segExtent;
13241 s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
13242 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
13243
13244 }
13245
13246 } else {
13247
13248 // region 5
13249
13250 s1 = - segExtent;
13251 s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
13252 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
13253
13254 }
13255
13256 } else {
13257
13258 if ( s1 <= - extDet ) {
13259
13260 // region 4
13261
13262 s0 = Math.max( 0, - ( - a01 * segExtent + b0 ) );
13263 s1 = ( s0 > 0 ) ? - segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
13264 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
13265
13266 } else if ( s1 <= extDet ) {
13267
13268 // region 3
13269
13270 s0 = 0;
13271 s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent );
13272 sqrDist = s1 * ( s1 + 2 * b1 ) + c;
13273
13274 } else {
13275
13276 // region 2
13277
13278 s0 = Math.max( 0, - ( a01 * segExtent + b0 ) );
13279 s1 = ( s0 > 0 ) ? segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
13280 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
13281
13282 }
13283
13284 }
13285
13286 } else {
13287
13288 // Ray and segment are parallel.
13289
13290 s1 = ( a01 > 0 ) ? - segExtent : segExtent;
13291 s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
13292 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
13293
13294 }
13295
13296 if ( optionalPointOnRay ) {
13297
13298 optionalPointOnRay.copy( this.direction ).multiplyScalar( s0 ).add( this.origin );
13299
13300 }
13301
13302 if ( optionalPointOnSegment ) {
13303
13304 optionalPointOnSegment.copy( segDir ).multiplyScalar( s1 ).add( segCenter );
13305
13306 }
13307
13308 return sqrDist;
13309
13310 };
13311
13312 }(),
13313
13314 intersectSphere: function () {
13315
13316 var v1 = new Vector3();
13317
13318 return function intersectSphere( sphere, target ) {
13319
13320 v1.subVectors( sphere.center, this.origin );
13321 var tca = v1.dot( this.direction );
13322 var d2 = v1.dot( v1 ) - tca * tca;
13323 var radius2 = sphere.radius * sphere.radius;
13324
13325 if ( d2 > radius2 ) return null;
13326
13327 var thc = Math.sqrt( radius2 - d2 );
13328
13329 // t0 = first intersect point - entrance on front of sphere
13330 var t0 = tca - thc;
13331
13332 // t1 = second intersect point - exit point on back of sphere
13333 var t1 = tca + thc;
13334
13335 // test to see if both t0 and t1 are behind the ray - if so, return null
13336 if ( t0 < 0 && t1 < 0 ) return null;
13337
13338 // test to see if t0 is behind the ray:
13339 // if it is, the ray is inside the sphere, so return the second exit point scaled by t1,
13340 // in order to always return an intersect point that is in front of the ray.
13341 if ( t0 < 0 ) return this.at( t1, target );
13342
13343 // else t0 is in front of the ray, so return the first collision point scaled by t0
13344 return this.at( t0, target );
13345
13346 };
13347
13348 }(),
13349
13350 intersectsSphere: function ( sphere ) {
13351
13352 return this.distanceToPoint( sphere.center ) <= sphere.radius;
13353
13354 },
13355
13356 distanceToPlane: function ( plane ) {
13357
13358 var denominator = plane.normal.dot( this.direction );
13359
13360 if ( denominator === 0 ) {
13361
13362 // line is coplanar, return origin
13363 if ( plane.distanceToPoint( this.origin ) === 0 ) {
13364
13365 return 0;
13366
13367 }
13368
13369 // Null is preferable to undefined since undefined means.... it is undefined
13370
13371 return null;
13372
13373 }
13374
13375 var t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator;
13376
13377 // Return if the ray never intersects the plane
13378
13379 return t >= 0 ? t : null;
13380
13381 },
13382
13383 intersectPlane: function ( plane, target ) {
13384
13385 var t = this.distanceToPlane( plane );
13386
13387 if ( t === null ) {
13388
13389 return null;
13390
13391 }
13392
13393 return this.at( t, target );
13394
13395 },
13396
13397 intersectsPlane: function ( plane ) {
13398
13399 // check if the ray lies on the plane first
13400
13401 var distToPoint = plane.distanceToPoint( this.origin );
13402
13403 if ( distToPoint === 0 ) {
13404
13405 return true;
13406
13407 }
13408
13409 var denominator = plane.normal.dot( this.direction );
13410
13411 if ( denominator * distToPoint < 0 ) {
13412
13413 return true;
13414
13415 }
13416
13417 // ray origin is behind the plane (and is pointing behind it)
13418
13419 return false;
13420
13421 },
13422
13423 intersectBox: function ( box, target ) {
13424
13425 var tmin, tmax, tymin, tymax, tzmin, tzmax;
13426
13427 var invdirx = 1 / this.direction.x,
13428 invdiry = 1 / this.direction.y,
13429 invdirz = 1 / this.direction.z;
13430
13431 var origin = this.origin;
13432
13433 if ( invdirx >= 0 ) {
13434
13435 tmin = ( box.min.x - origin.x ) * invdirx;
13436 tmax = ( box.max.x - origin.x ) * invdirx;
13437
13438 } else {
13439
13440 tmin = ( box.max.x - origin.x ) * invdirx;
13441 tmax = ( box.min.x - origin.x ) * invdirx;
13442
13443 }
13444
13445 if ( invdiry >= 0 ) {
13446
13447 tymin = ( box.min.y - origin.y ) * invdiry;
13448 tymax = ( box.max.y - origin.y ) * invdiry;
13449
13450 } else {
13451
13452 tymin = ( box.max.y - origin.y ) * invdiry;
13453 tymax = ( box.min.y - origin.y ) * invdiry;
13454
13455 }
13456
13457 if ( ( tmin > tymax ) || ( tymin > tmax ) ) return null;
13458
13459 // These lines also handle the case where tmin or tmax is NaN
13460 // (result of 0 * Infinity). x !== x returns true if x is NaN
13461
13462 if ( tymin > tmin || tmin !== tmin ) tmin = tymin;
13463
13464 if ( tymax < tmax || tmax !== tmax ) tmax = tymax;
13465
13466 if ( invdirz >= 0 ) {
13467
13468 tzmin = ( box.min.z - origin.z ) * invdirz;
13469 tzmax = ( box.max.z - origin.z ) * invdirz;
13470
13471 } else {
13472
13473 tzmin = ( box.max.z - origin.z ) * invdirz;
13474 tzmax = ( box.min.z - origin.z ) * invdirz;
13475
13476 }
13477
13478 if ( ( tmin > tzmax ) || ( tzmin > tmax ) ) return null;
13479
13480 if ( tzmin > tmin || tmin !== tmin ) tmin = tzmin;
13481
13482 if ( tzmax < tmax || tmax !== tmax ) tmax = tzmax;
13483
13484 //return point closest to the ray (positive side)
13485
13486 if ( tmax < 0 ) return null;
13487
13488 return this.at( tmin >= 0 ? tmin : tmax, target );
13489
13490 },
13491
13492 intersectsBox: ( function () {
13493
13494 var v = new Vector3();
13495
13496 return function intersectsBox( box ) {
13497
13498 return this.intersectBox( box, v ) !== null;
13499
13500 };
13501
13502 } )(),
13503
13504 intersectTriangle: function () {
13505
13506 // Compute the offset origin, edges, and normal.
13507 var diff = new Vector3();
13508 var edge1 = new Vector3();
13509 var edge2 = new Vector3();
13510 var normal = new Vector3();
13511
13512 return function intersectTriangle( a, b, c, backfaceCulling, target ) {
13513
13514 // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h
13515
13516 edge1.subVectors( b, a );
13517 edge2.subVectors( c, a );
13518 normal.crossVectors( edge1, edge2 );
13519
13520 // Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction,
13521 // E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by
13522 // |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2))
13523 // |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q))
13524 // |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N)
13525 var DdN = this.direction.dot( normal );
13526 var sign;
13527
13528 if ( DdN > 0 ) {
13529
13530 if ( backfaceCulling ) return null;
13531 sign = 1;
13532
13533 } else if ( DdN < 0 ) {
13534
13535 sign = - 1;
13536 DdN = - DdN;
13537
13538 } else {
13539
13540 return null;
13541
13542 }
13543
13544 diff.subVectors( this.origin, a );
13545 var DdQxE2 = sign * this.direction.dot( edge2.crossVectors( diff, edge2 ) );
13546
13547 // b1 < 0, no intersection
13548 if ( DdQxE2 < 0 ) {
13549
13550 return null;
13551
13552 }
13553
13554 var DdE1xQ = sign * this.direction.dot( edge1.cross( diff ) );
13555
13556 // b2 < 0, no intersection
13557 if ( DdE1xQ < 0 ) {
13558
13559 return null;
13560
13561 }
13562
13563 // b1+b2 > 1, no intersection
13564 if ( DdQxE2 + DdE1xQ > DdN ) {
13565
13566 return null;
13567
13568 }
13569
13570 // Line intersects triangle, check if ray does.
13571 var QdN = - sign * diff.dot( normal );
13572
13573 // t < 0, no intersection
13574 if ( QdN < 0 ) {
13575
13576 return null;
13577
13578 }
13579
13580 // Ray intersects triangle.
13581 return this.at( QdN / DdN, target );
13582
13583 };
13584
13585 }(),
13586
13587 applyMatrix4: function ( matrix4 ) {
13588
13589 this.origin.applyMatrix4( matrix4 );
13590 this.direction.transformDirection( matrix4 );
13591
13592 return this;
13593
13594 },
13595
13596 equals: function ( ray ) {
13597
13598 return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction );
13599
13600 }
13601
13602 } );
13603
13604 /**
13605 * @author bhouston / http://clara.io
13606 */
13607
13608 function Line3( start, end ) {
13609
13610 this.start = ( start !== undefined ) ? start : new Vector3();
13611 this.end = ( end !== undefined ) ? end : new Vector3();
13612
13613 }
13614
13615 Object.assign( Line3.prototype, {
13616
13617 set: function ( start, end ) {
13618
13619 this.start.copy( start );
13620 this.end.copy( end );
13621
13622 return this;
13623
13624 },
13625
13626 clone: function () {
13627
13628 return new this.constructor().copy( this );
13629
13630 },
13631
13632 copy: function ( line ) {
13633
13634 this.start.copy( line.start );
13635 this.end.copy( line.end );
13636
13637 return this;
13638
13639 },
13640
13641 getCenter: function ( target ) {
13642
13643 if ( target === undefined ) {
13644
13645 console.warn( 'THREE.Line3: .getCenter() target is now required' );
13646 target = new Vector3();
13647
13648 }
13649
13650 return target.addVectors( this.start, this.end ).multiplyScalar( 0.5 );
13651
13652 },
13653
13654 delta: function ( target ) {
13655
13656 if ( target === undefined ) {
13657
13658 console.warn( 'THREE.Line3: .delta() target is now required' );
13659 target = new Vector3();
13660
13661 }
13662
13663 return target.subVectors( this.end, this.start );
13664
13665 },
13666
13667 distanceSq: function () {
13668
13669 return this.start.distanceToSquared( this.end );
13670
13671 },
13672
13673 distance: function () {
13674
13675 return this.start.distanceTo( this.end );
13676
13677 },
13678
13679 at: function ( t, target ) {
13680
13681 if ( target === undefined ) {
13682
13683 console.warn( 'THREE.Line3: .at() target is now required' );
13684 target = new Vector3();
13685
13686 }
13687
13688 return this.delta( target ).multiplyScalar( t ).add( this.start );
13689
13690 },
13691
13692 closestPointToPointParameter: function () {
13693
13694 var startP = new Vector3();
13695 var startEnd = new Vector3();
13696
13697 return function closestPointToPointParameter( point, clampToLine ) {
13698
13699 startP.subVectors( point, this.start );
13700 startEnd.subVectors( this.end, this.start );
13701
13702 var startEnd2 = startEnd.dot( startEnd );
13703 var startEnd_startP = startEnd.dot( startP );
13704
13705 var t = startEnd_startP / startEnd2;
13706
13707 if ( clampToLine ) {
13708
13709 t = _Math.clamp( t, 0, 1 );
13710
13711 }
13712
13713 return t;
13714
13715 };
13716
13717 }(),
13718
13719 closestPointToPoint: function ( point, clampToLine, target ) {
13720
13721 var t = this.closestPointToPointParameter( point, clampToLine );
13722
13723 if ( target === undefined ) {
13724
13725 console.warn( 'THREE.Line3: .closestPointToPoint() target is now required' );
13726 target = new Vector3();
13727
13728 }
13729
13730 return this.delta( target ).multiplyScalar( t ).add( this.start );
13731
13732 },
13733
13734 applyMatrix4: function ( matrix ) {
13735
13736 this.start.applyMatrix4( matrix );
13737 this.end.applyMatrix4( matrix );
13738
13739 return this;
13740
13741 },
13742
13743 equals: function ( line ) {
13744
13745 return line.start.equals( this.start ) && line.end.equals( this.end );
13746
13747 }
13748
13749 } );
13750
13751 /**
13752 * @author bhouston / http://clara.io
13753 * @author mrdoob / http://mrdoob.com/
13754 */
13755
13756 function Triangle( a, b, c ) {
13757
13758 this.a = ( a !== undefined ) ? a : new Vector3();
13759 this.b = ( b !== undefined ) ? b : new Vector3();
13760 this.c = ( c !== undefined ) ? c : new Vector3();
13761
13762 }
13763
13764 Object.assign( Triangle, {
13765
13766 getNormal: function () {
13767
13768 var v0 = new Vector3();
13769
13770 return function getNormal( a, b, c, target ) {
13771
13772 if ( target === undefined ) {
13773
13774 console.warn( 'THREE.Triangle: .getNormal() target is now required' );
13775 target = new Vector3();
13776
13777 }
13778
13779 target.subVectors( c, b );
13780 v0.subVectors( a, b );
13781 target.cross( v0 );
13782
13783 var targetLengthSq = target.lengthSq();
13784 if ( targetLengthSq > 0 ) {
13785
13786 return target.multiplyScalar( 1 / Math.sqrt( targetLengthSq ) );
13787
13788 }
13789
13790 return target.set( 0, 0, 0 );
13791
13792 };
13793
13794 }(),
13795
13796 // static/instance method to calculate barycentric coordinates
13797 // based on: http://www.blackpawn.com/texts/pointinpoly/default.html
13798 getBarycoord: function () {
13799
13800 var v0 = new Vector3();
13801 var v1 = new Vector3();
13802 var v2 = new Vector3();
13803
13804 return function getBarycoord( point, a, b, c, target ) {
13805
13806 v0.subVectors( c, a );
13807 v1.subVectors( b, a );
13808 v2.subVectors( point, a );
13809
13810 var dot00 = v0.dot( v0 );
13811 var dot01 = v0.dot( v1 );
13812 var dot02 = v0.dot( v2 );
13813 var dot11 = v1.dot( v1 );
13814 var dot12 = v1.dot( v2 );
13815
13816 var denom = ( dot00 * dot11 - dot01 * dot01 );
13817
13818 if ( target === undefined ) {
13819
13820 console.warn( 'THREE.Triangle: .getBarycoord() target is now required' );
13821 target = new Vector3();
13822
13823 }
13824
13825 // collinear or singular triangle
13826 if ( denom === 0 ) {
13827
13828 // arbitrary location outside of triangle?
13829 // not sure if this is the best idea, maybe should be returning undefined
13830 return target.set( - 2, - 1, - 1 );
13831
13832 }
13833
13834 var invDenom = 1 / denom;
13835 var u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;
13836 var v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;
13837
13838 // barycentric coordinates must always sum to 1
13839 return target.set( 1 - u - v, v, u );
13840
13841 };
13842
13843 }(),
13844
13845 containsPoint: function () {
13846
13847 var v1 = new Vector3();
13848
13849 return function containsPoint( point, a, b, c ) {
13850
13851 Triangle.getBarycoord( point, a, b, c, v1 );
13852
13853 return ( v1.x >= 0 ) && ( v1.y >= 0 ) && ( ( v1.x + v1.y ) <= 1 );
13854
13855 };
13856
13857 }()
13858
13859 } );
13860
13861 Object.assign( Triangle.prototype, {
13862
13863 set: function ( a, b, c ) {
13864
13865 this.a.copy( a );
13866 this.b.copy( b );
13867 this.c.copy( c );
13868
13869 return this;
13870
13871 },
13872
13873 setFromPointsAndIndices: function ( points, i0, i1, i2 ) {
13874
13875 this.a.copy( points[ i0 ] );
13876 this.b.copy( points[ i1 ] );
13877 this.c.copy( points[ i2 ] );
13878
13879 return this;
13880
13881 },
13882
13883 clone: function () {
13884
13885 return new this.constructor().copy( this );
13886
13887 },
13888
13889 copy: function ( triangle ) {
13890
13891 this.a.copy( triangle.a );
13892 this.b.copy( triangle.b );
13893 this.c.copy( triangle.c );
13894
13895 return this;
13896
13897 },
13898
13899 getArea: function () {
13900
13901 var v0 = new Vector3();
13902 var v1 = new Vector3();
13903
13904 return function getArea() {
13905
13906 v0.subVectors( this.c, this.b );
13907 v1.subVectors( this.a, this.b );
13908
13909 return v0.cross( v1 ).length() * 0.5;
13910
13911 };
13912
13913 }(),
13914
13915 getMidpoint: function ( target ) {
13916
13917 if ( target === undefined ) {
13918
13919 console.warn( 'THREE.Triangle: .getMidpoint() target is now required' );
13920 target = new Vector3();
13921
13922 }
13923
13924 return target.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 );
13925
13926 },
13927
13928 getNormal: function ( target ) {
13929
13930 return Triangle.getNormal( this.a, this.b, this.c, target );
13931
13932 },
13933
13934 getPlane: function ( target ) {
13935
13936 if ( target === undefined ) {
13937
13938 console.warn( 'THREE.Triangle: .getPlane() target is now required' );
13939 target = new Vector3();
13940
13941 }
13942
13943 return target.setFromCoplanarPoints( this.a, this.b, this.c );
13944
13945 },
13946
13947 getBarycoord: function ( point, target ) {
13948
13949 return Triangle.getBarycoord( point, this.a, this.b, this.c, target );
13950
13951 },
13952
13953 containsPoint: function ( point ) {
13954
13955 return Triangle.containsPoint( point, this.a, this.b, this.c );
13956
13957 },
13958
13959 intersectsBox: function ( box ) {
13960
13961 return box.intersectsTriangle( this );
13962
13963 },
13964
13965 closestPointToPoint: function () {
13966
13967 var plane = new Plane();
13968 var edgeList = [ new Line3(), new Line3(), new Line3() ];
13969 var projectedPoint = new Vector3();
13970 var closestPoint = new Vector3();
13971
13972 return function closestPointToPoint( point, target ) {
13973
13974 if ( target === undefined ) {
13975
13976 console.warn( 'THREE.Triangle: .closestPointToPoint() target is now required' );
13977 target = new Vector3();
13978
13979 }
13980
13981 var minDistance = Infinity;
13982
13983 // project the point onto the plane of the triangle
13984
13985 plane.setFromCoplanarPoints( this.a, this.b, this.c );
13986 plane.projectPoint( point, projectedPoint );
13987
13988 // check if the projection lies within the triangle
13989
13990 if ( this.containsPoint( projectedPoint ) === true ) {
13991
13992 // if so, this is the closest point
13993
13994 target.copy( projectedPoint );
13995
13996 } else {
13997
13998 // if not, the point falls outside the triangle. the target is the closest point to the triangle's edges or vertices
13999
14000 edgeList[ 0 ].set( this.a, this.b );
14001 edgeList[ 1 ].set( this.b, this.c );
14002 edgeList[ 2 ].set( this.c, this.a );
14003
14004 for ( var i = 0; i < edgeList.length; i ++ ) {
14005
14006 edgeList[ i ].closestPointToPoint( projectedPoint, true, closestPoint );
14007
14008 var distance = projectedPoint.distanceToSquared( closestPoint );
14009
14010 if ( distance < minDistance ) {
14011
14012 minDistance = distance;
14013
14014 target.copy( closestPoint );
14015
14016 }
14017
14018 }
14019
14020 }
14021
14022 return target;
14023
14024 };
14025
14026 }(),
14027
14028 equals: function ( triangle ) {
14029
14030 return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c );
14031
14032 }
14033
14034 } );
14035
14036 /**
14037 * @author mrdoob / http://mrdoob.com/
14038 * @author alteredq / http://alteredqualia.com/
14039 * @author mikael emtinger / http://gomo.se/
14040 * @author jonobr1 / http://jonobr1.com/
14041 */
14042
14043 function Mesh( geometry, material ) {
14044
14045 Object3D.call( this );
14046
14047 this.type = 'Mesh';
14048
14049 this.geometry = geometry !== undefined ? geometry : new BufferGeometry();
14050 this.material = material !== undefined ? material : new MeshBasicMaterial( { color: Math.random() * 0xffffff } );
14051
14052 this.drawMode = TrianglesDrawMode;
14053
14054 this.updateMorphTargets();
14055
14056 }
14057
14058 Mesh.prototype = Object.assign( Object.create( Object3D.prototype ), {
14059
14060 constructor: Mesh,
14061
14062 isMesh: true,
14063
14064 setDrawMode: function ( value ) {
14065
14066 this.drawMode = value;
14067
14068 },
14069
14070 copy: function ( source ) {
14071
14072 Object3D.prototype.copy.call( this, source );
14073
14074 this.drawMode = source.drawMode;
14075
14076 if ( source.morphTargetInfluences !== undefined ) {
14077
14078 this.morphTargetInfluences = source.morphTargetInfluences.slice();
14079
14080 }
14081
14082 if ( source.morphTargetDictionary !== undefined ) {
14083
14084 this.morphTargetDictionary = Object.assign( {}, source.morphTargetDictionary );
14085
14086 }
14087
14088 return this;
14089
14090 },
14091
14092 updateMorphTargets: function () {
14093
14094 var geometry = this.geometry;
14095 var m, ml, name;
14096
14097 if ( geometry.isBufferGeometry ) {
14098
14099 var morphAttributes = geometry.morphAttributes;
14100 var keys = Object.keys( morphAttributes );
14101
14102 if ( keys.length > 0 ) {
14103
14104 var morphAttribute = morphAttributes[ keys[ 0 ] ];
14105
14106 if ( morphAttribute !== undefined ) {
14107
14108 this.morphTargetInfluences = [];
14109 this.morphTargetDictionary = {};
14110
14111 for ( m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
14112
14113 name = morphAttribute[ m ].name || String( m );
14114
14115 this.morphTargetInfluences.push( 0 );
14116 this.morphTargetDictionary[ name ] = m;
14117
14118 }
14119
14120 }
14121
14122 }
14123
14124 } else {
14125
14126 var morphTargets = geometry.morphTargets;
14127
14128 if ( morphTargets !== undefined && morphTargets.length > 0 ) {
14129
14130 this.morphTargetInfluences = [];
14131 this.morphTargetDictionary = {};
14132
14133 for ( m = 0, ml = morphTargets.length; m < ml; m ++ ) {
14134
14135 name = morphTargets[ m ].name || String( m );
14136
14137 this.morphTargetInfluences.push( 0 );
14138 this.morphTargetDictionary[ name ] = m;
14139
14140 }
14141
14142 }
14143
14144 }
14145
14146 },
14147
14148 raycast: ( function () {
14149
14150 var inverseMatrix = new Matrix4();
14151 var ray = new Ray();
14152 var sphere = new Sphere();
14153
14154 var vA = new Vector3();
14155 var vB = new Vector3();
14156 var vC = new Vector3();
14157
14158 var tempA = new Vector3();
14159 var tempB = new Vector3();
14160 var tempC = new Vector3();
14161
14162 var uvA = new Vector2();
14163 var uvB = new Vector2();
14164 var uvC = new Vector2();
14165
14166 var barycoord = new Vector3();
14167
14168 var intersectionPoint = new Vector3();
14169 var intersectionPointWorld = new Vector3();
14170
14171 function uvIntersection( point, p1, p2, p3, uv1, uv2, uv3 ) {
14172
14173 Triangle.getBarycoord( point, p1, p2, p3, barycoord );
14174
14175 uv1.multiplyScalar( barycoord.x );
14176 uv2.multiplyScalar( barycoord.y );
14177 uv3.multiplyScalar( barycoord.z );
14178
14179 uv1.add( uv2 ).add( uv3 );
14180
14181 return uv1.clone();
14182
14183 }
14184
14185 function checkIntersection( object, material, raycaster, ray, pA, pB, pC, point ) {
14186
14187 var intersect;
14188
14189 if ( material.side === BackSide ) {
14190
14191 intersect = ray.intersectTriangle( pC, pB, pA, true, point );
14192
14193 } else {
14194
14195 intersect = ray.intersectTriangle( pA, pB, pC, material.side !== DoubleSide, point );
14196
14197 }
14198
14199 if ( intersect === null ) return null;
14200
14201 intersectionPointWorld.copy( point );
14202 intersectionPointWorld.applyMatrix4( object.matrixWorld );
14203
14204 var distance = raycaster.ray.origin.distanceTo( intersectionPointWorld );
14205
14206 if ( distance < raycaster.near || distance > raycaster.far ) return null;
14207
14208 return {
14209 distance: distance,
14210 point: intersectionPointWorld.clone(),
14211 object: object
14212 };
14213
14214 }
14215
14216 function checkBufferGeometryIntersection( object, raycaster, ray, position, uv, a, b, c ) {
14217
14218 vA.fromBufferAttribute( position, a );
14219 vB.fromBufferAttribute( position, b );
14220 vC.fromBufferAttribute( position, c );
14221
14222 var intersection = checkIntersection( object, object.material, raycaster, ray, vA, vB, vC, intersectionPoint );
14223
14224 if ( intersection ) {
14225
14226 if ( uv ) {
14227
14228 uvA.fromBufferAttribute( uv, a );
14229 uvB.fromBufferAttribute( uv, b );
14230 uvC.fromBufferAttribute( uv, c );
14231
14232 intersection.uv = uvIntersection( intersectionPoint, vA, vB, vC, uvA, uvB, uvC );
14233
14234 }
14235
14236 var face = new Face3( a, b, c );
14237 Triangle.getNormal( vA, vB, vC, face.normal );
14238
14239 intersection.face = face;
14240 intersection.faceIndex = a;
14241
14242 }
14243
14244 return intersection;
14245
14246 }
14247
14248 return function raycast( raycaster, intersects ) {
14249
14250 var geometry = this.geometry;
14251 var material = this.material;
14252 var matrixWorld = this.matrixWorld;
14253
14254 if ( material === undefined ) return;
14255
14256 // Checking boundingSphere distance to ray
14257
14258 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
14259
14260 sphere.copy( geometry.boundingSphere );
14261 sphere.applyMatrix4( matrixWorld );
14262
14263 if ( raycaster.ray.intersectsSphere( sphere ) === false ) return;
14264
14265 //
14266
14267 inverseMatrix.getInverse( matrixWorld );
14268 ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix );
14269
14270 // Check boundingBox before continuing
14271
14272 if ( geometry.boundingBox !== null ) {
14273
14274 if ( ray.intersectsBox( geometry.boundingBox ) === false ) return;
14275
14276 }
14277
14278 var intersection;
14279
14280 if ( geometry.isBufferGeometry ) {
14281
14282 var a, b, c;
14283 var index = geometry.index;
14284 var position = geometry.attributes.position;
14285 var uv = geometry.attributes.uv;
14286 var i, l;
14287
14288 if ( index !== null ) {
14289
14290 // indexed buffer geometry
14291
14292 for ( i = 0, l = index.count; i < l; i += 3 ) {
14293
14294 a = index.getX( i );
14295 b = index.getX( i + 1 );
14296 c = index.getX( i + 2 );
14297
14298 intersection = checkBufferGeometryIntersection( this, raycaster, ray, position, uv, a, b, c );
14299
14300 if ( intersection ) {
14301
14302 intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indices buffer semantics
14303 intersects.push( intersection );
14304
14305 }
14306
14307 }
14308
14309 } else if ( position !== undefined ) {
14310
14311 // non-indexed buffer geometry
14312
14313 for ( i = 0, l = position.count; i < l; i += 3 ) {
14314
14315 a = i;
14316 b = i + 1;
14317 c = i + 2;
14318
14319 intersection = checkBufferGeometryIntersection( this, raycaster, ray, position, uv, a, b, c );
14320
14321 if ( intersection ) intersects.push( intersection );
14322
14323 }
14324
14325 }
14326
14327 } else if ( geometry.isGeometry ) {
14328
14329 var fvA, fvB, fvC;
14330 var isMultiMaterial = Array.isArray( material );
14331
14332 var vertices = geometry.vertices;
14333 var faces = geometry.faces;
14334 var uvs;
14335
14336 var faceVertexUvs = geometry.faceVertexUvs[ 0 ];
14337 if ( faceVertexUvs.length > 0 ) uvs = faceVertexUvs;
14338
14339 for ( var f = 0, fl = faces.length; f < fl; f ++ ) {
14340
14341 var face = faces[ f ];
14342 var faceMaterial = isMultiMaterial ? material[ face.materialIndex ] : material;
14343
14344 if ( faceMaterial === undefined ) continue;
14345
14346 fvA = vertices[ face.a ];
14347 fvB = vertices[ face.b ];
14348 fvC = vertices[ face.c ];
14349
14350 if ( faceMaterial.morphTargets === true ) {
14351
14352 var morphTargets = geometry.morphTargets;
14353 var morphInfluences = this.morphTargetInfluences;
14354
14355 vA.set( 0, 0, 0 );
14356 vB.set( 0, 0, 0 );
14357 vC.set( 0, 0, 0 );
14358
14359 for ( var t = 0, tl = morphTargets.length; t < tl; t ++ ) {
14360
14361 var influence = morphInfluences[ t ];
14362
14363 if ( influence === 0 ) continue;
14364
14365 var targets = morphTargets[ t ].vertices;
14366
14367 vA.addScaledVector( tempA.subVectors( targets[ face.a ], fvA ), influence );
14368 vB.addScaledVector( tempB.subVectors( targets[ face.b ], fvB ), influence );
14369 vC.addScaledVector( tempC.subVectors( targets[ face.c ], fvC ), influence );
14370
14371 }
14372
14373 vA.add( fvA );
14374 vB.add( fvB );
14375 vC.add( fvC );
14376
14377 fvA = vA;
14378 fvB = vB;
14379 fvC = vC;
14380
14381 }
14382
14383 intersection = checkIntersection( this, faceMaterial, raycaster, ray, fvA, fvB, fvC, intersectionPoint );
14384
14385 if ( intersection ) {
14386
14387 if ( uvs && uvs[ f ] ) {
14388
14389 var uvs_f = uvs[ f ];
14390 uvA.copy( uvs_f[ 0 ] );
14391 uvB.copy( uvs_f[ 1 ] );
14392 uvC.copy( uvs_f[ 2 ] );
14393
14394 intersection.uv = uvIntersection( intersectionPoint, fvA, fvB, fvC, uvA, uvB, uvC );
14395
14396 }
14397
14398 intersection.face = face;
14399 intersection.faceIndex = f;
14400 intersects.push( intersection );
14401
14402 }
14403
14404 }
14405
14406 }
14407
14408 };
14409
14410 }() ),
14411
14412 clone: function () {
14413
14414 return new this.constructor( this.geometry, this.material ).copy( this );
14415
14416 }
14417
14418 } );
14419
14420 /**
14421 * @author mrdoob / http://mrdoob.com/
14422 */
14423
14424 function WebGLBackground( renderer, state, geometries, premultipliedAlpha ) {
14425
14426 var clearColor = new Color( 0x000000 );
14427 var clearAlpha = 0;
14428
14429 var planeCamera, planeMesh;
14430 var boxMesh;
14431
14432 function render( renderList, scene, camera, forceClear ) {
14433
14434 var background = scene.background;
14435
14436 if ( background === null ) {
14437
14438 setClear( clearColor, clearAlpha );
14439
14440 } else if ( background && background.isColor ) {
14441
14442 setClear( background, 1 );
14443 forceClear = true;
14444
14445 }
14446
14447 if ( renderer.autoClear || forceClear ) {
14448
14449 renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil );
14450
14451 }
14452
14453 if ( background && background.isCubeTexture ) {
14454
14455 if ( boxMesh === undefined ) {
14456
14457 boxMesh = new Mesh(
14458 new BoxBufferGeometry( 1, 1, 1 ),
14459 new ShaderMaterial( {
14460 uniforms: ShaderLib.cube.uniforms,
14461 vertexShader: ShaderLib.cube.vertexShader,
14462 fragmentShader: ShaderLib.cube.fragmentShader,
14463 side: BackSide,
14464 depthTest: true,
14465 depthWrite: false,
14466 fog: false
14467 } )
14468 );
14469
14470 boxMesh.geometry.removeAttribute( 'normal' );
14471 boxMesh.geometry.removeAttribute( 'uv' );
14472
14473 boxMesh.onBeforeRender = function ( renderer, scene, camera ) {
14474
14475 this.matrixWorld.copyPosition( camera.matrixWorld );
14476
14477 };
14478
14479 geometries.update( boxMesh.geometry );
14480
14481 }
14482
14483 boxMesh.material.uniforms.tCube.value = background;
14484
14485 renderList.push( boxMesh, boxMesh.geometry, boxMesh.material, 0, null );
14486
14487 } else if ( background && background.isTexture ) {
14488
14489 if ( planeCamera === undefined ) {
14490
14491 planeCamera = new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );
14492
14493 planeMesh = new Mesh(
14494 new PlaneBufferGeometry( 2, 2 ),
14495 new MeshBasicMaterial( { depthTest: false, depthWrite: false, fog: false } )
14496 );
14497
14498 geometries.update( planeMesh.geometry );
14499
14500 }
14501
14502 planeMesh.material.map = background;
14503
14504 // TODO Push this to renderList
14505
14506 renderer.renderBufferDirect( planeCamera, null, planeMesh.geometry, planeMesh.material, planeMesh, null );
14507
14508 }
14509
14510 }
14511
14512 function setClear( color, alpha ) {
14513
14514 state.buffers.color.setClear( color.r, color.g, color.b, alpha, premultipliedAlpha );
14515
14516 }
14517
14518 return {
14519
14520 getClearColor: function () {
14521
14522 return clearColor;
14523
14524 },
14525 setClearColor: function ( color, alpha ) {
14526
14527 clearColor.set( color );
14528 clearAlpha = alpha !== undefined ? alpha : 1;
14529 setClear( clearColor, clearAlpha );
14530
14531 },
14532 getClearAlpha: function () {
14533
14534 return clearAlpha;
14535
14536 },
14537 setClearAlpha: function ( alpha ) {
14538
14539 clearAlpha = alpha;
14540 setClear( clearColor, clearAlpha );
14541
14542 },
14543 render: render
14544
14545 };
14546
14547 }
14548
14549 /**
14550 * @author mrdoob / http://mrdoob.com/
14551 */
14552
14553 function WebGLBufferRenderer( gl, extensions, info ) {
14554
14555 var mode;
14556
14557 function setMode( value ) {
14558
14559 mode = value;
14560
14561 }
14562
14563 function render( start, count ) {
14564
14565 gl.drawArrays( mode, start, count );
14566
14567 info.update( count, mode );
14568
14569 }
14570
14571 function renderInstances( geometry, start, count ) {
14572
14573 var extension = extensions.get( 'ANGLE_instanced_arrays' );
14574
14575 if ( extension === null ) {
14576
14577 console.error( 'THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
14578 return;
14579
14580 }
14581
14582 var position = geometry.attributes.position;
14583
14584 if ( position.isInterleavedBufferAttribute ) {
14585
14586 count = position.data.count;
14587
14588 extension.drawArraysInstancedANGLE( mode, 0, count, geometry.maxInstancedCount );
14589
14590 } else {
14591
14592 extension.drawArraysInstancedANGLE( mode, start, count, geometry.maxInstancedCount );
14593
14594 }
14595
14596 info.update( count, mode, geometry.maxInstancedCount );
14597
14598 }
14599
14600 //
14601
14602 this.setMode = setMode;
14603 this.render = render;
14604 this.renderInstances = renderInstances;
14605
14606 }
14607
14608 /**
14609 * @author mrdoob / http://mrdoob.com/
14610 */
14611
14612 function WebGLCapabilities( gl, extensions, parameters ) {
14613
14614 var maxAnisotropy;
14615
14616 function getMaxAnisotropy() {
14617
14618 if ( maxAnisotropy !== undefined ) return maxAnisotropy;
14619
14620 var extension = extensions.get( 'EXT_texture_filter_anisotropic' );
14621
14622 if ( extension !== null ) {
14623
14624 maxAnisotropy = gl.getParameter( extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT );
14625
14626 } else {
14627
14628 maxAnisotropy = 0;
14629
14630 }
14631
14632 return maxAnisotropy;
14633
14634 }
14635
14636 function getMaxPrecision( precision ) {
14637
14638 if ( precision === 'highp' ) {
14639
14640 if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.HIGH_FLOAT ).precision > 0 &&
14641 gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.HIGH_FLOAT ).precision > 0 ) {
14642
14643 return 'highp';
14644
14645 }
14646
14647 precision = 'mediump';
14648
14649 }
14650
14651 if ( precision === 'mediump' ) {
14652
14653 if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.MEDIUM_FLOAT ).precision > 0 &&
14654 gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT ).precision > 0 ) {
14655
14656 return 'mediump';
14657
14658 }
14659
14660 }
14661
14662 return 'lowp';
14663
14664 }
14665
14666 var precision = parameters.precision !== undefined ? parameters.precision : 'highp';
14667 var maxPrecision = getMaxPrecision( precision );
14668
14669 if ( maxPrecision !== precision ) {
14670
14671 console.warn( 'THREE.WebGLRenderer:', precision, 'not supported, using', maxPrecision, 'instead.' );
14672 precision = maxPrecision;
14673
14674 }
14675
14676 var logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true;
14677
14678 var maxTextures = gl.getParameter( gl.MAX_TEXTURE_IMAGE_UNITS );
14679 var maxVertexTextures = gl.getParameter( gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS );
14680 var maxTextureSize = gl.getParameter( gl.MAX_TEXTURE_SIZE );
14681 var maxCubemapSize = gl.getParameter( gl.MAX_CUBE_MAP_TEXTURE_SIZE );
14682
14683 var maxAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS );
14684 var maxVertexUniforms = gl.getParameter( gl.MAX_VERTEX_UNIFORM_VECTORS );
14685 var maxVaryings = gl.getParameter( gl.MAX_VARYING_VECTORS );
14686 var maxFragmentUniforms = gl.getParameter( gl.MAX_FRAGMENT_UNIFORM_VECTORS );
14687
14688 var vertexTextures = maxVertexTextures > 0;
14689 var floatFragmentTextures = !! extensions.get( 'OES_texture_float' );
14690 var floatVertexTextures = vertexTextures && floatFragmentTextures;
14691
14692 return {
14693
14694 getMaxAnisotropy: getMaxAnisotropy,
14695 getMaxPrecision: getMaxPrecision,
14696
14697 precision: precision,
14698 logarithmicDepthBuffer: logarithmicDepthBuffer,
14699
14700 maxTextures: maxTextures,
14701 maxVertexTextures: maxVertexTextures,
14702 maxTextureSize: maxTextureSize,
14703 maxCubemapSize: maxCubemapSize,
14704
14705 maxAttributes: maxAttributes,
14706 maxVertexUniforms: maxVertexUniforms,
14707 maxVaryings: maxVaryings,
14708 maxFragmentUniforms: maxFragmentUniforms,
14709
14710 vertexTextures: vertexTextures,
14711 floatFragmentTextures: floatFragmentTextures,
14712 floatVertexTextures: floatVertexTextures
14713
14714 };
14715
14716 }
14717
14718 /**
14719 * @author tschw
14720 */
14721
14722 function WebGLClipping() {
14723
14724 var scope = this,
14725
14726 globalState = null,
14727 numGlobalPlanes = 0,
14728 localClippingEnabled = false,
14729 renderingShadows = false,
14730
14731 plane = new Plane(),
14732 viewNormalMatrix = new Matrix3(),
14733
14734 uniform = { value: null, needsUpdate: false };
14735
14736 this.uniform = uniform;
14737 this.numPlanes = 0;
14738 this.numIntersection = 0;
14739
14740 this.init = function ( planes, enableLocalClipping, camera ) {
14741
14742 var enabled =
14743 planes.length !== 0 ||
14744 enableLocalClipping ||
14745 // enable state of previous frame - the clipping code has to
14746 // run another frame in order to reset the state:
14747 numGlobalPlanes !== 0 ||
14748 localClippingEnabled;
14749
14750 localClippingEnabled = enableLocalClipping;
14751
14752 globalState = projectPlanes( planes, camera, 0 );
14753 numGlobalPlanes = planes.length;
14754
14755 return enabled;
14756
14757 };
14758
14759 this.beginShadows = function () {
14760
14761 renderingShadows = true;
14762 projectPlanes( null );
14763
14764 };
14765
14766 this.endShadows = function () {
14767
14768 renderingShadows = false;
14769 resetGlobalState();
14770
14771 };
14772
14773 this.setState = function ( planes, clipIntersection, clipShadows, camera, cache, fromCache ) {
14774
14775 if ( ! localClippingEnabled || planes === null || planes.length === 0 || renderingShadows && ! clipShadows ) {
14776
14777 // there's no local clipping
14778
14779 if ( renderingShadows ) {
14780
14781 // there's no global clipping
14782
14783 projectPlanes( null );
14784
14785 } else {
14786
14787 resetGlobalState();
14788
14789 }
14790
14791 } else {
14792
14793 var nGlobal = renderingShadows ? 0 : numGlobalPlanes,
14794 lGlobal = nGlobal * 4,
14795
14796 dstArray = cache.clippingState || null;
14797
14798 uniform.value = dstArray; // ensure unique state
14799
14800 dstArray = projectPlanes( planes, camera, lGlobal, fromCache );
14801
14802 for ( var i = 0; i !== lGlobal; ++ i ) {
14803
14804 dstArray[ i ] = globalState[ i ];
14805
14806 }
14807
14808 cache.clippingState = dstArray;
14809 this.numIntersection = clipIntersection ? this.numPlanes : 0;
14810 this.numPlanes += nGlobal;
14811
14812 }
14813
14814
14815 };
14816
14817 function resetGlobalState() {
14818
14819 if ( uniform.value !== globalState ) {
14820
14821 uniform.value = globalState;
14822 uniform.needsUpdate = numGlobalPlanes > 0;
14823
14824 }
14825
14826 scope.numPlanes = numGlobalPlanes;
14827 scope.numIntersection = 0;
14828
14829 }
14830
14831 function projectPlanes( planes, camera, dstOffset, skipTransform ) {
14832
14833 var nPlanes = planes !== null ? planes.length : 0,
14834 dstArray = null;
14835
14836 if ( nPlanes !== 0 ) {
14837
14838 dstArray = uniform.value;
14839
14840 if ( skipTransform !== true || dstArray === null ) {
14841
14842 var flatSize = dstOffset + nPlanes * 4,
14843 viewMatrix = camera.matrixWorldInverse;
14844
14845 viewNormalMatrix.getNormalMatrix( viewMatrix );
14846
14847 if ( dstArray === null || dstArray.length < flatSize ) {
14848
14849 dstArray = new Float32Array( flatSize );
14850
14851 }
14852
14853 for ( var i = 0, i4 = dstOffset; i !== nPlanes; ++ i, i4 += 4 ) {
14854
14855 plane.copy( planes[ i ] ).applyMatrix4( viewMatrix, viewNormalMatrix );
14856
14857 plane.normal.toArray( dstArray, i4 );
14858 dstArray[ i4 + 3 ] = plane.constant;
14859
14860 }
14861
14862 }
14863
14864 uniform.value = dstArray;
14865 uniform.needsUpdate = true;
14866
14867 }
14868
14869 scope.numPlanes = nPlanes;
14870
14871 return dstArray;
14872
14873 }
14874
14875 }
14876
14877 /**
14878 * @author mrdoob / http://mrdoob.com/
14879 */
14880
14881 function WebGLExtensions( gl ) {
14882
14883 var extensions = {};
14884
14885 return {
14886
14887 get: function ( name ) {
14888
14889 if ( extensions[ name ] !== undefined ) {
14890
14891 return extensions[ name ];
14892
14893 }
14894
14895 var extension;
14896
14897 switch ( name ) {
14898
14899 case 'WEBGL_depth_texture':
14900 extension = gl.getExtension( 'WEBGL_depth_texture' ) || gl.getExtension( 'MOZ_WEBGL_depth_texture' ) || gl.getExtension( 'WEBKIT_WEBGL_depth_texture' );
14901 break;
14902
14903 case 'EXT_texture_filter_anisotropic':
14904 extension = gl.getExtension( 'EXT_texture_filter_anisotropic' ) || gl.getExtension( 'MOZ_EXT_texture_filter_anisotropic' ) || gl.getExtension( 'WEBKIT_EXT_texture_filter_anisotropic' );
14905 break;
14906
14907 case 'WEBGL_compressed_texture_s3tc':
14908 extension = gl.getExtension( 'WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'MOZ_WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_s3tc' );
14909 break;
14910
14911 case 'WEBGL_compressed_texture_pvrtc':
14912 extension = gl.getExtension( 'WEBGL_compressed_texture_pvrtc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_pvrtc' );
14913 break;
14914
14915 default:
14916 extension = gl.getExtension( name );
14917
14918 }
14919
14920 if ( extension === null ) {
14921
14922 console.warn( 'THREE.WebGLRenderer: ' + name + ' extension not supported.' );
14923
14924 }
14925
14926 extensions[ name ] = extension;
14927
14928 return extension;
14929
14930 }
14931
14932 };
14933
14934 }
14935
14936 /**
14937 * @author mrdoob / http://mrdoob.com/
14938 */
14939
14940 function WebGLGeometries( gl, attributes, info ) {
14941
14942 var geometries = {};
14943 var wireframeAttributes = {};
14944
14945 function onGeometryDispose( event ) {
14946
14947 var geometry = event.target;
14948 var buffergeometry = geometries[ geometry.id ];
14949
14950 if ( buffergeometry.index !== null ) {
14951
14952 attributes.remove( buffergeometry.index );
14953
14954 }
14955
14956 for ( var name in buffergeometry.attributes ) {
14957
14958 attributes.remove( buffergeometry.attributes[ name ] );
14959
14960 }
14961
14962 geometry.removeEventListener( 'dispose', onGeometryDispose );
14963
14964 delete geometries[ geometry.id ];
14965
14966 // TODO Remove duplicate code
14967
14968 var attribute = wireframeAttributes[ geometry.id ];
14969
14970 if ( attribute ) {
14971
14972 attributes.remove( attribute );
14973 delete wireframeAttributes[ geometry.id ];
14974
14975 }
14976
14977 attribute = wireframeAttributes[ buffergeometry.id ];
14978
14979 if ( attribute ) {
14980
14981 attributes.remove( attribute );
14982 delete wireframeAttributes[ buffergeometry.id ];
14983
14984 }
14985
14986 //
14987
14988 info.memory.geometries --;
14989
14990 }
14991
14992 function get( object, geometry ) {
14993
14994 var buffergeometry = geometries[ geometry.id ];
14995
14996 if ( buffergeometry ) return buffergeometry;
14997
14998 geometry.addEventListener( 'dispose', onGeometryDispose );
14999
15000 if ( geometry.isBufferGeometry ) {
15001
15002 buffergeometry = geometry;
15003
15004 } else if ( geometry.isGeometry ) {
15005
15006 if ( geometry._bufferGeometry === undefined ) {
15007
15008 geometry._bufferGeometry = new BufferGeometry().setFromObject( object );
15009
15010 }
15011
15012 buffergeometry = geometry._bufferGeometry;
15013
15014 }
15015
15016 geometries[ geometry.id ] = buffergeometry;
15017
15018 info.memory.geometries ++;
15019
15020 return buffergeometry;
15021
15022 }
15023
15024 function update( geometry ) {
15025
15026 var index = geometry.index;
15027 var geometryAttributes = geometry.attributes;
15028
15029 if ( index !== null ) {
15030
15031 attributes.update( index, gl.ELEMENT_ARRAY_BUFFER );
15032
15033 }
15034
15035 for ( var name in geometryAttributes ) {
15036
15037 attributes.update( geometryAttributes[ name ], gl.ARRAY_BUFFER );
15038
15039 }
15040
15041 // morph targets
15042
15043 var morphAttributes = geometry.morphAttributes;
15044
15045 for ( var name in morphAttributes ) {
15046
15047 var array = morphAttributes[ name ];
15048
15049 for ( var i = 0, l = array.length; i < l; i ++ ) {
15050
15051 attributes.update( array[ i ], gl.ARRAY_BUFFER );
15052
15053 }
15054
15055 }
15056
15057 }
15058
15059 function getWireframeAttribute( geometry ) {
15060
15061 var attribute = wireframeAttributes[ geometry.id ];
15062
15063 if ( attribute ) return attribute;
15064
15065 var indices = [];
15066
15067 var geometryIndex = geometry.index;
15068 var geometryAttributes = geometry.attributes;
15069
15070 // console.time( 'wireframe' );
15071
15072 if ( geometryIndex !== null ) {
15073
15074 var array = geometryIndex.array;
15075
15076 for ( var i = 0, l = array.length; i < l; i += 3 ) {
15077
15078 var a = array[ i + 0 ];
15079 var b = array[ i + 1 ];
15080 var c = array[ i + 2 ];
15081
15082 indices.push( a, b, b, c, c, a );
15083
15084 }
15085
15086 } else {
15087
15088 var array = geometryAttributes.position.array;
15089
15090 for ( var i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) {
15091
15092 var a = i + 0;
15093 var b = i + 1;
15094 var c = i + 2;
15095
15096 indices.push( a, b, b, c, c, a );
15097
15098 }
15099
15100 }
15101
15102 // console.timeEnd( 'wireframe' );
15103
15104 attribute = new ( arrayMax( indices ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 );
15105
15106 attributes.update( attribute, gl.ELEMENT_ARRAY_BUFFER );
15107
15108 wireframeAttributes[ geometry.id ] = attribute;
15109
15110 return attribute;
15111
15112 }
15113
15114 return {
15115
15116 get: get,
15117 update: update,
15118
15119 getWireframeAttribute: getWireframeAttribute
15120
15121 };
15122
15123 }
15124
15125 /**
15126 * @author mrdoob / http://mrdoob.com/
15127 */
15128
15129 function WebGLIndexedBufferRenderer( gl, extensions, info ) {
15130
15131 var mode;
15132
15133 function setMode( value ) {
15134
15135 mode = value;
15136
15137 }
15138
15139 var type, bytesPerElement;
15140
15141 function setIndex( value ) {
15142
15143 type = value.type;
15144 bytesPerElement = value.bytesPerElement;
15145
15146 }
15147
15148 function render( start, count ) {
15149
15150 gl.drawElements( mode, count, type, start * bytesPerElement );
15151
15152 info.update( count, mode );
15153
15154 }
15155
15156 function renderInstances( geometry, start, count ) {
15157
15158 var extension = extensions.get( 'ANGLE_instanced_arrays' );
15159
15160 if ( extension === null ) {
15161
15162 console.error( 'THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
15163 return;
15164
15165 }
15166
15167 extension.drawElementsInstancedANGLE( mode, count, type, start * bytesPerElement, geometry.maxInstancedCount );
15168
15169 info.update( count, mode, geometry.maxInstancedCount );
15170
15171 }
15172
15173 //
15174
15175 this.setMode = setMode;
15176 this.setIndex = setIndex;
15177 this.render = render;
15178 this.renderInstances = renderInstances;
15179
15180 }
15181
15182 /**
15183 * @author Mugen87 / https://github.com/Mugen87
15184 */
15185
15186 function WebGLInfo( gl ) {
15187
15188 var memory = {
15189 geometries: 0,
15190 textures: 0
15191 };
15192
15193 var render = {
15194 frame: 0,
15195 calls: 0,
15196 triangles: 0,
15197 points: 0,
15198 lines: 0
15199 };
15200
15201 function update( count, mode, instanceCount ) {
15202
15203 instanceCount = instanceCount || 1;
15204
15205 render.calls ++;
15206
15207 switch ( mode ) {
15208
15209 case gl.TRIANGLES:
15210 render.triangles += instanceCount * ( count / 3 );
15211 break;
15212
15213 case gl.TRIANGLE_STRIP:
15214 case gl.TRIANGLE_FAN:
15215 render.triangles += instanceCount * ( count - 2 );
15216 break;
15217
15218 case gl.LINES:
15219 render.lines += instanceCount * ( count / 2 );
15220 break;
15221
15222 case gl.LINE_STRIP:
15223 render.lines += instanceCount * ( count - 1 );
15224 break;
15225
15226 case gl.LINE_LOOP:
15227 render.lines += instanceCount * count;
15228 break;
15229
15230 case gl.POINTS:
15231 render.points += instanceCount * count;
15232 break;
15233
15234 default:
15235 console.error( 'THREE.WebGLInfo: Unknown draw mode:', mode );
15236 break;
15237
15238 }
15239
15240 }
15241
15242 function reset() {
15243
15244 render.frame ++;
15245 render.calls = 0;
15246 render.triangles = 0;
15247 render.points = 0;
15248 render.lines = 0;
15249
15250 }
15251
15252 return {
15253 memory: memory,
15254 render: render,
15255 programs: null,
15256 autoReset: true,
15257 reset: reset,
15258 update: update
15259 };
15260
15261 }
15262
15263 /**
15264 * @author mrdoob / http://mrdoob.com/
15265 */
15266
15267 function absNumericalSort( a, b ) {
15268
15269 return Math.abs( b[ 1 ] ) - Math.abs( a[ 1 ] );
15270
15271 }
15272
15273 function WebGLMorphtargets( gl ) {
15274
15275 var influencesList = {};
15276 var morphInfluences = new Float32Array( 8 );
15277
15278 function update( object, geometry, material, program ) {
15279
15280 var objectInfluences = object.morphTargetInfluences;
15281
15282 var length = objectInfluences.length;
15283
15284 var influences = influencesList[ geometry.id ];
15285
15286 if ( influences === undefined ) {
15287
15288 // initialise list
15289
15290 influences = [];
15291
15292 for ( var i = 0; i < length; i ++ ) {
15293
15294 influences[ i ] = [ i, 0 ];
15295
15296 }
15297
15298 influencesList[ geometry.id ] = influences;
15299
15300 }
15301
15302 var morphTargets = material.morphTargets && geometry.morphAttributes.position;
15303 var morphNormals = material.morphNormals && geometry.morphAttributes.normal;
15304
15305 // Remove current morphAttributes
15306
15307 for ( var i = 0; i < length; i ++ ) {
15308
15309 var influence = influences[ i ];
15310
15311 if ( influence[ 1 ] !== 0 ) {
15312
15313 if ( morphTargets ) geometry.removeAttribute( 'morphTarget' + i );
15314 if ( morphNormals ) geometry.removeAttribute( 'morphNormal' + i );
15315
15316 }
15317
15318 }
15319
15320 // Collect influences
15321
15322 for ( var i = 0; i < length; i ++ ) {
15323
15324 var influence = influences[ i ];
15325
15326 influence[ 0 ] = i;
15327 influence[ 1 ] = objectInfluences[ i ];
15328
15329 }
15330
15331 influences.sort( absNumericalSort );
15332
15333 // Add morphAttributes
15334
15335 for ( var i = 0; i < 8; i ++ ) {
15336
15337 var influence = influences[ i ];
15338
15339 if ( influence ) {
15340
15341 var index = influence[ 0 ];
15342 var value = influence[ 1 ];
15343
15344 if ( value ) {
15345
15346 if ( morphTargets ) geometry.addAttribute( 'morphTarget' + i, morphTargets[ index ] );
15347 if ( morphNormals ) geometry.addAttribute( 'morphNormal' + i, morphNormals[ index ] );
15348
15349 morphInfluences[ i ] = value;
15350 continue;
15351
15352 }
15353
15354 }
15355
15356 morphInfluences[ i ] = 0;
15357
15358 }
15359
15360 program.getUniforms().setValue( gl, 'morphTargetInfluences', morphInfluences );
15361
15362 }
15363
15364 return {
15365
15366 update: update
15367
15368 };
15369
15370 }
15371
15372 /**
15373 * @author mrdoob / http://mrdoob.com/
15374 */
15375
15376 function WebGLObjects( geometries, info ) {
15377
15378 var updateList = {};
15379
15380 function update( object ) {
15381
15382 var frame = info.render.frame;
15383
15384 var geometry = object.geometry;
15385 var buffergeometry = geometries.get( object, geometry );
15386
15387 // Update once per frame
15388
15389 if ( updateList[ buffergeometry.id ] !== frame ) {
15390
15391 if ( geometry.isGeometry ) {
15392
15393 buffergeometry.updateFromObject( object );
15394
15395 }
15396
15397 geometries.update( buffergeometry );
15398
15399 updateList[ buffergeometry.id ] = frame;
15400
15401 }
15402
15403 return buffergeometry;
15404
15405 }
15406
15407 function dispose() {
15408
15409 updateList = {};
15410
15411 }
15412
15413 return {
15414
15415 update: update,
15416 dispose: dispose
15417
15418 };
15419
15420 }
15421
15422 /**
15423 * @author mrdoob / http://mrdoob.com/
15424 */
15425
15426 function CubeTexture( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) {
15427
15428 images = images !== undefined ? images : [];
15429 mapping = mapping !== undefined ? mapping : CubeReflectionMapping;
15430
15431 Texture.call( this, images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
15432
15433 this.flipY = false;
15434
15435 }
15436
15437 CubeTexture.prototype = Object.create( Texture.prototype );
15438 CubeTexture.prototype.constructor = CubeTexture;
15439
15440 CubeTexture.prototype.isCubeTexture = true;
15441
15442 Object.defineProperty( CubeTexture.prototype, 'images', {
15443
15444 get: function () {
15445
15446 return this.image;
15447
15448 },
15449
15450 set: function ( value ) {
15451
15452 this.image = value;
15453
15454 }
15455
15456 } );
15457
15458 /**
15459 * @author tschw
15460 *
15461 * Uniforms of a program.
15462 * Those form a tree structure with a special top-level container for the root,
15463 * which you get by calling 'new WebGLUniforms( gl, program, renderer )'.
15464 *
15465 *
15466 * Properties of inner nodes including the top-level container:
15467 *
15468 * .seq - array of nested uniforms
15469 * .map - nested uniforms by name
15470 *
15471 *
15472 * Methods of all nodes except the top-level container:
15473 *
15474 * .setValue( gl, value, [renderer] )
15475 *
15476 * uploads a uniform value(s)
15477 * the 'renderer' parameter is needed for sampler uniforms
15478 *
15479 *
15480 * Static methods of the top-level container (renderer factorizations):
15481 *
15482 * .upload( gl, seq, values, renderer )
15483 *
15484 * sets uniforms in 'seq' to 'values[id].value'
15485 *
15486 * .seqWithValue( seq, values ) : filteredSeq
15487 *
15488 * filters 'seq' entries with corresponding entry in values
15489 *
15490 *
15491 * Methods of the top-level container (renderer factorizations):
15492 *
15493 * .setValue( gl, name, value )
15494 *
15495 * sets uniform with name 'name' to 'value'
15496 *
15497 * .set( gl, obj, prop )
15498 *
15499 * sets uniform from object and property with same name than uniform
15500 *
15501 * .setOptional( gl, obj, prop )
15502 *
15503 * like .set for an optional property of the object
15504 *
15505 */
15506
15507 var emptyTexture = new Texture();
15508 var emptyCubeTexture = new CubeTexture();
15509
15510 // --- Base for inner nodes (including the root) ---
15511
15512 function UniformContainer() {
15513
15514 this.seq = [];
15515 this.map = {};
15516
15517 }
15518
15519 // --- Utilities ---
15520
15521 // Array Caches (provide typed arrays for temporary by size)
15522
15523 var arrayCacheF32 = [];
15524 var arrayCacheI32 = [];
15525
15526 // Float32Array caches used for uploading Matrix uniforms
15527
15528 var mat4array = new Float32Array( 16 );
15529 var mat3array = new Float32Array( 9 );
15530
15531 // Flattening for arrays of vectors and matrices
15532
15533 function flatten( array, nBlocks, blockSize ) {
15534
15535 var firstElem = array[ 0 ];
15536
15537 if ( firstElem <= 0 || firstElem > 0 ) return array;
15538 // unoptimized: ! isNaN( firstElem )
15539 // see http://jacksondunstan.com/articles/983
15540
15541 var n = nBlocks * blockSize,
15542 r = arrayCacheF32[ n ];
15543
15544 if ( r === undefined ) {
15545
15546 r = new Float32Array( n );
15547 arrayCacheF32[ n ] = r;
15548
15549 }
15550
15551 if ( nBlocks !== 0 ) {
15552
15553 firstElem.toArray( r, 0 );
15554
15555 for ( var i = 1, offset = 0; i !== nBlocks; ++ i ) {
15556
15557 offset += blockSize;
15558 array[ i ].toArray( r, offset );
15559
15560 }
15561
15562 }
15563
15564 return r;
15565
15566 }
15567
15568 // Texture unit allocation
15569
15570 function allocTexUnits( renderer, n ) {
15571
15572 var r = arrayCacheI32[ n ];
15573
15574 if ( r === undefined ) {
15575
15576 r = new Int32Array( n );
15577 arrayCacheI32[ n ] = r;
15578
15579 }
15580
15581 for ( var i = 0; i !== n; ++ i )
15582 r[ i ] = renderer.allocTextureUnit();
15583
15584 return r;
15585
15586 }
15587
15588 // --- Setters ---
15589
15590 // Note: Defining these methods externally, because they come in a bunch
15591 // and this way their names minify.
15592
15593 // Single scalar
15594
15595 function setValue1f( gl, v ) {
15596
15597 gl.uniform1f( this.addr, v );
15598
15599 }
15600
15601 function setValue1i( gl, v ) {
15602
15603 gl.uniform1i( this.addr, v );
15604
15605 }
15606
15607 // Single float vector (from flat array or THREE.VectorN)
15608
15609 function setValue2fv( gl, v ) {
15610
15611 if ( v.x === undefined ) {
15612
15613 gl.uniform2fv( this.addr, v );
15614
15615 } else {
15616
15617 gl.uniform2f( this.addr, v.x, v.y );
15618
15619 }
15620
15621 }
15622
15623 function setValue3fv( gl, v ) {
15624
15625 if ( v.x !== undefined ) {
15626
15627 gl.uniform3f( this.addr, v.x, v.y, v.z );
15628
15629 } else if ( v.r !== undefined ) {
15630
15631 gl.uniform3f( this.addr, v.r, v.g, v.b );
15632
15633 } else {
15634
15635 gl.uniform3fv( this.addr, v );
15636
15637 }
15638
15639 }
15640
15641 function setValue4fv( gl, v ) {
15642
15643 if ( v.x === undefined ) {
15644
15645 gl.uniform4fv( this.addr, v );
15646
15647 } else {
15648
15649 gl.uniform4f( this.addr, v.x, v.y, v.z, v.w );
15650
15651 }
15652
15653 }
15654
15655 // Single matrix (from flat array or MatrixN)
15656
15657 function setValue2fm( gl, v ) {
15658
15659 gl.uniformMatrix2fv( this.addr, false, v.elements || v );
15660
15661 }
15662
15663 function setValue3fm( gl, v ) {
15664
15665 if ( v.elements === undefined ) {
15666
15667 gl.uniformMatrix3fv( this.addr, false, v );
15668
15669 } else {
15670
15671 mat3array.set( v.elements );
15672 gl.uniformMatrix3fv( this.addr, false, mat3array );
15673
15674 }
15675
15676 }
15677
15678 function setValue4fm( gl, v ) {
15679
15680 if ( v.elements === undefined ) {
15681
15682 gl.uniformMatrix4fv( this.addr, false, v );
15683
15684 } else {
15685
15686 mat4array.set( v.elements );
15687 gl.uniformMatrix4fv( this.addr, false, mat4array );
15688
15689 }
15690
15691 }
15692
15693 // Single texture (2D / Cube)
15694
15695 function setValueT1( gl, v, renderer ) {
15696
15697 var unit = renderer.allocTextureUnit();
15698 gl.uniform1i( this.addr, unit );
15699 renderer.setTexture2D( v || emptyTexture, unit );
15700
15701 }
15702
15703 function setValueT6( gl, v, renderer ) {
15704
15705 var unit = renderer.allocTextureUnit();
15706 gl.uniform1i( this.addr, unit );
15707 renderer.setTextureCube( v || emptyCubeTexture, unit );
15708
15709 }
15710
15711 // Integer / Boolean vectors or arrays thereof (always flat arrays)
15712
15713 function setValue2iv( gl, v ) {
15714
15715 gl.uniform2iv( this.addr, v );
15716
15717 }
15718
15719 function setValue3iv( gl, v ) {
15720
15721 gl.uniform3iv( this.addr, v );
15722
15723 }
15724
15725 function setValue4iv( gl, v ) {
15726
15727 gl.uniform4iv( this.addr, v );
15728
15729 }
15730
15731 // Helper to pick the right setter for the singular case
15732
15733 function getSingularSetter( type ) {
15734
15735 switch ( type ) {
15736
15737 case 0x1406: return setValue1f; // FLOAT
15738 case 0x8b50: return setValue2fv; // _VEC2
15739 case 0x8b51: return setValue3fv; // _VEC3
15740 case 0x8b52: return setValue4fv; // _VEC4
15741
15742 case 0x8b5a: return setValue2fm; // _MAT2
15743 case 0x8b5b: return setValue3fm; // _MAT3
15744 case 0x8b5c: return setValue4fm; // _MAT4
15745
15746 case 0x8b5e: case 0x8d66: return setValueT1; // SAMPLER_2D, SAMPLER_EXTERNAL_OES
15747 case 0x8b60: return setValueT6; // SAMPLER_CUBE
15748
15749 case 0x1404: case 0x8b56: return setValue1i; // INT, BOOL
15750 case 0x8b53: case 0x8b57: return setValue2iv; // _VEC2
15751 case 0x8b54: case 0x8b58: return setValue3iv; // _VEC3
15752 case 0x8b55: case 0x8b59: return setValue4iv; // _VEC4
15753
15754 }
15755
15756 }
15757
15758 // Array of scalars
15759
15760 function setValue1fv( gl, v ) {
15761
15762 gl.uniform1fv( this.addr, v );
15763
15764 }
15765 function setValue1iv( gl, v ) {
15766
15767 gl.uniform1iv( this.addr, v );
15768
15769 }
15770
15771 // Array of vectors (flat or from THREE classes)
15772
15773 function setValueV2a( gl, v ) {
15774
15775 gl.uniform2fv( this.addr, flatten( v, this.size, 2 ) );
15776
15777 }
15778
15779 function setValueV3a( gl, v ) {
15780
15781 gl.uniform3fv( this.addr, flatten( v, this.size, 3 ) );
15782
15783 }
15784
15785 function setValueV4a( gl, v ) {
15786
15787 gl.uniform4fv( this.addr, flatten( v, this.size, 4 ) );
15788
15789 }
15790
15791 // Array of matrices (flat or from THREE clases)
15792
15793 function setValueM2a( gl, v ) {
15794
15795 gl.uniformMatrix2fv( this.addr, false, flatten( v, this.size, 4 ) );
15796
15797 }
15798
15799 function setValueM3a( gl, v ) {
15800
15801 gl.uniformMatrix3fv( this.addr, false, flatten( v, this.size, 9 ) );
15802
15803 }
15804
15805 function setValueM4a( gl, v ) {
15806
15807 gl.uniformMatrix4fv( this.addr, false, flatten( v, this.size, 16 ) );
15808
15809 }
15810
15811 // Array of textures (2D / Cube)
15812
15813 function setValueT1a( gl, v, renderer ) {
15814
15815 var n = v.length,
15816 units = allocTexUnits( renderer, n );
15817
15818 gl.uniform1iv( this.addr, units );
15819
15820 for ( var i = 0; i !== n; ++ i ) {
15821
15822 renderer.setTexture2D( v[ i ] || emptyTexture, units[ i ] );
15823
15824 }
15825
15826 }
15827
15828 function setValueT6a( gl, v, renderer ) {
15829
15830 var n = v.length,
15831 units = allocTexUnits( renderer, n );
15832
15833 gl.uniform1iv( this.addr, units );
15834
15835 for ( var i = 0; i !== n; ++ i ) {
15836
15837 renderer.setTextureCube( v[ i ] || emptyCubeTexture, units[ i ] );
15838
15839 }
15840
15841 }
15842
15843 // Helper to pick the right setter for a pure (bottom-level) array
15844
15845 function getPureArraySetter( type ) {
15846
15847 switch ( type ) {
15848
15849 case 0x1406: return setValue1fv; // FLOAT
15850 case 0x8b50: return setValueV2a; // _VEC2
15851 case 0x8b51: return setValueV3a; // _VEC3
15852 case 0x8b52: return setValueV4a; // _VEC4
15853
15854 case 0x8b5a: return setValueM2a; // _MAT2
15855 case 0x8b5b: return setValueM3a; // _MAT3
15856 case 0x8b5c: return setValueM4a; // _MAT4
15857
15858 case 0x8b5e: return setValueT1a; // SAMPLER_2D
15859 case 0x8b60: return setValueT6a; // SAMPLER_CUBE
15860
15861 case 0x1404: case 0x8b56: return setValue1iv; // INT, BOOL
15862 case 0x8b53: case 0x8b57: return setValue2iv; // _VEC2
15863 case 0x8b54: case 0x8b58: return setValue3iv; // _VEC3
15864 case 0x8b55: case 0x8b59: return setValue4iv; // _VEC4
15865
15866 }
15867
15868 }
15869
15870 // --- Uniform Classes ---
15871
15872 function SingleUniform( id, activeInfo, addr ) {
15873
15874 this.id = id;
15875 this.addr = addr;
15876 this.setValue = getSingularSetter( activeInfo.type );
15877
15878 // this.path = activeInfo.name; // DEBUG
15879
15880 }
15881
15882 function PureArrayUniform( id, activeInfo, addr ) {
15883
15884 this.id = id;
15885 this.addr = addr;
15886 this.size = activeInfo.size;
15887 this.setValue = getPureArraySetter( activeInfo.type );
15888
15889 // this.path = activeInfo.name; // DEBUG
15890
15891 }
15892
15893 function StructuredUniform( id ) {
15894
15895 this.id = id;
15896
15897 UniformContainer.call( this ); // mix-in
15898
15899 }
15900
15901 StructuredUniform.prototype.setValue = function ( gl, value ) {
15902
15903 // Note: Don't need an extra 'renderer' parameter, since samplers
15904 // are not allowed in structured uniforms.
15905
15906 var seq = this.seq;
15907
15908 for ( var i = 0, n = seq.length; i !== n; ++ i ) {
15909
15910 var u = seq[ i ];
15911 u.setValue( gl, value[ u.id ] );
15912
15913 }
15914
15915 };
15916
15917 // --- Top-level ---
15918
15919 // Parser - builds up the property tree from the path strings
15920
15921 var RePathPart = /([\w\d_]+)(\])?(\[|\.)?/g;
15922
15923 // extracts
15924 // - the identifier (member name or array index)
15925 // - followed by an optional right bracket (found when array index)
15926 // - followed by an optional left bracket or dot (type of subscript)
15927 //
15928 // Note: These portions can be read in a non-overlapping fashion and
15929 // allow straightforward parsing of the hierarchy that WebGL encodes
15930 // in the uniform names.
15931
15932 function addUniform( container, uniformObject ) {
15933
15934 container.seq.push( uniformObject );
15935 container.map[ uniformObject.id ] = uniformObject;
15936
15937 }
15938
15939 function parseUniform( activeInfo, addr, container ) {
15940
15941 var path = activeInfo.name,
15942 pathLength = path.length;
15943
15944 // reset RegExp object, because of the early exit of a previous run
15945 RePathPart.lastIndex = 0;
15946
15947 for ( ; ; ) {
15948
15949 var match = RePathPart.exec( path ),
15950 matchEnd = RePathPart.lastIndex,
15951
15952 id = match[ 1 ],
15953 idIsIndex = match[ 2 ] === ']',
15954 subscript = match[ 3 ];
15955
15956 if ( idIsIndex ) id = id | 0; // convert to integer
15957
15958 if ( subscript === undefined || subscript === '[' && matchEnd + 2 === pathLength ) {
15959
15960 // bare name or "pure" bottom-level array "[0]" suffix
15961
15962 addUniform( container, subscript === undefined ?
15963 new SingleUniform( id, activeInfo, addr ) :
15964 new PureArrayUniform( id, activeInfo, addr ) );
15965
15966 break;
15967
15968 } else {
15969
15970 // step into inner node / create it in case it doesn't exist
15971
15972 var map = container.map, next = map[ id ];
15973
15974 if ( next === undefined ) {
15975
15976 next = new StructuredUniform( id );
15977 addUniform( container, next );
15978
15979 }
15980
15981 container = next;
15982
15983 }
15984
15985 }
15986
15987 }
15988
15989 // Root Container
15990
15991 function WebGLUniforms( gl, program, renderer ) {
15992
15993 UniformContainer.call( this );
15994
15995 this.renderer = renderer;
15996
15997 var n = gl.getProgramParameter( program, gl.ACTIVE_UNIFORMS );
15998
15999 for ( var i = 0; i < n; ++ i ) {
16000
16001 var info = gl.getActiveUniform( program, i ),
16002 addr = gl.getUniformLocation( program, info.name );
16003
16004 parseUniform( info, addr, this );
16005
16006 }
16007
16008 }
16009
16010 WebGLUniforms.prototype.setValue = function ( gl, name, value ) {
16011
16012 var u = this.map[ name ];
16013
16014 if ( u !== undefined ) u.setValue( gl, value, this.renderer );
16015
16016 };
16017
16018 WebGLUniforms.prototype.setOptional = function ( gl, object, name ) {
16019
16020 var v = object[ name ];
16021
16022 if ( v !== undefined ) this.setValue( gl, name, v );
16023
16024 };
16025
16026
16027 // Static interface
16028
16029 WebGLUniforms.upload = function ( gl, seq, values, renderer ) {
16030
16031 for ( var i = 0, n = seq.length; i !== n; ++ i ) {
16032
16033 var u = seq[ i ],
16034 v = values[ u.id ];
16035
16036 if ( v.needsUpdate !== false ) {
16037
16038 // note: always updating when .needsUpdate is undefined
16039 u.setValue( gl, v.value, renderer );
16040
16041 }
16042
16043 }
16044
16045 };
16046
16047 WebGLUniforms.seqWithValue = function ( seq, values ) {
16048
16049 var r = [];
16050
16051 for ( var i = 0, n = seq.length; i !== n; ++ i ) {
16052
16053 var u = seq[ i ];
16054 if ( u.id in values ) r.push( u );
16055
16056 }
16057
16058 return r;
16059
16060 };
16061
16062 /**
16063 * @author mrdoob / http://mrdoob.com/
16064 */
16065
16066 function addLineNumbers( string ) {
16067
16068 var lines = string.split( '\n' );
16069
16070 for ( var i = 0; i < lines.length; i ++ ) {
16071
16072 lines[ i ] = ( i + 1 ) + ': ' + lines[ i ];
16073
16074 }
16075
16076 return lines.join( '\n' );
16077
16078 }
16079
16080 function WebGLShader( gl, type, string ) {
16081
16082 var shader = gl.createShader( type );
16083
16084 gl.shaderSource( shader, string );
16085 gl.compileShader( shader );
16086
16087 if ( gl.getShaderParameter( shader, gl.COMPILE_STATUS ) === false ) {
16088
16089 console.error( 'THREE.WebGLShader: Shader couldn\'t compile.' );
16090
16091 }
16092
16093 if ( gl.getShaderInfoLog( shader ) !== '' ) {
16094
16095 console.warn( 'THREE.WebGLShader: gl.getShaderInfoLog()', type === gl.VERTEX_SHADER ? 'vertex' : 'fragment', gl.getShaderInfoLog( shader ), addLineNumbers( string ) );
16096
16097 }
16098
16099 // --enable-privileged-webgl-extension
16100 // console.log( type, gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) );
16101
16102 return shader;
16103
16104 }
16105
16106 /**
16107 * @author mrdoob / http://mrdoob.com/
16108 */
16109
16110 var programIdCount = 0;
16111
16112 function getEncodingComponents( encoding ) {
16113
16114 switch ( encoding ) {
16115
16116 case LinearEncoding:
16117 return [ 'Linear', '( value )' ];
16118 case sRGBEncoding:
16119 return [ 'sRGB', '( value )' ];
16120 case RGBEEncoding:
16121 return [ 'RGBE', '( value )' ];
16122 case RGBM7Encoding:
16123 return [ 'RGBM', '( value, 7.0 )' ];
16124 case RGBM16Encoding:
16125 return [ 'RGBM', '( value, 16.0 )' ];
16126 case RGBDEncoding:
16127 return [ 'RGBD', '( value, 256.0 )' ];
16128 case GammaEncoding:
16129 return [ 'Gamma', '( value, float( GAMMA_FACTOR ) )' ];
16130 default:
16131 throw new Error( 'unsupported encoding: ' + encoding );
16132
16133 }
16134
16135 }
16136
16137 function getTexelDecodingFunction( functionName, encoding ) {
16138
16139 var components = getEncodingComponents( encoding );
16140 return 'vec4 ' + functionName + '( vec4 value ) { return ' + components[ 0 ] + 'ToLinear' + components[ 1 ] + '; }';
16141
16142 }
16143
16144 function getTexelEncodingFunction( functionName, encoding ) {
16145
16146 var components = getEncodingComponents( encoding );
16147 return 'vec4 ' + functionName + '( vec4 value ) { return LinearTo' + components[ 0 ] + components[ 1 ] + '; }';
16148
16149 }
16150
16151 function getToneMappingFunction( functionName, toneMapping ) {
16152
16153 var toneMappingName;
16154
16155 switch ( toneMapping ) {
16156
16157 case LinearToneMapping:
16158 toneMappingName = 'Linear';
16159 break;
16160
16161 case ReinhardToneMapping:
16162 toneMappingName = 'Reinhard';
16163 break;
16164
16165 case Uncharted2ToneMapping:
16166 toneMappingName = 'Uncharted2';
16167 break;
16168
16169 case CineonToneMapping:
16170 toneMappingName = 'OptimizedCineon';
16171 break;
16172
16173 default:
16174 throw new Error( 'unsupported toneMapping: ' + toneMapping );
16175
16176 }
16177
16178 return 'vec3 ' + functionName + '( vec3 color ) { return ' + toneMappingName + 'ToneMapping( color ); }';
16179
16180 }
16181
16182 function generateExtensions( extensions, parameters, rendererExtensions ) {
16183
16184 extensions = extensions || {};
16185
16186 var chunks = [
16187 ( extensions.derivatives || parameters.envMapCubeUV || parameters.bumpMap || parameters.normalMap || parameters.flatShading ) ? '#extension GL_OES_standard_derivatives : enable' : '',
16188 ( extensions.fragDepth || parameters.logarithmicDepthBuffer ) && rendererExtensions.get( 'EXT_frag_depth' ) ? '#extension GL_EXT_frag_depth : enable' : '',
16189 ( extensions.drawBuffers ) && rendererExtensions.get( 'WEBGL_draw_buffers' ) ? '#extension GL_EXT_draw_buffers : require' : '',
16190 ( extensions.shaderTextureLOD || parameters.envMap ) && rendererExtensions.get( 'EXT_shader_texture_lod' ) ? '#extension GL_EXT_shader_texture_lod : enable' : ''
16191 ];
16192
16193 return chunks.filter( filterEmptyLine ).join( '\n' );
16194
16195 }
16196
16197 function generateDefines( defines ) {
16198
16199 var chunks = [];
16200
16201 for ( var name in defines ) {
16202
16203 var value = defines[ name ];
16204
16205 if ( value === false ) continue;
16206
16207 chunks.push( '#define ' + name + ' ' + value );
16208
16209 }
16210
16211 return chunks.join( '\n' );
16212
16213 }
16214
16215 function fetchAttributeLocations( gl, program ) {
16216
16217 var attributes = {};
16218
16219 var n = gl.getProgramParameter( program, gl.ACTIVE_ATTRIBUTES );
16220
16221 for ( var i = 0; i < n; i ++ ) {
16222
16223 var info = gl.getActiveAttrib( program, i );
16224 var name = info.name;
16225
16226 // console.log( 'THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:', name, i );
16227
16228 attributes[ name ] = gl.getAttribLocation( program, name );
16229
16230 }
16231
16232 return attributes;
16233
16234 }
16235
16236 function filterEmptyLine( string ) {
16237
16238 return string !== '';
16239
16240 }
16241
16242 function replaceLightNums( string, parameters ) {
16243
16244 return string
16245 .replace( /NUM_DIR_LIGHTS/g, parameters.numDirLights )
16246 .replace( /NUM_SPOT_LIGHTS/g, parameters.numSpotLights )
16247 .replace( /NUM_RECT_AREA_LIGHTS/g, parameters.numRectAreaLights )
16248 .replace( /NUM_POINT_LIGHTS/g, parameters.numPointLights )
16249 .replace( /NUM_HEMI_LIGHTS/g, parameters.numHemiLights );
16250
16251 }
16252
16253 function replaceClippingPlaneNums( string, parameters ) {
16254
16255 return string
16256 .replace( /NUM_CLIPPING_PLANES/g, parameters.numClippingPlanes )
16257 .replace( /UNION_CLIPPING_PLANES/g, ( parameters.numClippingPlanes - parameters.numClipIntersection ) );
16258
16259 }
16260
16261 function parseIncludes( string ) {
16262
16263 var pattern = /^[ \t]*#include +<([\w\d.]+)>/gm;
16264
16265 function replace( match, include ) {
16266
16267 var replace = ShaderChunk[ include ];
16268
16269 if ( replace === undefined ) {
16270
16271 throw new Error( 'Can not resolve #include <' + include + '>' );
16272
16273 }
16274
16275 return parseIncludes( replace );
16276
16277 }
16278
16279 return string.replace( pattern, replace );
16280
16281 }
16282
16283 function unrollLoops( string ) {
16284
16285 var pattern = /#pragma unroll_loop[\s]+?for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g;
16286
16287 function replace( match, start, end, snippet ) {
16288
16289 var unroll = '';
16290
16291 for ( var i = parseInt( start ); i < parseInt( end ); i ++ ) {
16292
16293 unroll += snippet.replace( /\[ i \]/g, '[ ' + i + ' ]' );
16294
16295 }
16296
16297 return unroll;
16298
16299 }
16300
16301 return string.replace( pattern, replace );
16302
16303 }
16304
16305 function WebGLProgram( renderer, extensions, code, material, shader, parameters ) {
16306
16307 var gl = renderer.context;
16308
16309 var defines = material.defines;
16310
16311 var vertexShader = shader.vertexShader;
16312 var fragmentShader = shader.fragmentShader;
16313
16314 var shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC';
16315
16316 if ( parameters.shadowMapType === PCFShadowMap ) {
16317
16318 shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF';
16319
16320 } else if ( parameters.shadowMapType === PCFSoftShadowMap ) {
16321
16322 shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT';
16323
16324 }
16325
16326 var envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
16327 var envMapModeDefine = 'ENVMAP_MODE_REFLECTION';
16328 var envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
16329
16330 if ( parameters.envMap ) {
16331
16332 switch ( material.envMap.mapping ) {
16333
16334 case CubeReflectionMapping:
16335 case CubeRefractionMapping:
16336 envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
16337 break;
16338
16339 case CubeUVReflectionMapping:
16340 case CubeUVRefractionMapping:
16341 envMapTypeDefine = 'ENVMAP_TYPE_CUBE_UV';
16342 break;
16343
16344 case EquirectangularReflectionMapping:
16345 case EquirectangularRefractionMapping:
16346 envMapTypeDefine = 'ENVMAP_TYPE_EQUIREC';
16347 break;
16348
16349 case SphericalReflectionMapping:
16350 envMapTypeDefine = 'ENVMAP_TYPE_SPHERE';
16351 break;
16352
16353 }
16354
16355 switch ( material.envMap.mapping ) {
16356
16357 case CubeRefractionMapping:
16358 case EquirectangularRefractionMapping:
16359 envMapModeDefine = 'ENVMAP_MODE_REFRACTION';
16360 break;
16361
16362 }
16363
16364 switch ( material.combine ) {
16365
16366 case MultiplyOperation:
16367 envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
16368 break;
16369
16370 case MixOperation:
16371 envMapBlendingDefine = 'ENVMAP_BLENDING_MIX';
16372 break;
16373
16374 case AddOperation:
16375 envMapBlendingDefine = 'ENVMAP_BLENDING_ADD';
16376 break;
16377
16378 }
16379
16380 }
16381
16382 var gammaFactorDefine = ( renderer.gammaFactor > 0 ) ? renderer.gammaFactor : 1.0;
16383
16384 // console.log( 'building new program ' );
16385
16386 //
16387
16388 var customExtensions = generateExtensions( material.extensions, parameters, extensions );
16389
16390 var customDefines = generateDefines( defines );
16391
16392 //
16393
16394 var program = gl.createProgram();
16395
16396 var prefixVertex, prefixFragment;
16397
16398 if ( material.isRawShaderMaterial ) {
16399
16400 prefixVertex = [
16401
16402 customDefines
16403
16404 ].filter( filterEmptyLine ).join( '\n' );
16405
16406 if ( prefixVertex.length > 0 ) {
16407
16408 prefixVertex += '\n';
16409
16410 }
16411
16412 prefixFragment = [
16413
16414 customExtensions,
16415 customDefines
16416
16417 ].filter( filterEmptyLine ).join( '\n' );
16418
16419 if ( prefixFragment.length > 0 ) {
16420
16421 prefixFragment += '\n';
16422
16423 }
16424
16425 } else {
16426
16427 prefixVertex = [
16428
16429 'precision ' + parameters.precision + ' float;',
16430 'precision ' + parameters.precision + ' int;',
16431
16432 '#define SHADER_NAME ' + shader.name,
16433
16434 customDefines,
16435
16436 parameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '',
16437
16438 '#define GAMMA_FACTOR ' + gammaFactorDefine,
16439
16440 '#define MAX_BONES ' + parameters.maxBones,
16441 ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',
16442 ( parameters.useFog && parameters.fogExp ) ? '#define FOG_EXP2' : '',
16443
16444 parameters.map ? '#define USE_MAP' : '',
16445 parameters.envMap ? '#define USE_ENVMAP' : '',
16446 parameters.envMap ? '#define ' + envMapModeDefine : '',
16447 parameters.lightMap ? '#define USE_LIGHTMAP' : '',
16448 parameters.aoMap ? '#define USE_AOMAP' : '',
16449 parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
16450 parameters.bumpMap ? '#define USE_BUMPMAP' : '',
16451 parameters.normalMap ? '#define USE_NORMALMAP' : '',
16452 parameters.displacementMap && parameters.supportsVertexTextures ? '#define USE_DISPLACEMENTMAP' : '',
16453 parameters.specularMap ? '#define USE_SPECULARMAP' : '',
16454 parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
16455 parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
16456 parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
16457 parameters.vertexColors ? '#define USE_COLOR' : '',
16458
16459 parameters.flatShading ? '#define FLAT_SHADED' : '',
16460
16461 parameters.skinning ? '#define USE_SKINNING' : '',
16462 parameters.useVertexTexture ? '#define BONE_TEXTURE' : '',
16463
16464 parameters.morphTargets ? '#define USE_MORPHTARGETS' : '',
16465 parameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '',
16466 parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
16467 parameters.flipSided ? '#define FLIP_SIDED' : '',
16468
16469 parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
16470 parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
16471
16472 parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '',
16473
16474 parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
16475 parameters.logarithmicDepthBuffer && extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
16476
16477 'uniform mat4 modelMatrix;',
16478 'uniform mat4 modelViewMatrix;',
16479 'uniform mat4 projectionMatrix;',
16480 'uniform mat4 viewMatrix;',
16481 'uniform mat3 normalMatrix;',
16482 'uniform vec3 cameraPosition;',
16483
16484 'attribute vec3 position;',
16485 'attribute vec3 normal;',
16486 'attribute vec2 uv;',
16487
16488 '#ifdef USE_COLOR',
16489
16490 ' attribute vec3 color;',
16491
16492 '#endif',
16493
16494 '#ifdef USE_MORPHTARGETS',
16495
16496 ' attribute vec3 morphTarget0;',
16497 ' attribute vec3 morphTarget1;',
16498 ' attribute vec3 morphTarget2;',
16499 ' attribute vec3 morphTarget3;',
16500
16501 ' #ifdef USE_MORPHNORMALS',
16502
16503 ' attribute vec3 morphNormal0;',
16504 ' attribute vec3 morphNormal1;',
16505 ' attribute vec3 morphNormal2;',
16506 ' attribute vec3 morphNormal3;',
16507
16508 ' #else',
16509
16510 ' attribute vec3 morphTarget4;',
16511 ' attribute vec3 morphTarget5;',
16512 ' attribute vec3 morphTarget6;',
16513 ' attribute vec3 morphTarget7;',
16514
16515 ' #endif',
16516
16517 '#endif',
16518
16519 '#ifdef USE_SKINNING',
16520
16521 ' attribute vec4 skinIndex;',
16522 ' attribute vec4 skinWeight;',
16523
16524 '#endif',
16525
16526 '\n'
16527
16528 ].filter( filterEmptyLine ).join( '\n' );
16529
16530 prefixFragment = [
16531
16532 customExtensions,
16533
16534 'precision ' + parameters.precision + ' float;',
16535 'precision ' + parameters.precision + ' int;',
16536
16537 '#define SHADER_NAME ' + shader.name,
16538
16539 customDefines,
16540
16541 parameters.alphaTest ? '#define ALPHATEST ' + parameters.alphaTest : '',
16542
16543 '#define GAMMA_FACTOR ' + gammaFactorDefine,
16544
16545 ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',
16546 ( parameters.useFog && parameters.fogExp ) ? '#define FOG_EXP2' : '',
16547
16548 parameters.map ? '#define USE_MAP' : '',
16549 parameters.envMap ? '#define USE_ENVMAP' : '',
16550 parameters.envMap ? '#define ' + envMapTypeDefine : '',
16551 parameters.envMap ? '#define ' + envMapModeDefine : '',
16552 parameters.envMap ? '#define ' + envMapBlendingDefine : '',
16553 parameters.lightMap ? '#define USE_LIGHTMAP' : '',
16554 parameters.aoMap ? '#define USE_AOMAP' : '',
16555 parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
16556 parameters.bumpMap ? '#define USE_BUMPMAP' : '',
16557 parameters.normalMap ? '#define USE_NORMALMAP' : '',
16558 parameters.specularMap ? '#define USE_SPECULARMAP' : '',
16559 parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
16560 parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
16561 parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
16562 parameters.vertexColors ? '#define USE_COLOR' : '',
16563
16564 parameters.gradientMap ? '#define USE_GRADIENTMAP' : '',
16565
16566 parameters.flatShading ? '#define FLAT_SHADED' : '',
16567
16568 parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
16569 parameters.flipSided ? '#define FLIP_SIDED' : '',
16570
16571 parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
16572 parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
16573
16574 parameters.premultipliedAlpha ? '#define PREMULTIPLIED_ALPHA' : '',
16575
16576 parameters.physicallyCorrectLights ? '#define PHYSICALLY_CORRECT_LIGHTS' : '',
16577
16578 parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
16579 parameters.logarithmicDepthBuffer && extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
16580
16581 parameters.envMap && extensions.get( 'EXT_shader_texture_lod' ) ? '#define TEXTURE_LOD_EXT' : '',
16582
16583 'uniform mat4 viewMatrix;',
16584 'uniform vec3 cameraPosition;',
16585
16586 ( parameters.toneMapping !== NoToneMapping ) ? '#define TONE_MAPPING' : '',
16587 ( parameters.toneMapping !== NoToneMapping ) ? ShaderChunk[ 'tonemapping_pars_fragment' ] : '', // this code is required here because it is used by the toneMapping() function defined below
16588 ( parameters.toneMapping !== NoToneMapping ) ? getToneMappingFunction( 'toneMapping', parameters.toneMapping ) : '',
16589
16590 parameters.dithering ? '#define DITHERING' : '',
16591
16592 ( 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
16593 parameters.mapEncoding ? getTexelDecodingFunction( 'mapTexelToLinear', parameters.mapEncoding ) : '',
16594 parameters.envMapEncoding ? getTexelDecodingFunction( 'envMapTexelToLinear', parameters.envMapEncoding ) : '',
16595 parameters.emissiveMapEncoding ? getTexelDecodingFunction( 'emissiveMapTexelToLinear', parameters.emissiveMapEncoding ) : '',
16596 parameters.outputEncoding ? getTexelEncodingFunction( 'linearToOutputTexel', parameters.outputEncoding ) : '',
16597
16598 parameters.depthPacking ? '#define DEPTH_PACKING ' + material.depthPacking : '',
16599
16600 '\n'
16601
16602 ].filter( filterEmptyLine ).join( '\n' );
16603
16604 }
16605
16606 vertexShader = parseIncludes( vertexShader );
16607 vertexShader = replaceLightNums( vertexShader, parameters );
16608 vertexShader = replaceClippingPlaneNums( vertexShader, parameters );
16609
16610 fragmentShader = parseIncludes( fragmentShader );
16611 fragmentShader = replaceLightNums( fragmentShader, parameters );
16612 fragmentShader = replaceClippingPlaneNums( fragmentShader, parameters );
16613
16614 vertexShader = unrollLoops( vertexShader );
16615 fragmentShader = unrollLoops( fragmentShader );
16616
16617 var vertexGlsl = prefixVertex + vertexShader;
16618 var fragmentGlsl = prefixFragment + fragmentShader;
16619
16620 // console.log( '*VERTEX*', vertexGlsl );
16621 // console.log( '*FRAGMENT*', fragmentGlsl );
16622
16623 var glVertexShader = WebGLShader( gl, gl.VERTEX_SHADER, vertexGlsl );
16624 var glFragmentShader = WebGLShader( gl, gl.FRAGMENT_SHADER, fragmentGlsl );
16625
16626 gl.attachShader( program, glVertexShader );
16627 gl.attachShader( program, glFragmentShader );
16628
16629 // Force a particular attribute to index 0.
16630
16631 if ( material.index0AttributeName !== undefined ) {
16632
16633 gl.bindAttribLocation( program, 0, material.index0AttributeName );
16634
16635 } else if ( parameters.morphTargets === true ) {
16636
16637 // programs with morphTargets displace position out of attribute 0
16638 gl.bindAttribLocation( program, 0, 'position' );
16639
16640 }
16641
16642 gl.linkProgram( program );
16643
16644 var programLog = gl.getProgramInfoLog( program ).trim();
16645 var vertexLog = gl.getShaderInfoLog( glVertexShader ).trim();
16646 var fragmentLog = gl.getShaderInfoLog( glFragmentShader ).trim();
16647
16648 var runnable = true;
16649 var haveDiagnostics = true;
16650
16651 // console.log( '**VERTEX**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( glVertexShader ) );
16652 // console.log( '**FRAGMENT**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( glFragmentShader ) );
16653
16654 if ( gl.getProgramParameter( program, gl.LINK_STATUS ) === false ) {
16655
16656 runnable = false;
16657
16658 console.error( 'THREE.WebGLProgram: shader error: ', gl.getError(), 'gl.VALIDATE_STATUS', gl.getProgramParameter( program, gl.VALIDATE_STATUS ), 'gl.getProgramInfoLog', programLog, vertexLog, fragmentLog );
16659
16660 } else if ( programLog !== '' ) {
16661
16662 console.warn( 'THREE.WebGLProgram: gl.getProgramInfoLog()', programLog );
16663
16664 } else if ( vertexLog === '' || fragmentLog === '' ) {
16665
16666 haveDiagnostics = false;
16667
16668 }
16669
16670 if ( haveDiagnostics ) {
16671
16672 this.diagnostics = {
16673
16674 runnable: runnable,
16675 material: material,
16676
16677 programLog: programLog,
16678
16679 vertexShader: {
16680
16681 log: vertexLog,
16682 prefix: prefixVertex
16683
16684 },
16685
16686 fragmentShader: {
16687
16688 log: fragmentLog,
16689 prefix: prefixFragment
16690
16691 }
16692
16693 };
16694
16695 }
16696
16697 // clean up
16698
16699 gl.deleteShader( glVertexShader );
16700 gl.deleteShader( glFragmentShader );
16701
16702 // set up caching for uniform locations
16703
16704 var cachedUniforms;
16705
16706 this.getUniforms = function () {
16707
16708 if ( cachedUniforms === undefined ) {
16709
16710 cachedUniforms = new WebGLUniforms( gl, program, renderer );
16711
16712 }
16713
16714 return cachedUniforms;
16715
16716 };
16717
16718 // set up caching for attribute locations
16719
16720 var cachedAttributes;
16721
16722 this.getAttributes = function () {
16723
16724 if ( cachedAttributes === undefined ) {
16725
16726 cachedAttributes = fetchAttributeLocations( gl, program );
16727
16728 }
16729
16730 return cachedAttributes;
16731
16732 };
16733
16734 // free resource
16735
16736 this.destroy = function () {
16737
16738 gl.deleteProgram( program );
16739 this.program = undefined;
16740
16741 };
16742
16743 // DEPRECATED
16744
16745 Object.defineProperties( this, {
16746
16747 uniforms: {
16748 get: function () {
16749
16750 console.warn( 'THREE.WebGLProgram: .uniforms is now .getUniforms().' );
16751 return this.getUniforms();
16752
16753 }
16754 },
16755
16756 attributes: {
16757 get: function () {
16758
16759 console.warn( 'THREE.WebGLProgram: .attributes is now .getAttributes().' );
16760 return this.getAttributes();
16761
16762 }
16763 }
16764
16765 } );
16766
16767
16768 //
16769
16770 this.name = shader.name;
16771 this.id = programIdCount ++;
16772 this.code = code;
16773 this.usedTimes = 1;
16774 this.program = program;
16775 this.vertexShader = glVertexShader;
16776 this.fragmentShader = glFragmentShader;
16777
16778 return this;
16779
16780 }
16781
16782 /**
16783 * @author mrdoob / http://mrdoob.com/
16784 */
16785
16786 function WebGLPrograms( renderer, extensions, capabilities ) {
16787
16788 var programs = [];
16789
16790 var shaderIDs = {
16791 MeshDepthMaterial: 'depth',
16792 MeshDistanceMaterial: 'distanceRGBA',
16793 MeshNormalMaterial: 'normal',
16794 MeshBasicMaterial: 'basic',
16795 MeshLambertMaterial: 'lambert',
16796 MeshPhongMaterial: 'phong',
16797 MeshToonMaterial: 'phong',
16798 MeshStandardMaterial: 'physical',
16799 MeshPhysicalMaterial: 'physical',
16800 LineBasicMaterial: 'basic',
16801 LineDashedMaterial: 'dashed',
16802 PointsMaterial: 'points',
16803 ShadowMaterial: 'shadow'
16804 };
16805
16806 var parameterNames = [
16807 "precision", "supportsVertexTextures", "map", "mapEncoding", "envMap", "envMapMode", "envMapEncoding",
16808 "lightMap", "aoMap", "emissiveMap", "emissiveMapEncoding", "bumpMap", "normalMap", "displacementMap", "specularMap",
16809 "roughnessMap", "metalnessMap", "gradientMap",
16810 "alphaMap", "combine", "vertexColors", "fog", "useFog", "fogExp",
16811 "flatShading", "sizeAttenuation", "logarithmicDepthBuffer", "skinning",
16812 "maxBones", "useVertexTexture", "morphTargets", "morphNormals",
16813 "maxMorphTargets", "maxMorphNormals", "premultipliedAlpha",
16814 "numDirLights", "numPointLights", "numSpotLights", "numHemiLights", "numRectAreaLights",
16815 "shadowMapEnabled", "shadowMapType", "toneMapping", 'physicallyCorrectLights',
16816 "alphaTest", "doubleSided", "flipSided", "numClippingPlanes", "numClipIntersection", "depthPacking", "dithering"
16817 ];
16818
16819
16820 function allocateBones( object ) {
16821
16822 var skeleton = object.skeleton;
16823 var bones = skeleton.bones;
16824
16825 if ( capabilities.floatVertexTextures ) {
16826
16827 return 1024;
16828
16829 } else {
16830
16831 // default for when object is not specified
16832 // ( for example when prebuilding shader to be used with multiple objects )
16833 //
16834 // - leave some extra space for other uniforms
16835 // - limit here is ANGLE's 254 max uniform vectors
16836 // (up to 54 should be safe)
16837
16838 var nVertexUniforms = capabilities.maxVertexUniforms;
16839 var nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 );
16840
16841 var maxBones = Math.min( nVertexMatrices, bones.length );
16842
16843 if ( maxBones < bones.length ) {
16844
16845 console.warn( 'THREE.WebGLRenderer: Skeleton has ' + bones.length + ' bones. This GPU supports ' + maxBones + '.' );
16846 return 0;
16847
16848 }
16849
16850 return maxBones;
16851
16852 }
16853
16854 }
16855
16856 function getTextureEncodingFromMap( map, gammaOverrideLinear ) {
16857
16858 var encoding;
16859
16860 if ( ! map ) {
16861
16862 encoding = LinearEncoding;
16863
16864 } else if ( map.isTexture ) {
16865
16866 encoding = map.encoding;
16867
16868 } else if ( map.isWebGLRenderTarget ) {
16869
16870 console.warn( "THREE.WebGLPrograms.getTextureEncodingFromMap: don't use render targets as textures. Use their .texture property instead." );
16871 encoding = map.texture.encoding;
16872
16873 }
16874
16875 // add backwards compatibility for WebGLRenderer.gammaInput/gammaOutput parameter, should probably be removed at some point.
16876 if ( encoding === LinearEncoding && gammaOverrideLinear ) {
16877
16878 encoding = GammaEncoding;
16879
16880 }
16881
16882 return encoding;
16883
16884 }
16885
16886 this.getParameters = function ( material, lights, shadows, fog, nClipPlanes, nClipIntersection, object ) {
16887
16888 var shaderID = shaderIDs[ material.type ];
16889
16890 // heuristics to create shader parameters according to lights in the scene
16891 // (not to blow over maxLights budget)
16892
16893 var maxBones = object.isSkinnedMesh ? allocateBones( object ) : 0;
16894 var precision = capabilities.precision;
16895
16896 if ( material.precision !== null ) {
16897
16898 precision = capabilities.getMaxPrecision( material.precision );
16899
16900 if ( precision !== material.precision ) {
16901
16902 console.warn( 'THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.' );
16903
16904 }
16905
16906 }
16907
16908 var currentRenderTarget = renderer.getRenderTarget();
16909
16910 var parameters = {
16911
16912 shaderID: shaderID,
16913
16914 precision: precision,
16915 supportsVertexTextures: capabilities.vertexTextures,
16916 outputEncoding: getTextureEncodingFromMap( ( ! currentRenderTarget ) ? null : currentRenderTarget.texture, renderer.gammaOutput ),
16917 map: !! material.map,
16918 mapEncoding: getTextureEncodingFromMap( material.map, renderer.gammaInput ),
16919 envMap: !! material.envMap,
16920 envMapMode: material.envMap && material.envMap.mapping,
16921 envMapEncoding: getTextureEncodingFromMap( material.envMap, renderer.gammaInput ),
16922 envMapCubeUV: ( !! material.envMap ) && ( ( material.envMap.mapping === CubeUVReflectionMapping ) || ( material.envMap.mapping === CubeUVRefractionMapping ) ),
16923 lightMap: !! material.lightMap,
16924 aoMap: !! material.aoMap,
16925 emissiveMap: !! material.emissiveMap,
16926 emissiveMapEncoding: getTextureEncodingFromMap( material.emissiveMap, renderer.gammaInput ),
16927 bumpMap: !! material.bumpMap,
16928 normalMap: !! material.normalMap,
16929 displacementMap: !! material.displacementMap,
16930 roughnessMap: !! material.roughnessMap,
16931 metalnessMap: !! material.metalnessMap,
16932 specularMap: !! material.specularMap,
16933 alphaMap: !! material.alphaMap,
16934
16935 gradientMap: !! material.gradientMap,
16936
16937 combine: material.combine,
16938
16939 vertexColors: material.vertexColors,
16940
16941 fog: !! fog,
16942 useFog: material.fog,
16943 fogExp: ( fog && fog.isFogExp2 ),
16944
16945 flatShading: material.flatShading,
16946
16947 sizeAttenuation: material.sizeAttenuation,
16948 logarithmicDepthBuffer: capabilities.logarithmicDepthBuffer,
16949
16950 skinning: material.skinning && maxBones > 0,
16951 maxBones: maxBones,
16952 useVertexTexture: capabilities.floatVertexTextures,
16953
16954 morphTargets: material.morphTargets,
16955 morphNormals: material.morphNormals,
16956 maxMorphTargets: renderer.maxMorphTargets,
16957 maxMorphNormals: renderer.maxMorphNormals,
16958
16959 numDirLights: lights.directional.length,
16960 numPointLights: lights.point.length,
16961 numSpotLights: lights.spot.length,
16962 numRectAreaLights: lights.rectArea.length,
16963 numHemiLights: lights.hemi.length,
16964
16965 numClippingPlanes: nClipPlanes,
16966 numClipIntersection: nClipIntersection,
16967
16968 dithering: material.dithering,
16969
16970 shadowMapEnabled: renderer.shadowMap.enabled && object.receiveShadow && shadows.length > 0,
16971 shadowMapType: renderer.shadowMap.type,
16972
16973 toneMapping: renderer.toneMapping,
16974 physicallyCorrectLights: renderer.physicallyCorrectLights,
16975
16976 premultipliedAlpha: material.premultipliedAlpha,
16977
16978 alphaTest: material.alphaTest,
16979 doubleSided: material.side === DoubleSide,
16980 flipSided: material.side === BackSide,
16981
16982 depthPacking: ( material.depthPacking !== undefined ) ? material.depthPacking : false
16983
16984 };
16985
16986 return parameters;
16987
16988 };
16989
16990 this.getProgramCode = function ( material, parameters ) {
16991
16992 var array = [];
16993
16994 if ( parameters.shaderID ) {
16995
16996 array.push( parameters.shaderID );
16997
16998 } else {
16999
17000 array.push( material.fragmentShader );
17001 array.push( material.vertexShader );
17002
17003 }
17004
17005 if ( material.defines !== undefined ) {
17006
17007 for ( var name in material.defines ) {
17008
17009 array.push( name );
17010 array.push( material.defines[ name ] );
17011
17012 }
17013
17014 }
17015
17016 for ( var i = 0; i < parameterNames.length; i ++ ) {
17017
17018 array.push( parameters[ parameterNames[ i ] ] );
17019
17020 }
17021
17022 array.push( material.onBeforeCompile.toString() );
17023
17024 array.push( renderer.gammaOutput );
17025
17026 return array.join();
17027
17028 };
17029
17030 this.acquireProgram = function ( material, shader, parameters, code ) {
17031
17032 var program;
17033
17034 // Check if code has been already compiled
17035 for ( var p = 0, pl = programs.length; p < pl; p ++ ) {
17036
17037 var programInfo = programs[ p ];
17038
17039 if ( programInfo.code === code ) {
17040
17041 program = programInfo;
17042 ++ program.usedTimes;
17043
17044 break;
17045
17046 }
17047
17048 }
17049
17050 if ( program === undefined ) {
17051
17052 program = new WebGLProgram( renderer, extensions, code, material, shader, parameters );
17053 programs.push( program );
17054
17055 }
17056
17057 return program;
17058
17059 };
17060
17061 this.releaseProgram = function ( program ) {
17062
17063 if ( -- program.usedTimes === 0 ) {
17064
17065 // Remove from unordered set
17066 var i = programs.indexOf( program );
17067 programs[ i ] = programs[ programs.length - 1 ];
17068 programs.pop();
17069
17070 // Free WebGL resources
17071 program.destroy();
17072
17073 }
17074
17075 };
17076
17077 // Exposed for resource monitoring & error feedback via renderer.info:
17078 this.programs = programs;
17079
17080 }
17081
17082 /**
17083 * @author fordacious / fordacious.github.io
17084 */
17085
17086 function WebGLProperties() {
17087
17088 var properties = new WeakMap();
17089
17090 function get( object ) {
17091
17092 var map = properties.get( object );
17093
17094 if ( map === undefined ) {
17095
17096 map = {};
17097 properties.set( object, map );
17098
17099 }
17100
17101 return map;
17102
17103 }
17104
17105 function remove( object ) {
17106
17107 properties.delete( object );
17108
17109 }
17110
17111 function update( object, key, value ) {
17112
17113 properties.get( object )[ key ] = value;
17114
17115 }
17116
17117 function dispose() {
17118
17119 properties = new WeakMap();
17120
17121 }
17122
17123 return {
17124 get: get,
17125 remove: remove,
17126 update: update,
17127 dispose: dispose
17128 };
17129
17130 }
17131
17132 /**
17133 * @author mrdoob / http://mrdoob.com/
17134 */
17135
17136 function painterSortStable( a, b ) {
17137
17138 if ( a.renderOrder !== b.renderOrder ) {
17139
17140 return a.renderOrder - b.renderOrder;
17141
17142 } else if ( a.program && b.program && a.program !== b.program ) {
17143
17144 return a.program.id - b.program.id;
17145
17146 } else if ( a.material.id !== b.material.id ) {
17147
17148 return a.material.id - b.material.id;
17149
17150 } else if ( a.z !== b.z ) {
17151
17152 return a.z - b.z;
17153
17154 } else {
17155
17156 return a.id - b.id;
17157
17158 }
17159
17160 }
17161
17162 function reversePainterSortStable( a, b ) {
17163
17164 if ( a.renderOrder !== b.renderOrder ) {
17165
17166 return a.renderOrder - b.renderOrder;
17167
17168 } if ( a.z !== b.z ) {
17169
17170 return b.z - a.z;
17171
17172 } else {
17173
17174 return a.id - b.id;
17175
17176 }
17177
17178 }
17179
17180 function WebGLRenderList() {
17181
17182 var renderItems = [];
17183 var renderItemsIndex = 0;
17184
17185 var opaque = [];
17186 var transparent = [];
17187
17188 function init() {
17189
17190 renderItemsIndex = 0;
17191
17192 opaque.length = 0;
17193 transparent.length = 0;
17194
17195 }
17196
17197 function push( object, geometry, material, z, group ) {
17198
17199 var renderItem = renderItems[ renderItemsIndex ];
17200
17201 if ( renderItem === undefined ) {
17202
17203 renderItem = {
17204 id: object.id,
17205 object: object,
17206 geometry: geometry,
17207 material: material,
17208 program: material.program,
17209 renderOrder: object.renderOrder,
17210 z: z,
17211 group: group
17212 };
17213
17214 renderItems[ renderItemsIndex ] = renderItem;
17215
17216 } else {
17217
17218 renderItem.id = object.id;
17219 renderItem.object = object;
17220 renderItem.geometry = geometry;
17221 renderItem.material = material;
17222 renderItem.program = material.program;
17223 renderItem.renderOrder = object.renderOrder;
17224 renderItem.z = z;
17225 renderItem.group = group;
17226
17227 }
17228
17229 ( material.transparent === true ? transparent : opaque ).push( renderItem );
17230
17231 renderItemsIndex ++;
17232
17233 }
17234
17235 function sort() {
17236
17237 if ( opaque.length > 1 ) opaque.sort( painterSortStable );
17238 if ( transparent.length > 1 ) transparent.sort( reversePainterSortStable );
17239
17240 }
17241
17242 return {
17243 opaque: opaque,
17244 transparent: transparent,
17245
17246 init: init,
17247 push: push,
17248
17249 sort: sort
17250 };
17251
17252 }
17253
17254 function WebGLRenderLists() {
17255
17256 var lists = {};
17257
17258 function get( scene, camera ) {
17259
17260 var hash = scene.id + ',' + camera.id;
17261 var list = lists[ hash ];
17262
17263 if ( list === undefined ) {
17264
17265 // console.log( 'THREE.WebGLRenderLists:', hash );
17266
17267 list = new WebGLRenderList();
17268 lists[ hash ] = list;
17269
17270 }
17271
17272 return list;
17273
17274 }
17275
17276 function dispose() {
17277
17278 lists = {};
17279
17280 }
17281
17282 return {
17283 get: get,
17284 dispose: dispose
17285 };
17286
17287 }
17288
17289 /**
17290 * @author mrdoob / http://mrdoob.com/
17291 */
17292
17293 function UniformsCache() {
17294
17295 var lights = {};
17296
17297 return {
17298
17299 get: function ( light ) {
17300
17301 if ( lights[ light.id ] !== undefined ) {
17302
17303 return lights[ light.id ];
17304
17305 }
17306
17307 var uniforms;
17308
17309 switch ( light.type ) {
17310
17311 case 'DirectionalLight':
17312 uniforms = {
17313 direction: new Vector3(),
17314 color: new Color(),
17315
17316 shadow: false,
17317 shadowBias: 0,
17318 shadowRadius: 1,
17319 shadowMapSize: new Vector2()
17320 };
17321 break;
17322
17323 case 'SpotLight':
17324 uniforms = {
17325 position: new Vector3(),
17326 direction: new Vector3(),
17327 color: new Color(),
17328 distance: 0,
17329 coneCos: 0,
17330 penumbraCos: 0,
17331 decay: 0,
17332
17333 shadow: false,
17334 shadowBias: 0,
17335 shadowRadius: 1,
17336 shadowMapSize: new Vector2()
17337 };
17338 break;
17339
17340 case 'PointLight':
17341 uniforms = {
17342 position: new Vector3(),
17343 color: new Color(),
17344 distance: 0,
17345 decay: 0,
17346
17347 shadow: false,
17348 shadowBias: 0,
17349 shadowRadius: 1,
17350 shadowMapSize: new Vector2(),
17351 shadowCameraNear: 1,
17352 shadowCameraFar: 1000
17353 };
17354 break;
17355
17356 case 'HemisphereLight':
17357 uniforms = {
17358 direction: new Vector3(),
17359 skyColor: new Color(),
17360 groundColor: new Color()
17361 };
17362 break;
17363
17364 case 'RectAreaLight':
17365 uniforms = {
17366 color: new Color(),
17367 position: new Vector3(),
17368 halfWidth: new Vector3(),
17369 halfHeight: new Vector3()
17370 // TODO (abelnation): set RectAreaLight shadow uniforms
17371 };
17372 break;
17373
17374 }
17375
17376 lights[ light.id ] = uniforms;
17377
17378 return uniforms;
17379
17380 }
17381
17382 };
17383
17384 }
17385
17386 var count = 0;
17387
17388 function WebGLLights() {
17389
17390 var cache = new UniformsCache();
17391
17392 var state = {
17393
17394 id: count ++,
17395
17396 hash: '',
17397
17398 ambient: [ 0, 0, 0 ],
17399 directional: [],
17400 directionalShadowMap: [],
17401 directionalShadowMatrix: [],
17402 spot: [],
17403 spotShadowMap: [],
17404 spotShadowMatrix: [],
17405 rectArea: [],
17406 point: [],
17407 pointShadowMap: [],
17408 pointShadowMatrix: [],
17409 hemi: []
17410
17411 };
17412
17413 var vector3 = new Vector3();
17414 var matrix4 = new Matrix4();
17415 var matrix42 = new Matrix4();
17416
17417 function setup( lights, shadows, camera ) {
17418
17419 var r = 0, g = 0, b = 0;
17420
17421 var directionalLength = 0;
17422 var pointLength = 0;
17423 var spotLength = 0;
17424 var rectAreaLength = 0;
17425 var hemiLength = 0;
17426
17427 var viewMatrix = camera.matrixWorldInverse;
17428
17429 for ( var i = 0, l = lights.length; i < l; i ++ ) {
17430
17431 var light = lights[ i ];
17432
17433 var color = light.color;
17434 var intensity = light.intensity;
17435 var distance = light.distance;
17436
17437 var shadowMap = ( light.shadow && light.shadow.map ) ? light.shadow.map.texture : null;
17438
17439 if ( light.isAmbientLight ) {
17440
17441 r += color.r * intensity;
17442 g += color.g * intensity;
17443 b += color.b * intensity;
17444
17445 } else if ( light.isDirectionalLight ) {
17446
17447 var uniforms = cache.get( light );
17448
17449 uniforms.color.copy( light.color ).multiplyScalar( light.intensity );
17450 uniforms.direction.setFromMatrixPosition( light.matrixWorld );
17451 vector3.setFromMatrixPosition( light.target.matrixWorld );
17452 uniforms.direction.sub( vector3 );
17453 uniforms.direction.transformDirection( viewMatrix );
17454
17455 uniforms.shadow = light.castShadow;
17456
17457 if ( light.castShadow ) {
17458
17459 var shadow = light.shadow;
17460
17461 uniforms.shadowBias = shadow.bias;
17462 uniforms.shadowRadius = shadow.radius;
17463 uniforms.shadowMapSize = shadow.mapSize;
17464
17465 }
17466
17467 state.directionalShadowMap[ directionalLength ] = shadowMap;
17468 state.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix;
17469 state.directional[ directionalLength ] = uniforms;
17470
17471 directionalLength ++;
17472
17473 } else if ( light.isSpotLight ) {
17474
17475 var uniforms = cache.get( light );
17476
17477 uniforms.position.setFromMatrixPosition( light.matrixWorld );
17478 uniforms.position.applyMatrix4( viewMatrix );
17479
17480 uniforms.color.copy( color ).multiplyScalar( intensity );
17481 uniforms.distance = distance;
17482
17483 uniforms.direction.setFromMatrixPosition( light.matrixWorld );
17484 vector3.setFromMatrixPosition( light.target.matrixWorld );
17485 uniforms.direction.sub( vector3 );
17486 uniforms.direction.transformDirection( viewMatrix );
17487
17488 uniforms.coneCos = Math.cos( light.angle );
17489 uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) );
17490 uniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay;
17491
17492 uniforms.shadow = light.castShadow;
17493
17494 if ( light.castShadow ) {
17495
17496 var shadow = light.shadow;
17497
17498 uniforms.shadowBias = shadow.bias;
17499 uniforms.shadowRadius = shadow.radius;
17500 uniforms.shadowMapSize = shadow.mapSize;
17501
17502 }
17503
17504 state.spotShadowMap[ spotLength ] = shadowMap;
17505 state.spotShadowMatrix[ spotLength ] = light.shadow.matrix;
17506 state.spot[ spotLength ] = uniforms;
17507
17508 spotLength ++;
17509
17510 } else if ( light.isRectAreaLight ) {
17511
17512 var uniforms = cache.get( light );
17513
17514 // (a) intensity is the total visible light emitted
17515 //uniforms.color.copy( color ).multiplyScalar( intensity / ( light.width * light.height * Math.PI ) );
17516
17517 // (b) intensity is the brightness of the light
17518 uniforms.color.copy( color ).multiplyScalar( intensity );
17519
17520 uniforms.position.setFromMatrixPosition( light.matrixWorld );
17521 uniforms.position.applyMatrix4( viewMatrix );
17522
17523 // extract local rotation of light to derive width/height half vectors
17524 matrix42.identity();
17525 matrix4.copy( light.matrixWorld );
17526 matrix4.premultiply( viewMatrix );
17527 matrix42.extractRotation( matrix4 );
17528
17529 uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 );
17530 uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 );
17531
17532 uniforms.halfWidth.applyMatrix4( matrix42 );
17533 uniforms.halfHeight.applyMatrix4( matrix42 );
17534
17535 // TODO (abelnation): RectAreaLight distance?
17536 // uniforms.distance = distance;
17537
17538 state.rectArea[ rectAreaLength ] = uniforms;
17539
17540 rectAreaLength ++;
17541
17542 } else if ( light.isPointLight ) {
17543
17544 var uniforms = cache.get( light );
17545
17546 uniforms.position.setFromMatrixPosition( light.matrixWorld );
17547 uniforms.position.applyMatrix4( viewMatrix );
17548
17549 uniforms.color.copy( light.color ).multiplyScalar( light.intensity );
17550 uniforms.distance = light.distance;
17551 uniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay;
17552
17553 uniforms.shadow = light.castShadow;
17554
17555 if ( light.castShadow ) {
17556
17557 var shadow = light.shadow;
17558
17559 uniforms.shadowBias = shadow.bias;
17560 uniforms.shadowRadius = shadow.radius;
17561 uniforms.shadowMapSize = shadow.mapSize;
17562 uniforms.shadowCameraNear = shadow.camera.near;
17563 uniforms.shadowCameraFar = shadow.camera.far;
17564
17565 }
17566
17567 state.pointShadowMap[ pointLength ] = shadowMap;
17568 state.pointShadowMatrix[ pointLength ] = light.shadow.matrix;
17569 state.point[ pointLength ] = uniforms;
17570
17571 pointLength ++;
17572
17573 } else if ( light.isHemisphereLight ) {
17574
17575 var uniforms = cache.get( light );
17576
17577 uniforms.direction.setFromMatrixPosition( light.matrixWorld );
17578 uniforms.direction.transformDirection( viewMatrix );
17579 uniforms.direction.normalize();
17580
17581 uniforms.skyColor.copy( light.color ).multiplyScalar( intensity );
17582 uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity );
17583
17584 state.hemi[ hemiLength ] = uniforms;
17585
17586 hemiLength ++;
17587
17588 }
17589
17590 }
17591
17592 state.ambient[ 0 ] = r;
17593 state.ambient[ 1 ] = g;
17594 state.ambient[ 2 ] = b;
17595
17596 state.directional.length = directionalLength;
17597 state.spot.length = spotLength;
17598 state.rectArea.length = rectAreaLength;
17599 state.point.length = pointLength;
17600 state.hemi.length = hemiLength;
17601
17602 state.hash = state.id + ',' + directionalLength + ',' + pointLength + ',' + spotLength + ',' + rectAreaLength + ',' + hemiLength + ',' + shadows.length;
17603
17604 }
17605
17606 return {
17607 setup: setup,
17608 state: state
17609 };
17610
17611 }
17612
17613 /**
17614 * @author Mugen87 / https://github.com/Mugen87
17615 */
17616
17617 function WebGLRenderState() {
17618
17619 var lights = new WebGLLights();
17620
17621 var lightsArray = [];
17622 var shadowsArray = [];
17623 var spritesArray = [];
17624
17625 function init() {
17626
17627 lightsArray.length = 0;
17628 shadowsArray.length = 0;
17629 spritesArray.length = 0;
17630
17631 }
17632
17633 function pushLight( light ) {
17634
17635 lightsArray.push( light );
17636
17637 }
17638
17639 function pushShadow( shadowLight ) {
17640
17641 shadowsArray.push( shadowLight );
17642
17643 }
17644
17645 function pushSprite( shadowLight ) {
17646
17647 spritesArray.push( shadowLight );
17648
17649 }
17650
17651 function setupLights( camera ) {
17652
17653 lights.setup( lightsArray, shadowsArray, camera );
17654
17655 }
17656
17657 var state = {
17658 lightsArray: lightsArray,
17659 shadowsArray: shadowsArray,
17660 spritesArray: spritesArray,
17661
17662 lights: lights
17663 };
17664
17665 return {
17666 init: init,
17667 state: state,
17668 setupLights: setupLights,
17669
17670 pushLight: pushLight,
17671 pushShadow: pushShadow,
17672 pushSprite: pushSprite
17673 };
17674
17675 }
17676
17677 function WebGLRenderStates() {
17678
17679 var renderStates = {};
17680
17681 function get( scene, camera ) {
17682
17683 var hash = scene.id + ',' + camera.id;
17684
17685 var renderState = renderStates[ hash ];
17686
17687 if ( renderState === undefined ) {
17688
17689 renderState = new WebGLRenderState();
17690 renderStates[ hash ] = renderState;
17691
17692 }
17693
17694 return renderState;
17695
17696 }
17697
17698 function dispose() {
17699
17700 renderStates = {};
17701
17702 }
17703
17704 return {
17705 get: get,
17706 dispose: dispose
17707 };
17708
17709 }
17710
17711 /**
17712 * @author mrdoob / http://mrdoob.com/
17713 * @author alteredq / http://alteredqualia.com/
17714 * @author bhouston / https://clara.io
17715 * @author WestLangley / http://github.com/WestLangley
17716 *
17717 * parameters = {
17718 *
17719 * opacity: <float>,
17720 *
17721 * map: new THREE.Texture( <Image> ),
17722 *
17723 * alphaMap: new THREE.Texture( <Image> ),
17724 *
17725 * displacementMap: new THREE.Texture( <Image> ),
17726 * displacementScale: <float>,
17727 * displacementBias: <float>,
17728 *
17729 * wireframe: <boolean>,
17730 * wireframeLinewidth: <float>
17731 * }
17732 */
17733
17734 function MeshDepthMaterial( parameters ) {
17735
17736 Material.call( this );
17737
17738 this.type = 'MeshDepthMaterial';
17739
17740 this.depthPacking = BasicDepthPacking;
17741
17742 this.skinning = false;
17743 this.morphTargets = false;
17744
17745 this.map = null;
17746
17747 this.alphaMap = null;
17748
17749 this.displacementMap = null;
17750 this.displacementScale = 1;
17751 this.displacementBias = 0;
17752
17753 this.wireframe = false;
17754 this.wireframeLinewidth = 1;
17755
17756 this.fog = false;
17757 this.lights = false;
17758
17759 this.setValues( parameters );
17760
17761 }
17762
17763 MeshDepthMaterial.prototype = Object.create( Material.prototype );
17764 MeshDepthMaterial.prototype.constructor = MeshDepthMaterial;
17765
17766 MeshDepthMaterial.prototype.isMeshDepthMaterial = true;
17767
17768 MeshDepthMaterial.prototype.copy = function ( source ) {
17769
17770 Material.prototype.copy.call( this, source );
17771
17772 this.depthPacking = source.depthPacking;
17773
17774 this.skinning = source.skinning;
17775 this.morphTargets = source.morphTargets;
17776
17777 this.map = source.map;
17778
17779 this.alphaMap = source.alphaMap;
17780
17781 this.displacementMap = source.displacementMap;
17782 this.displacementScale = source.displacementScale;
17783 this.displacementBias = source.displacementBias;
17784
17785 this.wireframe = source.wireframe;
17786 this.wireframeLinewidth = source.wireframeLinewidth;
17787
17788 return this;
17789
17790 };
17791
17792 /**
17793 * @author WestLangley / http://github.com/WestLangley
17794 *
17795 * parameters = {
17796 *
17797 * referencePosition: <float>,
17798 * nearDistance: <float>,
17799 * farDistance: <float>,
17800 *
17801 * skinning: <bool>,
17802 * morphTargets: <bool>,
17803 *
17804 * map: new THREE.Texture( <Image> ),
17805 *
17806 * alphaMap: new THREE.Texture( <Image> ),
17807 *
17808 * displacementMap: new THREE.Texture( <Image> ),
17809 * displacementScale: <float>,
17810 * displacementBias: <float>
17811 *
17812 * }
17813 */
17814
17815 function MeshDistanceMaterial( parameters ) {
17816
17817 Material.call( this );
17818
17819 this.type = 'MeshDistanceMaterial';
17820
17821 this.referencePosition = new Vector3();
17822 this.nearDistance = 1;
17823 this.farDistance = 1000;
17824
17825 this.skinning = false;
17826 this.morphTargets = false;
17827
17828 this.map = null;
17829
17830 this.alphaMap = null;
17831
17832 this.displacementMap = null;
17833 this.displacementScale = 1;
17834 this.displacementBias = 0;
17835
17836 this.fog = false;
17837 this.lights = false;
17838
17839 this.setValues( parameters );
17840
17841 }
17842
17843 MeshDistanceMaterial.prototype = Object.create( Material.prototype );
17844 MeshDistanceMaterial.prototype.constructor = MeshDistanceMaterial;
17845
17846 MeshDistanceMaterial.prototype.isMeshDistanceMaterial = true;
17847
17848 MeshDistanceMaterial.prototype.copy = function ( source ) {
17849
17850 Material.prototype.copy.call( this, source );
17851
17852 this.referencePosition.copy( source.referencePosition );
17853 this.nearDistance = source.nearDistance;
17854 this.farDistance = source.farDistance;
17855
17856 this.skinning = source.skinning;
17857 this.morphTargets = source.morphTargets;
17858
17859 this.map = source.map;
17860
17861 this.alphaMap = source.alphaMap;
17862
17863 this.displacementMap = source.displacementMap;
17864 this.displacementScale = source.displacementScale;
17865 this.displacementBias = source.displacementBias;
17866
17867 return this;
17868
17869 };
17870
17871 /**
17872 * @author alteredq / http://alteredqualia.com/
17873 * @author mrdoob / http://mrdoob.com/
17874 */
17875
17876 function WebGLShadowMap( _renderer, _objects, maxTextureSize ) {
17877
17878 var _frustum = new Frustum(),
17879 _projScreenMatrix = new Matrix4(),
17880
17881 _shadowMapSize = new Vector2(),
17882 _maxShadowMapSize = new Vector2( maxTextureSize, maxTextureSize ),
17883
17884 _lookTarget = new Vector3(),
17885 _lightPositionWorld = new Vector3(),
17886
17887 _MorphingFlag = 1,
17888 _SkinningFlag = 2,
17889
17890 _NumberOfMaterialVariants = ( _MorphingFlag | _SkinningFlag ) + 1,
17891
17892 _depthMaterials = new Array( _NumberOfMaterialVariants ),
17893 _distanceMaterials = new Array( _NumberOfMaterialVariants ),
17894
17895 _materialCache = {};
17896
17897 var shadowSide = { 0: BackSide, 1: FrontSide, 2: DoubleSide };
17898
17899 var cubeDirections = [
17900 new Vector3( 1, 0, 0 ), new Vector3( - 1, 0, 0 ), new Vector3( 0, 0, 1 ),
17901 new Vector3( 0, 0, - 1 ), new Vector3( 0, 1, 0 ), new Vector3( 0, - 1, 0 )
17902 ];
17903
17904 var cubeUps = [
17905 new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ),
17906 new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ), new Vector3( 0, 0, - 1 )
17907 ];
17908
17909 var cube2DViewPorts = [
17910 new Vector4(), new Vector4(), new Vector4(),
17911 new Vector4(), new Vector4(), new Vector4()
17912 ];
17913
17914 // init
17915
17916 for ( var i = 0; i !== _NumberOfMaterialVariants; ++ i ) {
17917
17918 var useMorphing = ( i & _MorphingFlag ) !== 0;
17919 var useSkinning = ( i & _SkinningFlag ) !== 0;
17920
17921 var depthMaterial = new MeshDepthMaterial( {
17922
17923 depthPacking: RGBADepthPacking,
17924
17925 morphTargets: useMorphing,
17926 skinning: useSkinning
17927
17928 } );
17929
17930 _depthMaterials[ i ] = depthMaterial;
17931
17932 //
17933
17934 var distanceMaterial = new MeshDistanceMaterial( {
17935
17936 morphTargets: useMorphing,
17937 skinning: useSkinning
17938
17939 } );
17940
17941 _distanceMaterials[ i ] = distanceMaterial;
17942
17943 }
17944
17945 //
17946
17947 var scope = this;
17948
17949 this.enabled = false;
17950
17951 this.autoUpdate = true;
17952 this.needsUpdate = false;
17953
17954 this.type = PCFShadowMap;
17955
17956 this.render = function ( lights, scene, camera ) {
17957
17958 if ( scope.enabled === false ) return;
17959 if ( scope.autoUpdate === false && scope.needsUpdate === false ) return;
17960
17961 if ( lights.length === 0 ) return;
17962
17963 // TODO Clean up (needed in case of contextlost)
17964 var _gl = _renderer.context;
17965 var _state = _renderer.state;
17966
17967 // Set GL state for depth map.
17968 _state.disable( _gl.BLEND );
17969 _state.buffers.color.setClear( 1, 1, 1, 1 );
17970 _state.buffers.depth.setTest( true );
17971 _state.setScissorTest( false );
17972
17973 // render depth map
17974
17975 var faceCount;
17976
17977 for ( var i = 0, il = lights.length; i < il; i ++ ) {
17978
17979 var light = lights[ i ];
17980 var shadow = light.shadow;
17981 var isPointLight = light && light.isPointLight;
17982
17983 if ( shadow === undefined ) {
17984
17985 console.warn( 'THREE.WebGLShadowMap:', light, 'has no shadow.' );
17986 continue;
17987
17988 }
17989
17990 var shadowCamera = shadow.camera;
17991
17992 _shadowMapSize.copy( shadow.mapSize );
17993 _shadowMapSize.min( _maxShadowMapSize );
17994
17995 if ( isPointLight ) {
17996
17997 var vpWidth = _shadowMapSize.x;
17998 var vpHeight = _shadowMapSize.y;
17999
18000 // These viewports map a cube-map onto a 2D texture with the
18001 // following orientation:
18002 //
18003 // xzXZ
18004 // y Y
18005 //
18006 // X - Positive x direction
18007 // x - Negative x direction
18008 // Y - Positive y direction
18009 // y - Negative y direction
18010 // Z - Positive z direction
18011 // z - Negative z direction
18012
18013 // positive X
18014 cube2DViewPorts[ 0 ].set( vpWidth * 2, vpHeight, vpWidth, vpHeight );
18015 // negative X
18016 cube2DViewPorts[ 1 ].set( 0, vpHeight, vpWidth, vpHeight );
18017 // positive Z
18018 cube2DViewPorts[ 2 ].set( vpWidth * 3, vpHeight, vpWidth, vpHeight );
18019 // negative Z
18020 cube2DViewPorts[ 3 ].set( vpWidth, vpHeight, vpWidth, vpHeight );
18021 // positive Y
18022 cube2DViewPorts[ 4 ].set( vpWidth * 3, 0, vpWidth, vpHeight );
18023 // negative Y
18024 cube2DViewPorts[ 5 ].set( vpWidth, 0, vpWidth, vpHeight );
18025
18026 _shadowMapSize.x *= 4.0;
18027 _shadowMapSize.y *= 2.0;
18028
18029 }
18030
18031 if ( shadow.map === null ) {
18032
18033 var pars = { minFilter: NearestFilter, magFilter: NearestFilter, format: RGBAFormat };
18034
18035 shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );
18036 shadow.map.texture.name = light.name + ".shadowMap";
18037
18038 shadowCamera.updateProjectionMatrix();
18039
18040 }
18041
18042 if ( shadow.isSpotLightShadow ) {
18043
18044 shadow.update( light );
18045
18046 }
18047
18048 var shadowMap = shadow.map;
18049 var shadowMatrix = shadow.matrix;
18050
18051 _lightPositionWorld.setFromMatrixPosition( light.matrixWorld );
18052 shadowCamera.position.copy( _lightPositionWorld );
18053
18054 if ( isPointLight ) {
18055
18056 faceCount = 6;
18057
18058 // for point lights we set the shadow matrix to be a translation-only matrix
18059 // equal to inverse of the light's position
18060
18061 shadowMatrix.makeTranslation( - _lightPositionWorld.x, - _lightPositionWorld.y, - _lightPositionWorld.z );
18062
18063 } else {
18064
18065 faceCount = 1;
18066
18067 _lookTarget.setFromMatrixPosition( light.target.matrixWorld );
18068 shadowCamera.lookAt( _lookTarget );
18069 shadowCamera.updateMatrixWorld();
18070
18071 // compute shadow matrix
18072
18073 shadowMatrix.set(
18074 0.5, 0.0, 0.0, 0.5,
18075 0.0, 0.5, 0.0, 0.5,
18076 0.0, 0.0, 0.5, 0.5,
18077 0.0, 0.0, 0.0, 1.0
18078 );
18079
18080 shadowMatrix.multiply( shadowCamera.projectionMatrix );
18081 shadowMatrix.multiply( shadowCamera.matrixWorldInverse );
18082
18083 }
18084
18085 _renderer.setRenderTarget( shadowMap );
18086 _renderer.clear();
18087
18088 // render shadow map for each cube face (if omni-directional) or
18089 // run a single pass if not
18090
18091 for ( var face = 0; face < faceCount; face ++ ) {
18092
18093 if ( isPointLight ) {
18094
18095 _lookTarget.copy( shadowCamera.position );
18096 _lookTarget.add( cubeDirections[ face ] );
18097 shadowCamera.up.copy( cubeUps[ face ] );
18098 shadowCamera.lookAt( _lookTarget );
18099 shadowCamera.updateMatrixWorld();
18100
18101 var vpDimensions = cube2DViewPorts[ face ];
18102 _state.viewport( vpDimensions );
18103
18104 }
18105
18106 // update camera matrices and frustum
18107
18108 _projScreenMatrix.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse );
18109 _frustum.setFromMatrix( _projScreenMatrix );
18110
18111 // set object matrices & frustum culling
18112
18113 renderObject( scene, camera, shadowCamera, isPointLight );
18114
18115 }
18116
18117 }
18118
18119 scope.needsUpdate = false;
18120
18121 };
18122
18123 function getDepthMaterial( object, material, isPointLight, lightPositionWorld, shadowCameraNear, shadowCameraFar ) {
18124
18125 var geometry = object.geometry;
18126
18127 var result = null;
18128
18129 var materialVariants = _depthMaterials;
18130 var customMaterial = object.customDepthMaterial;
18131
18132 if ( isPointLight ) {
18133
18134 materialVariants = _distanceMaterials;
18135 customMaterial = object.customDistanceMaterial;
18136
18137 }
18138
18139 if ( ! customMaterial ) {
18140
18141 var useMorphing = false;
18142
18143 if ( material.morphTargets ) {
18144
18145 if ( geometry && geometry.isBufferGeometry ) {
18146
18147 useMorphing = geometry.morphAttributes && geometry.morphAttributes.position && geometry.morphAttributes.position.length > 0;
18148
18149 } else if ( geometry && geometry.isGeometry ) {
18150
18151 useMorphing = geometry.morphTargets && geometry.morphTargets.length > 0;
18152
18153 }
18154
18155 }
18156
18157 if ( object.isSkinnedMesh && material.skinning === false ) {
18158
18159 console.warn( 'THREE.WebGLShadowMap: THREE.SkinnedMesh with material.skinning set to false:', object );
18160
18161 }
18162
18163 var useSkinning = object.isSkinnedMesh && material.skinning;
18164
18165 var variantIndex = 0;
18166
18167 if ( useMorphing ) variantIndex |= _MorphingFlag;
18168 if ( useSkinning ) variantIndex |= _SkinningFlag;
18169
18170 result = materialVariants[ variantIndex ];
18171
18172 } else {
18173
18174 result = customMaterial;
18175
18176 }
18177
18178 if ( _renderer.localClippingEnabled &&
18179 material.clipShadows === true &&
18180 material.clippingPlanes.length !== 0 ) {
18181
18182 // in this case we need a unique material instance reflecting the
18183 // appropriate state
18184
18185 var keyA = result.uuid, keyB = material.uuid;
18186
18187 var materialsForVariant = _materialCache[ keyA ];
18188
18189 if ( materialsForVariant === undefined ) {
18190
18191 materialsForVariant = {};
18192 _materialCache[ keyA ] = materialsForVariant;
18193
18194 }
18195
18196 var cachedMaterial = materialsForVariant[ keyB ];
18197
18198 if ( cachedMaterial === undefined ) {
18199
18200 cachedMaterial = result.clone();
18201 materialsForVariant[ keyB ] = cachedMaterial;
18202
18203 }
18204
18205 result = cachedMaterial;
18206
18207 }
18208
18209 result.visible = material.visible;
18210 result.wireframe = material.wireframe;
18211
18212 result.side = ( material.shadowSide != null ) ? material.shadowSide : shadowSide[ material.side ];
18213
18214 result.clipShadows = material.clipShadows;
18215 result.clippingPlanes = material.clippingPlanes;
18216 result.clipIntersection = material.clipIntersection;
18217
18218 result.wireframeLinewidth = material.wireframeLinewidth;
18219 result.linewidth = material.linewidth;
18220
18221 if ( isPointLight && result.isMeshDistanceMaterial ) {
18222
18223 result.referencePosition.copy( lightPositionWorld );
18224 result.nearDistance = shadowCameraNear;
18225 result.farDistance = shadowCameraFar;
18226
18227 }
18228
18229 return result;
18230
18231 }
18232
18233 function renderObject( object, camera, shadowCamera, isPointLight ) {
18234
18235 if ( object.visible === false ) return;
18236
18237 var visible = object.layers.test( camera.layers );
18238
18239 if ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) {
18240
18241 if ( object.castShadow && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) {
18242
18243 object.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld );
18244
18245 var geometry = _objects.update( object );
18246 var material = object.material;
18247
18248 if ( Array.isArray( material ) ) {
18249
18250 var groups = geometry.groups;
18251
18252 for ( var k = 0, kl = groups.length; k < kl; k ++ ) {
18253
18254 var group = groups[ k ];
18255 var groupMaterial = material[ group.materialIndex ];
18256
18257 if ( groupMaterial && groupMaterial.visible ) {
18258
18259 var depthMaterial = getDepthMaterial( object, groupMaterial, isPointLight, _lightPositionWorld, shadowCamera.near, shadowCamera.far );
18260 _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group );
18261
18262 }
18263
18264 }
18265
18266 } else if ( material.visible ) {
18267
18268 var depthMaterial = getDepthMaterial( object, material, isPointLight, _lightPositionWorld, shadowCamera.near, shadowCamera.far );
18269 _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null );
18270
18271 }
18272
18273 }
18274
18275 }
18276
18277 var children = object.children;
18278
18279 for ( var i = 0, l = children.length; i < l; i ++ ) {
18280
18281 renderObject( children[ i ], camera, shadowCamera, isPointLight );
18282
18283 }
18284
18285 }
18286
18287 }
18288
18289 /**
18290 * @author mrdoob / http://mrdoob.com/
18291 */
18292
18293 function CanvasTexture( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
18294
18295 Texture.call( this, canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
18296
18297 this.needsUpdate = true;
18298
18299 }
18300
18301 CanvasTexture.prototype = Object.create( Texture.prototype );
18302 CanvasTexture.prototype.constructor = CanvasTexture;
18303
18304 /**
18305 * @author mikael emtinger / http://gomo.se/
18306 * @author alteredq / http://alteredqualia.com/
18307 */
18308
18309 function WebGLSpriteRenderer( renderer, gl, state, textures, capabilities ) {
18310
18311 var vertexBuffer, elementBuffer;
18312 var program, attributes, uniforms;
18313
18314 var texture;
18315
18316 // decompose matrixWorld
18317
18318 var spritePosition = new Vector3();
18319 var spriteRotation = new Quaternion();
18320 var spriteScale = new Vector3();
18321
18322 function init() {
18323
18324 var vertices = new Float32Array( [
18325 - 0.5, - 0.5, 0, 0,
18326 0.5, - 0.5, 1, 0,
18327 0.5, 0.5, 1, 1,
18328 - 0.5, 0.5, 0, 1
18329 ] );
18330
18331 var faces = new Uint16Array( [
18332 0, 1, 2,
18333 0, 2, 3
18334 ] );
18335
18336 vertexBuffer = gl.createBuffer();
18337 elementBuffer = gl.createBuffer();
18338
18339 gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer );
18340 gl.bufferData( gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW );
18341
18342 gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer );
18343 gl.bufferData( gl.ELEMENT_ARRAY_BUFFER, faces, gl.STATIC_DRAW );
18344
18345 program = createProgram();
18346
18347 attributes = {
18348 position: gl.getAttribLocation( program, 'position' ),
18349 uv: gl.getAttribLocation( program, 'uv' )
18350 };
18351
18352 uniforms = {
18353 uvOffset: gl.getUniformLocation( program, 'uvOffset' ),
18354 uvScale: gl.getUniformLocation( program, 'uvScale' ),
18355
18356 rotation: gl.getUniformLocation( program, 'rotation' ),
18357 center: gl.getUniformLocation( program, 'center' ),
18358 scale: gl.getUniformLocation( program, 'scale' ),
18359
18360 color: gl.getUniformLocation( program, 'color' ),
18361 map: gl.getUniformLocation( program, 'map' ),
18362 opacity: gl.getUniformLocation( program, 'opacity' ),
18363
18364 modelViewMatrix: gl.getUniformLocation( program, 'modelViewMatrix' ),
18365 projectionMatrix: gl.getUniformLocation( program, 'projectionMatrix' ),
18366
18367 fogType: gl.getUniformLocation( program, 'fogType' ),
18368 fogDensity: gl.getUniformLocation( program, 'fogDensity' ),
18369 fogNear: gl.getUniformLocation( program, 'fogNear' ),
18370 fogFar: gl.getUniformLocation( program, 'fogFar' ),
18371 fogColor: gl.getUniformLocation( program, 'fogColor' ),
18372 fogDepth: gl.getUniformLocation( program, 'fogDepth' ),
18373
18374 alphaTest: gl.getUniformLocation( program, 'alphaTest' )
18375 };
18376
18377 var canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
18378 canvas.width = 8;
18379 canvas.height = 8;
18380
18381 var context = canvas.getContext( '2d' );
18382 context.fillStyle = 'white';
18383 context.fillRect( 0, 0, 8, 8 );
18384
18385 texture = new CanvasTexture( canvas );
18386
18387 }
18388
18389 this.render = function ( sprites, scene, camera ) {
18390
18391 if ( sprites.length === 0 ) return;
18392
18393 // setup gl
18394
18395 if ( program === undefined ) {
18396
18397 init();
18398
18399 }
18400
18401 state.useProgram( program );
18402
18403 state.initAttributes();
18404 state.enableAttribute( attributes.position );
18405 state.enableAttribute( attributes.uv );
18406 state.disableUnusedAttributes();
18407
18408 state.disable( gl.CULL_FACE );
18409 state.enable( gl.BLEND );
18410
18411 gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer );
18412 gl.vertexAttribPointer( attributes.position, 2, gl.FLOAT, false, 2 * 8, 0 );
18413 gl.vertexAttribPointer( attributes.uv, 2, gl.FLOAT, false, 2 * 8, 8 );
18414
18415 gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer );
18416
18417 gl.uniformMatrix4fv( uniforms.projectionMatrix, false, camera.projectionMatrix.elements );
18418
18419 state.activeTexture( gl.TEXTURE0 );
18420 gl.uniform1i( uniforms.map, 0 );
18421
18422 var oldFogType = 0;
18423 var sceneFogType = 0;
18424 var fog = scene.fog;
18425
18426 if ( fog ) {
18427
18428 gl.uniform3f( uniforms.fogColor, fog.color.r, fog.color.g, fog.color.b );
18429
18430 if ( fog.isFog ) {
18431
18432 gl.uniform1f( uniforms.fogNear, fog.near );
18433 gl.uniform1f( uniforms.fogFar, fog.far );
18434
18435 gl.uniform1i( uniforms.fogType, 1 );
18436 oldFogType = 1;
18437 sceneFogType = 1;
18438
18439 } else if ( fog.isFogExp2 ) {
18440
18441 gl.uniform1f( uniforms.fogDensity, fog.density );
18442
18443 gl.uniform1i( uniforms.fogType, 2 );
18444 oldFogType = 2;
18445 sceneFogType = 2;
18446
18447 }
18448
18449 } else {
18450
18451 gl.uniform1i( uniforms.fogType, 0 );
18452 oldFogType = 0;
18453 sceneFogType = 0;
18454
18455 }
18456
18457
18458 // update positions and sort
18459
18460 for ( var i = 0, l = sprites.length; i < l; i ++ ) {
18461
18462 var sprite = sprites[ i ];
18463
18464 sprite.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, sprite.matrixWorld );
18465 sprite.z = - sprite.modelViewMatrix.elements[ 14 ];
18466
18467 }
18468
18469 sprites.sort( painterSortStable );
18470
18471 // render all sprites
18472
18473 var scale = [];
18474 var center = [];
18475
18476 for ( var i = 0, l = sprites.length; i < l; i ++ ) {
18477
18478 var sprite = sprites[ i ];
18479 var material = sprite.material;
18480
18481 if ( material.visible === false ) continue;
18482
18483 sprite.onBeforeRender( renderer, scene, camera, undefined, material, undefined );
18484
18485 gl.uniform1f( uniforms.alphaTest, material.alphaTest );
18486 gl.uniformMatrix4fv( uniforms.modelViewMatrix, false, sprite.modelViewMatrix.elements );
18487
18488 sprite.matrixWorld.decompose( spritePosition, spriteRotation, spriteScale );
18489
18490 scale[ 0 ] = spriteScale.x;
18491 scale[ 1 ] = spriteScale.y;
18492
18493 center[ 0 ] = sprite.center.x - 0.5;
18494 center[ 1 ] = sprite.center.y - 0.5;
18495
18496 var fogType = 0;
18497
18498 if ( scene.fog && material.fog ) {
18499
18500 fogType = sceneFogType;
18501
18502 }
18503
18504 if ( oldFogType !== fogType ) {
18505
18506 gl.uniform1i( uniforms.fogType, fogType );
18507 oldFogType = fogType;
18508
18509 }
18510
18511 if ( material.map !== null ) {
18512
18513 gl.uniform2f( uniforms.uvOffset, material.map.offset.x, material.map.offset.y );
18514 gl.uniform2f( uniforms.uvScale, material.map.repeat.x, material.map.repeat.y );
18515
18516 } else {
18517
18518 gl.uniform2f( uniforms.uvOffset, 0, 0 );
18519 gl.uniform2f( uniforms.uvScale, 1, 1 );
18520
18521 }
18522
18523 gl.uniform1f( uniforms.opacity, material.opacity );
18524 gl.uniform3f( uniforms.color, material.color.r, material.color.g, material.color.b );
18525
18526 gl.uniform1f( uniforms.rotation, material.rotation );
18527 gl.uniform2fv( uniforms.center, center );
18528 gl.uniform2fv( uniforms.scale, scale );
18529
18530 state.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha );
18531 state.buffers.depth.setTest( material.depthTest );
18532 state.buffers.depth.setMask( material.depthWrite );
18533 state.buffers.color.setMask( material.colorWrite );
18534
18535 textures.setTexture2D( material.map || texture, 0 );
18536
18537 gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 );
18538
18539 sprite.onAfterRender( renderer, scene, camera, undefined, material, undefined );
18540
18541 }
18542
18543 // restore gl
18544
18545 state.enable( gl.CULL_FACE );
18546
18547 state.reset();
18548
18549 };
18550
18551 function createProgram() {
18552
18553 var program = gl.createProgram();
18554
18555 var vertexShader = gl.createShader( gl.VERTEX_SHADER );
18556 var fragmentShader = gl.createShader( gl.FRAGMENT_SHADER );
18557
18558 gl.shaderSource( vertexShader, [
18559
18560 'precision ' + capabilities.precision + ' float;',
18561
18562 '#define SHADER_NAME ' + 'SpriteMaterial',
18563
18564 'uniform mat4 modelViewMatrix;',
18565 'uniform mat4 projectionMatrix;',
18566 'uniform float rotation;',
18567 'uniform vec2 center;',
18568 'uniform vec2 scale;',
18569 'uniform vec2 uvOffset;',
18570 'uniform vec2 uvScale;',
18571
18572 'attribute vec2 position;',
18573 'attribute vec2 uv;',
18574
18575 'varying vec2 vUV;',
18576 'varying float fogDepth;',
18577
18578 'void main() {',
18579
18580 ' vUV = uvOffset + uv * uvScale;',
18581
18582 ' vec2 alignedPosition = ( position - center ) * scale;',
18583
18584 ' vec2 rotatedPosition;',
18585 ' rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;',
18586 ' rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;',
18587
18588 ' vec4 mvPosition;',
18589
18590 ' mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );',
18591 ' mvPosition.xy += rotatedPosition;',
18592
18593 ' gl_Position = projectionMatrix * mvPosition;',
18594
18595 ' fogDepth = - mvPosition.z;',
18596
18597 '}'
18598
18599 ].join( '\n' ) );
18600
18601 gl.shaderSource( fragmentShader, [
18602
18603 'precision ' + capabilities.precision + ' float;',
18604
18605 '#define SHADER_NAME ' + 'SpriteMaterial',
18606
18607 'uniform vec3 color;',
18608 'uniform sampler2D map;',
18609 'uniform float opacity;',
18610
18611 'uniform int fogType;',
18612 'uniform vec3 fogColor;',
18613 'uniform float fogDensity;',
18614 'uniform float fogNear;',
18615 'uniform float fogFar;',
18616 'uniform float alphaTest;',
18617
18618 'varying vec2 vUV;',
18619 'varying float fogDepth;',
18620
18621 'void main() {',
18622
18623 ' vec4 texture = texture2D( map, vUV );',
18624
18625 ' gl_FragColor = vec4( color * texture.xyz, texture.a * opacity );',
18626
18627 ' if ( gl_FragColor.a < alphaTest ) discard;',
18628
18629 ' if ( fogType > 0 ) {',
18630
18631 ' float fogFactor = 0.0;',
18632
18633 ' if ( fogType == 1 ) {',
18634
18635 ' fogFactor = smoothstep( fogNear, fogFar, fogDepth );',
18636
18637 ' } else {',
18638
18639 ' const float LOG2 = 1.442695;',
18640 ' fogFactor = exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 );',
18641 ' fogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );',
18642
18643 ' }',
18644
18645 ' gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );',
18646
18647 ' }',
18648
18649 '}'
18650
18651 ].join( '\n' ) );
18652
18653 gl.compileShader( vertexShader );
18654 gl.compileShader( fragmentShader );
18655
18656 gl.attachShader( program, vertexShader );
18657 gl.attachShader( program, fragmentShader );
18658
18659 gl.linkProgram( program );
18660
18661 return program;
18662
18663 }
18664
18665 function painterSortStable( a, b ) {
18666
18667 if ( a.renderOrder !== b.renderOrder ) {
18668
18669 return a.renderOrder - b.renderOrder;
18670
18671 } else if ( a.z !== b.z ) {
18672
18673 return b.z - a.z;
18674
18675 } else {
18676
18677 return b.id - a.id;
18678
18679 }
18680
18681 }
18682
18683 }
18684
18685 /**
18686 * @author mrdoob / http://mrdoob.com/
18687 */
18688
18689 function WebGLState( gl, extensions, utils ) {
18690
18691 function ColorBuffer() {
18692
18693 var locked = false;
18694
18695 var color = new Vector4();
18696 var currentColorMask = null;
18697 var currentColorClear = new Vector4( 0, 0, 0, 0 );
18698
18699 return {
18700
18701 setMask: function ( colorMask ) {
18702
18703 if ( currentColorMask !== colorMask && ! locked ) {
18704
18705 gl.colorMask( colorMask, colorMask, colorMask, colorMask );
18706 currentColorMask = colorMask;
18707
18708 }
18709
18710 },
18711
18712 setLocked: function ( lock ) {
18713
18714 locked = lock;
18715
18716 },
18717
18718 setClear: function ( r, g, b, a, premultipliedAlpha ) {
18719
18720 if ( premultipliedAlpha === true ) {
18721
18722 r *= a; g *= a; b *= a;
18723
18724 }
18725
18726 color.set( r, g, b, a );
18727
18728 if ( currentColorClear.equals( color ) === false ) {
18729
18730 gl.clearColor( r, g, b, a );
18731 currentColorClear.copy( color );
18732
18733 }
18734
18735 },
18736
18737 reset: function () {
18738
18739 locked = false;
18740
18741 currentColorMask = null;
18742 currentColorClear.set( - 1, 0, 0, 0 ); // set to invalid state
18743
18744 }
18745
18746 };
18747
18748 }
18749
18750 function DepthBuffer() {
18751
18752 var locked = false;
18753
18754 var currentDepthMask = null;
18755 var currentDepthFunc = null;
18756 var currentDepthClear = null;
18757
18758 return {
18759
18760 setTest: function ( depthTest ) {
18761
18762 if ( depthTest ) {
18763
18764 enable( gl.DEPTH_TEST );
18765
18766 } else {
18767
18768 disable( gl.DEPTH_TEST );
18769
18770 }
18771
18772 },
18773
18774 setMask: function ( depthMask ) {
18775
18776 if ( currentDepthMask !== depthMask && ! locked ) {
18777
18778 gl.depthMask( depthMask );
18779 currentDepthMask = depthMask;
18780
18781 }
18782
18783 },
18784
18785 setFunc: function ( depthFunc ) {
18786
18787 if ( currentDepthFunc !== depthFunc ) {
18788
18789 if ( depthFunc ) {
18790
18791 switch ( depthFunc ) {
18792
18793 case NeverDepth:
18794
18795 gl.depthFunc( gl.NEVER );
18796 break;
18797
18798 case AlwaysDepth:
18799
18800 gl.depthFunc( gl.ALWAYS );
18801 break;
18802
18803 case LessDepth:
18804
18805 gl.depthFunc( gl.LESS );
18806 break;
18807
18808 case LessEqualDepth:
18809
18810 gl.depthFunc( gl.LEQUAL );
18811 break;
18812
18813 case EqualDepth:
18814
18815 gl.depthFunc( gl.EQUAL );
18816 break;
18817
18818 case GreaterEqualDepth:
18819
18820 gl.depthFunc( gl.GEQUAL );
18821 break;
18822
18823 case GreaterDepth:
18824
18825 gl.depthFunc( gl.GREATER );
18826 break;
18827
18828 case NotEqualDepth:
18829
18830 gl.depthFunc( gl.NOTEQUAL );
18831 break;
18832
18833 default:
18834
18835 gl.depthFunc( gl.LEQUAL );
18836
18837 }
18838
18839 } else {
18840
18841 gl.depthFunc( gl.LEQUAL );
18842
18843 }
18844
18845 currentDepthFunc = depthFunc;
18846
18847 }
18848
18849 },
18850
18851 setLocked: function ( lock ) {
18852
18853 locked = lock;
18854
18855 },
18856
18857 setClear: function ( depth ) {
18858
18859 if ( currentDepthClear !== depth ) {
18860
18861 gl.clearDepth( depth );
18862 currentDepthClear = depth;
18863
18864 }
18865
18866 },
18867
18868 reset: function () {
18869
18870 locked = false;
18871
18872 currentDepthMask = null;
18873 currentDepthFunc = null;
18874 currentDepthClear = null;
18875
18876 }
18877
18878 };
18879
18880 }
18881
18882 function StencilBuffer() {
18883
18884 var locked = false;
18885
18886 var currentStencilMask = null;
18887 var currentStencilFunc = null;
18888 var currentStencilRef = null;
18889 var currentStencilFuncMask = null;
18890 var currentStencilFail = null;
18891 var currentStencilZFail = null;
18892 var currentStencilZPass = null;
18893 var currentStencilClear = null;
18894
18895 return {
18896
18897 setTest: function ( stencilTest ) {
18898
18899 if ( stencilTest ) {
18900
18901 enable( gl.STENCIL_TEST );
18902
18903 } else {
18904
18905 disable( gl.STENCIL_TEST );
18906
18907 }
18908
18909 },
18910
18911 setMask: function ( stencilMask ) {
18912
18913 if ( currentStencilMask !== stencilMask && ! locked ) {
18914
18915 gl.stencilMask( stencilMask );
18916 currentStencilMask = stencilMask;
18917
18918 }
18919
18920 },
18921
18922 setFunc: function ( stencilFunc, stencilRef, stencilMask ) {
18923
18924 if ( currentStencilFunc !== stencilFunc ||
18925 currentStencilRef !== stencilRef ||
18926 currentStencilFuncMask !== stencilMask ) {
18927
18928 gl.stencilFunc( stencilFunc, stencilRef, stencilMask );
18929
18930 currentStencilFunc = stencilFunc;
18931 currentStencilRef = stencilRef;
18932 currentStencilFuncMask = stencilMask;
18933
18934 }
18935
18936 },
18937
18938 setOp: function ( stencilFail, stencilZFail, stencilZPass ) {
18939
18940 if ( currentStencilFail !== stencilFail ||
18941 currentStencilZFail !== stencilZFail ||
18942 currentStencilZPass !== stencilZPass ) {
18943
18944 gl.stencilOp( stencilFail, stencilZFail, stencilZPass );
18945
18946 currentStencilFail = stencilFail;
18947 currentStencilZFail = stencilZFail;
18948 currentStencilZPass = stencilZPass;
18949
18950 }
18951
18952 },
18953
18954 setLocked: function ( lock ) {
18955
18956 locked = lock;
18957
18958 },
18959
18960 setClear: function ( stencil ) {
18961
18962 if ( currentStencilClear !== stencil ) {
18963
18964 gl.clearStencil( stencil );
18965 currentStencilClear = stencil;
18966
18967 }
18968
18969 },
18970
18971 reset: function () {
18972
18973 locked = false;
18974
18975 currentStencilMask = null;
18976 currentStencilFunc = null;
18977 currentStencilRef = null;
18978 currentStencilFuncMask = null;
18979 currentStencilFail = null;
18980 currentStencilZFail = null;
18981 currentStencilZPass = null;
18982 currentStencilClear = null;
18983
18984 }
18985
18986 };
18987
18988 }
18989
18990 //
18991
18992 var colorBuffer = new ColorBuffer();
18993 var depthBuffer = new DepthBuffer();
18994 var stencilBuffer = new StencilBuffer();
18995
18996 var maxVertexAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS );
18997 var newAttributes = new Uint8Array( maxVertexAttributes );
18998 var enabledAttributes = new Uint8Array( maxVertexAttributes );
18999 var attributeDivisors = new Uint8Array( maxVertexAttributes );
19000
19001 var capabilities = {};
19002
19003 var compressedTextureFormats = null;
19004
19005 var currentProgram = null;
19006
19007 var currentBlending = null;
19008 var currentBlendEquation = null;
19009 var currentBlendSrc = null;
19010 var currentBlendDst = null;
19011 var currentBlendEquationAlpha = null;
19012 var currentBlendSrcAlpha = null;
19013 var currentBlendDstAlpha = null;
19014 var currentPremultipledAlpha = false;
19015
19016 var currentFlipSided = null;
19017 var currentCullFace = null;
19018
19019 var currentLineWidth = null;
19020
19021 var currentPolygonOffsetFactor = null;
19022 var currentPolygonOffsetUnits = null;
19023
19024 var maxTextures = gl.getParameter( gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS );
19025
19026 var lineWidthAvailable = false;
19027 var version = 0;
19028 var glVersion = gl.getParameter( gl.VERSION );
19029
19030 if ( glVersion.indexOf( 'WebGL' ) !== - 1 ) {
19031
19032 version = parseFloat( /^WebGL\ ([0-9])/.exec( glVersion )[ 1 ] );
19033 lineWidthAvailable = ( version >= 1.0 );
19034
19035 } else if ( glVersion.indexOf( 'OpenGL ES' ) !== - 1 ) {
19036
19037 version = parseFloat( /^OpenGL\ ES\ ([0-9])/.exec( glVersion )[ 1 ] );
19038 lineWidthAvailable = ( version >= 2.0 );
19039
19040 }
19041
19042 var currentTextureSlot = null;
19043 var currentBoundTextures = {};
19044
19045 var currentScissor = new Vector4();
19046 var currentViewport = new Vector4();
19047
19048 function createTexture( type, target, count ) {
19049
19050 var data = new Uint8Array( 4 ); // 4 is required to match default unpack alignment of 4.
19051 var texture = gl.createTexture();
19052
19053 gl.bindTexture( type, texture );
19054 gl.texParameteri( type, gl.TEXTURE_MIN_FILTER, gl.NEAREST );
19055 gl.texParameteri( type, gl.TEXTURE_MAG_FILTER, gl.NEAREST );
19056
19057 for ( var i = 0; i < count; i ++ ) {
19058
19059 gl.texImage2D( target + i, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, data );
19060
19061 }
19062
19063 return texture;
19064
19065 }
19066
19067 var emptyTextures = {};
19068 emptyTextures[ gl.TEXTURE_2D ] = createTexture( gl.TEXTURE_2D, gl.TEXTURE_2D, 1 );
19069 emptyTextures[ gl.TEXTURE_CUBE_MAP ] = createTexture( gl.TEXTURE_CUBE_MAP, gl.TEXTURE_CUBE_MAP_POSITIVE_X, 6 );
19070
19071 // init
19072
19073 colorBuffer.setClear( 0, 0, 0, 1 );
19074 depthBuffer.setClear( 1 );
19075 stencilBuffer.setClear( 0 );
19076
19077 enable( gl.DEPTH_TEST );
19078 depthBuffer.setFunc( LessEqualDepth );
19079
19080 setFlipSided( false );
19081 setCullFace( CullFaceBack );
19082 enable( gl.CULL_FACE );
19083
19084 enable( gl.BLEND );
19085 setBlending( NormalBlending );
19086
19087 //
19088
19089 function initAttributes() {
19090
19091 for ( var i = 0, l = newAttributes.length; i < l; i ++ ) {
19092
19093 newAttributes[ i ] = 0;
19094
19095 }
19096
19097 }
19098
19099 function enableAttribute( attribute ) {
19100
19101 newAttributes[ attribute ] = 1;
19102
19103 if ( enabledAttributes[ attribute ] === 0 ) {
19104
19105 gl.enableVertexAttribArray( attribute );
19106 enabledAttributes[ attribute ] = 1;
19107
19108 }
19109
19110 if ( attributeDivisors[ attribute ] !== 0 ) {
19111
19112 var extension = extensions.get( 'ANGLE_instanced_arrays' );
19113
19114 extension.vertexAttribDivisorANGLE( attribute, 0 );
19115 attributeDivisors[ attribute ] = 0;
19116
19117 }
19118
19119 }
19120
19121 function enableAttributeAndDivisor( attribute, meshPerAttribute ) {
19122
19123 newAttributes[ attribute ] = 1;
19124
19125 if ( enabledAttributes[ attribute ] === 0 ) {
19126
19127 gl.enableVertexAttribArray( attribute );
19128 enabledAttributes[ attribute ] = 1;
19129
19130 }
19131
19132 if ( attributeDivisors[ attribute ] !== meshPerAttribute ) {
19133
19134 var extension = extensions.get( 'ANGLE_instanced_arrays' );
19135
19136 extension.vertexAttribDivisorANGLE( attribute, meshPerAttribute );
19137 attributeDivisors[ attribute ] = meshPerAttribute;
19138
19139 }
19140
19141 }
19142
19143 function disableUnusedAttributes() {
19144
19145 for ( var i = 0, l = enabledAttributes.length; i !== l; ++ i ) {
19146
19147 if ( enabledAttributes[ i ] !== newAttributes[ i ] ) {
19148
19149 gl.disableVertexAttribArray( i );
19150 enabledAttributes[ i ] = 0;
19151
19152 }
19153
19154 }
19155
19156 }
19157
19158 function enable( id ) {
19159
19160 if ( capabilities[ id ] !== true ) {
19161
19162 gl.enable( id );
19163 capabilities[ id ] = true;
19164
19165 }
19166
19167 }
19168
19169 function disable( id ) {
19170
19171 if ( capabilities[ id ] !== false ) {
19172
19173 gl.disable( id );
19174 capabilities[ id ] = false;
19175
19176 }
19177
19178 }
19179
19180 function getCompressedTextureFormats() {
19181
19182 if ( compressedTextureFormats === null ) {
19183
19184 compressedTextureFormats = [];
19185
19186 if ( extensions.get( 'WEBGL_compressed_texture_pvrtc' ) ||
19187 extensions.get( 'WEBGL_compressed_texture_s3tc' ) ||
19188 extensions.get( 'WEBGL_compressed_texture_etc1' ) ||
19189 extensions.get( 'WEBGL_compressed_texture_astc' ) ) {
19190
19191 var formats = gl.getParameter( gl.COMPRESSED_TEXTURE_FORMATS );
19192
19193 for ( var i = 0; i < formats.length; i ++ ) {
19194
19195 compressedTextureFormats.push( formats[ i ] );
19196
19197 }
19198
19199 }
19200
19201 }
19202
19203 return compressedTextureFormats;
19204
19205 }
19206
19207 function useProgram( program ) {
19208
19209 if ( currentProgram !== program ) {
19210
19211 gl.useProgram( program );
19212
19213 currentProgram = program;
19214
19215 return true;
19216
19217 }
19218
19219 return false;
19220
19221 }
19222
19223 function setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, premultipliedAlpha ) {
19224
19225 if ( blending !== NoBlending ) {
19226
19227 enable( gl.BLEND );
19228
19229 } else {
19230
19231 disable( gl.BLEND );
19232
19233 }
19234
19235 if ( blending !== CustomBlending ) {
19236
19237 if ( blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha ) {
19238
19239 switch ( blending ) {
19240
19241 case AdditiveBlending:
19242
19243 if ( premultipliedAlpha ) {
19244
19245 gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD );
19246 gl.blendFuncSeparate( gl.ONE, gl.ONE, gl.ONE, gl.ONE );
19247
19248 } else {
19249
19250 gl.blendEquation( gl.FUNC_ADD );
19251 gl.blendFunc( gl.SRC_ALPHA, gl.ONE );
19252
19253 }
19254 break;
19255
19256 case SubtractiveBlending:
19257
19258 if ( premultipliedAlpha ) {
19259
19260 gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD );
19261 gl.blendFuncSeparate( gl.ZERO, gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ONE_MINUS_SRC_ALPHA );
19262
19263 } else {
19264
19265 gl.blendEquation( gl.FUNC_ADD );
19266 gl.blendFunc( gl.ZERO, gl.ONE_MINUS_SRC_COLOR );
19267
19268 }
19269 break;
19270
19271 case MultiplyBlending:
19272
19273 if ( premultipliedAlpha ) {
19274
19275 gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD );
19276 gl.blendFuncSeparate( gl.ZERO, gl.SRC_COLOR, gl.ZERO, gl.SRC_ALPHA );
19277
19278 } else {
19279
19280 gl.blendEquation( gl.FUNC_ADD );
19281 gl.blendFunc( gl.ZERO, gl.SRC_COLOR );
19282
19283 }
19284 break;
19285
19286 default:
19287
19288 if ( premultipliedAlpha ) {
19289
19290 gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD );
19291 gl.blendFuncSeparate( gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA );
19292
19293 } else {
19294
19295 gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD );
19296 gl.blendFuncSeparate( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA );
19297
19298 }
19299
19300 }
19301
19302 }
19303
19304 currentBlendEquation = null;
19305 currentBlendSrc = null;
19306 currentBlendDst = null;
19307 currentBlendEquationAlpha = null;
19308 currentBlendSrcAlpha = null;
19309 currentBlendDstAlpha = null;
19310
19311 } else {
19312
19313 blendEquationAlpha = blendEquationAlpha || blendEquation;
19314 blendSrcAlpha = blendSrcAlpha || blendSrc;
19315 blendDstAlpha = blendDstAlpha || blendDst;
19316
19317 if ( blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha ) {
19318
19319 gl.blendEquationSeparate( utils.convert( blendEquation ), utils.convert( blendEquationAlpha ) );
19320
19321 currentBlendEquation = blendEquation;
19322 currentBlendEquationAlpha = blendEquationAlpha;
19323
19324 }
19325
19326 if ( blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha ) {
19327
19328 gl.blendFuncSeparate( utils.convert( blendSrc ), utils.convert( blendDst ), utils.convert( blendSrcAlpha ), utils.convert( blendDstAlpha ) );
19329
19330 currentBlendSrc = blendSrc;
19331 currentBlendDst = blendDst;
19332 currentBlendSrcAlpha = blendSrcAlpha;
19333 currentBlendDstAlpha = blendDstAlpha;
19334
19335 }
19336
19337 }
19338
19339 currentBlending = blending;
19340 currentPremultipledAlpha = premultipliedAlpha;
19341
19342 }
19343
19344 function setMaterial( material, frontFaceCW ) {
19345
19346 material.side === DoubleSide
19347 ? disable( gl.CULL_FACE )
19348 : enable( gl.CULL_FACE );
19349
19350 var flipSided = ( material.side === BackSide );
19351 if ( frontFaceCW ) flipSided = ! flipSided;
19352
19353 setFlipSided( flipSided );
19354
19355 material.transparent === true
19356 ? setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha )
19357 : setBlending( NoBlending );
19358
19359 depthBuffer.setFunc( material.depthFunc );
19360 depthBuffer.setTest( material.depthTest );
19361 depthBuffer.setMask( material.depthWrite );
19362 colorBuffer.setMask( material.colorWrite );
19363
19364 setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
19365
19366 }
19367
19368 //
19369
19370 function setFlipSided( flipSided ) {
19371
19372 if ( currentFlipSided !== flipSided ) {
19373
19374 if ( flipSided ) {
19375
19376 gl.frontFace( gl.CW );
19377
19378 } else {
19379
19380 gl.frontFace( gl.CCW );
19381
19382 }
19383
19384 currentFlipSided = flipSided;
19385
19386 }
19387
19388 }
19389
19390 function setCullFace( cullFace ) {
19391
19392 if ( cullFace !== CullFaceNone ) {
19393
19394 enable( gl.CULL_FACE );
19395
19396 if ( cullFace !== currentCullFace ) {
19397
19398 if ( cullFace === CullFaceBack ) {
19399
19400 gl.cullFace( gl.BACK );
19401
19402 } else if ( cullFace === CullFaceFront ) {
19403
19404 gl.cullFace( gl.FRONT );
19405
19406 } else {
19407
19408 gl.cullFace( gl.FRONT_AND_BACK );
19409
19410 }
19411
19412 }
19413
19414 } else {
19415
19416 disable( gl.CULL_FACE );
19417
19418 }
19419
19420 currentCullFace = cullFace;
19421
19422 }
19423
19424 function setLineWidth( width ) {
19425
19426 if ( width !== currentLineWidth ) {
19427
19428 if ( lineWidthAvailable ) gl.lineWidth( width );
19429
19430 currentLineWidth = width;
19431
19432 }
19433
19434 }
19435
19436 function setPolygonOffset( polygonOffset, factor, units ) {
19437
19438 if ( polygonOffset ) {
19439
19440 enable( gl.POLYGON_OFFSET_FILL );
19441
19442 if ( currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units ) {
19443
19444 gl.polygonOffset( factor, units );
19445
19446 currentPolygonOffsetFactor = factor;
19447 currentPolygonOffsetUnits = units;
19448
19449 }
19450
19451 } else {
19452
19453 disable( gl.POLYGON_OFFSET_FILL );
19454
19455 }
19456
19457 }
19458
19459 function setScissorTest( scissorTest ) {
19460
19461 if ( scissorTest ) {
19462
19463 enable( gl.SCISSOR_TEST );
19464
19465 } else {
19466
19467 disable( gl.SCISSOR_TEST );
19468
19469 }
19470
19471 }
19472
19473 // texture
19474
19475 function activeTexture( webglSlot ) {
19476
19477 if ( webglSlot === undefined ) webglSlot = gl.TEXTURE0 + maxTextures - 1;
19478
19479 if ( currentTextureSlot !== webglSlot ) {
19480
19481 gl.activeTexture( webglSlot );
19482 currentTextureSlot = webglSlot;
19483
19484 }
19485
19486 }
19487
19488 function bindTexture( webglType, webglTexture ) {
19489
19490 if ( currentTextureSlot === null ) {
19491
19492 activeTexture();
19493
19494 }
19495
19496 var boundTexture = currentBoundTextures[ currentTextureSlot ];
19497
19498 if ( boundTexture === undefined ) {
19499
19500 boundTexture = { type: undefined, texture: undefined };
19501 currentBoundTextures[ currentTextureSlot ] = boundTexture;
19502
19503 }
19504
19505 if ( boundTexture.type !== webglType || boundTexture.texture !== webglTexture ) {
19506
19507 gl.bindTexture( webglType, webglTexture || emptyTextures[ webglType ] );
19508
19509 boundTexture.type = webglType;
19510 boundTexture.texture = webglTexture;
19511
19512 }
19513
19514 }
19515
19516 function compressedTexImage2D() {
19517
19518 try {
19519
19520 gl.compressedTexImage2D.apply( gl, arguments );
19521
19522 } catch ( error ) {
19523
19524 console.error( 'THREE.WebGLState:', error );
19525
19526 }
19527
19528 }
19529
19530 function texImage2D() {
19531
19532 try {
19533
19534 gl.texImage2D.apply( gl, arguments );
19535
19536 } catch ( error ) {
19537
19538 console.error( 'THREE.WebGLState:', error );
19539
19540 }
19541
19542 }
19543
19544 //
19545
19546 function scissor( scissor ) {
19547
19548 if ( currentScissor.equals( scissor ) === false ) {
19549
19550 gl.scissor( scissor.x, scissor.y, scissor.z, scissor.w );
19551 currentScissor.copy( scissor );
19552
19553 }
19554
19555 }
19556
19557 function viewport( viewport ) {
19558
19559 if ( currentViewport.equals( viewport ) === false ) {
19560
19561 gl.viewport( viewport.x, viewport.y, viewport.z, viewport.w );
19562 currentViewport.copy( viewport );
19563
19564 }
19565
19566 }
19567
19568 //
19569
19570 function reset() {
19571
19572 for ( var i = 0; i < enabledAttributes.length; i ++ ) {
19573
19574 if ( enabledAttributes[ i ] === 1 ) {
19575
19576 gl.disableVertexAttribArray( i );
19577 enabledAttributes[ i ] = 0;
19578
19579 }
19580
19581 }
19582
19583 capabilities = {};
19584
19585 compressedTextureFormats = null;
19586
19587 currentTextureSlot = null;
19588 currentBoundTextures = {};
19589
19590 currentProgram = null;
19591
19592 currentBlending = null;
19593
19594 currentFlipSided = null;
19595 currentCullFace = null;
19596
19597 colorBuffer.reset();
19598 depthBuffer.reset();
19599 stencilBuffer.reset();
19600
19601 }
19602
19603 return {
19604
19605 buffers: {
19606 color: colorBuffer,
19607 depth: depthBuffer,
19608 stencil: stencilBuffer
19609 },
19610
19611 initAttributes: initAttributes,
19612 enableAttribute: enableAttribute,
19613 enableAttributeAndDivisor: enableAttributeAndDivisor,
19614 disableUnusedAttributes: disableUnusedAttributes,
19615 enable: enable,
19616 disable: disable,
19617 getCompressedTextureFormats: getCompressedTextureFormats,
19618
19619 useProgram: useProgram,
19620
19621 setBlending: setBlending,
19622 setMaterial: setMaterial,
19623
19624 setFlipSided: setFlipSided,
19625 setCullFace: setCullFace,
19626
19627 setLineWidth: setLineWidth,
19628 setPolygonOffset: setPolygonOffset,
19629
19630 setScissorTest: setScissorTest,
19631
19632 activeTexture: activeTexture,
19633 bindTexture: bindTexture,
19634 compressedTexImage2D: compressedTexImage2D,
19635 texImage2D: texImage2D,
19636
19637 scissor: scissor,
19638 viewport: viewport,
19639
19640 reset: reset
19641
19642 };
19643
19644 }
19645
19646 /**
19647 * @author mrdoob / http://mrdoob.com/
19648 */
19649
19650 function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ) {
19651
19652 var _isWebGL2 = ( typeof WebGL2RenderingContext !== 'undefined' && _gl instanceof WebGL2RenderingContext ); /* global WebGL2RenderingContext */
19653 var _videoTextures = {};
19654 var _canvas;
19655
19656 //
19657
19658 function clampToMaxSize( image, maxSize ) {
19659
19660 if ( image.width > maxSize || image.height > maxSize ) {
19661
19662 if ( 'data' in image ) {
19663
19664 console.warn( 'THREE.WebGLRenderer: image in DataTexture is too big (' + image.width + 'x' + image.height + ').' );
19665 return;
19666
19667 }
19668
19669 // Warning: Scaling through the canvas will only work with images that use
19670 // premultiplied alpha.
19671
19672 var scale = maxSize / Math.max( image.width, image.height );
19673
19674 var canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
19675 canvas.width = Math.floor( image.width * scale );
19676 canvas.height = Math.floor( image.height * scale );
19677
19678 var context = canvas.getContext( '2d' );
19679 context.drawImage( image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height );
19680
19681 console.warn( 'THREE.WebGLRenderer: image is too big (' + image.width + 'x' + image.height + '). Resized to ' + canvas.width + 'x' + canvas.height, image );
19682
19683 return canvas;
19684
19685 }
19686
19687 return image;
19688
19689 }
19690
19691 function isPowerOfTwo( image ) {
19692
19693 return _Math.isPowerOfTwo( image.width ) && _Math.isPowerOfTwo( image.height );
19694
19695 }
19696
19697 function makePowerOfTwo( image ) {
19698
19699 if ( image instanceof HTMLImageElement || image instanceof HTMLCanvasElement || image instanceof ImageBitmap ) {
19700
19701 if ( _canvas === undefined ) _canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
19702
19703 _canvas.width = _Math.floorPowerOfTwo( image.width );
19704 _canvas.height = _Math.floorPowerOfTwo( image.height );
19705
19706 var context = _canvas.getContext( '2d' );
19707 context.drawImage( image, 0, 0, _canvas.width, _canvas.height );
19708
19709 console.warn( 'THREE.WebGLRenderer: image is not power of two (' + image.width + 'x' + image.height + '). Resized to ' + _canvas.width + 'x' + _canvas.height, image );
19710
19711 return _canvas;
19712
19713 }
19714
19715 return image;
19716
19717 }
19718
19719 function textureNeedsPowerOfTwo( texture ) {
19720
19721 return ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) ||
19722 ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter );
19723
19724 }
19725
19726 function textureNeedsGenerateMipmaps( texture, isPowerOfTwo ) {
19727
19728 return texture.generateMipmaps && isPowerOfTwo &&
19729 texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter;
19730
19731 }
19732
19733 function generateMipmap( target, texture, width, height ) {
19734
19735 _gl.generateMipmap( target );
19736
19737 var textureProperties = properties.get( texture );
19738
19739 // Note: Math.log( x ) * Math.LOG2E used instead of Math.log2( x ) which is not supported by IE11
19740 textureProperties.__maxMipLevel = Math.log( Math.max( width, height ) ) * Math.LOG2E;
19741
19742 }
19743
19744 // Fallback filters for non-power-of-2 textures
19745
19746 function filterFallback( f ) {
19747
19748 if ( f === NearestFilter || f === NearestMipMapNearestFilter || f === NearestMipMapLinearFilter ) {
19749
19750 return _gl.NEAREST;
19751
19752 }
19753
19754 return _gl.LINEAR;
19755
19756 }
19757
19758 //
19759
19760 function onTextureDispose( event ) {
19761
19762 var texture = event.target;
19763
19764 texture.removeEventListener( 'dispose', onTextureDispose );
19765
19766 deallocateTexture( texture );
19767
19768 if ( texture.isVideoTexture ) {
19769
19770 delete _videoTextures[ texture.id ];
19771
19772 }
19773
19774 info.memory.textures --;
19775
19776 }
19777
19778 function onRenderTargetDispose( event ) {
19779
19780 var renderTarget = event.target;
19781
19782 renderTarget.removeEventListener( 'dispose', onRenderTargetDispose );
19783
19784 deallocateRenderTarget( renderTarget );
19785
19786 info.memory.textures --;
19787
19788 }
19789
19790 //
19791
19792 function deallocateTexture( texture ) {
19793
19794 var textureProperties = properties.get( texture );
19795
19796 if ( texture.image && textureProperties.__image__webglTextureCube ) {
19797
19798 // cube texture
19799
19800 _gl.deleteTexture( textureProperties.__image__webglTextureCube );
19801
19802 } else {
19803
19804 // 2D texture
19805
19806 if ( textureProperties.__webglInit === undefined ) return;
19807
19808 _gl.deleteTexture( textureProperties.__webglTexture );
19809
19810 }
19811
19812 // remove all webgl properties
19813 properties.remove( texture );
19814
19815 }
19816
19817 function deallocateRenderTarget( renderTarget ) {
19818
19819 var renderTargetProperties = properties.get( renderTarget );
19820 var textureProperties = properties.get( renderTarget.texture );
19821
19822 if ( ! renderTarget ) return;
19823
19824 if ( textureProperties.__webglTexture !== undefined ) {
19825
19826 _gl.deleteTexture( textureProperties.__webglTexture );
19827
19828 }
19829
19830 if ( renderTarget.depthTexture ) {
19831
19832 renderTarget.depthTexture.dispose();
19833
19834 }
19835
19836 if ( renderTarget.isWebGLRenderTargetCube ) {
19837
19838 for ( var i = 0; i < 6; i ++ ) {
19839
19840 _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ] );
19841 if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer[ i ] );
19842
19843 }
19844
19845 } else {
19846
19847 _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer );
19848 if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer );
19849
19850 }
19851
19852 properties.remove( renderTarget.texture );
19853 properties.remove( renderTarget );
19854
19855 }
19856
19857 //
19858
19859
19860
19861 function setTexture2D( texture, slot ) {
19862
19863 var textureProperties = properties.get( texture );
19864
19865 if ( texture.isVideoTexture ) updateVideoTexture( texture );
19866
19867 if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
19868
19869 var image = texture.image;
19870
19871 if ( image === undefined ) {
19872
19873 console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is undefined', texture );
19874
19875 } else if ( image.complete === false ) {
19876
19877 console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is incomplete', texture );
19878
19879 } else {
19880
19881 uploadTexture( textureProperties, texture, slot );
19882 return;
19883
19884 }
19885
19886 }
19887
19888 state.activeTexture( _gl.TEXTURE0 + slot );
19889 state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture );
19890
19891 }
19892
19893 function setTextureCube( texture, slot ) {
19894
19895 var textureProperties = properties.get( texture );
19896
19897 if ( texture.image.length === 6 ) {
19898
19899 if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
19900
19901 if ( ! textureProperties.__image__webglTextureCube ) {
19902
19903 texture.addEventListener( 'dispose', onTextureDispose );
19904
19905 textureProperties.__image__webglTextureCube = _gl.createTexture();
19906
19907 info.memory.textures ++;
19908
19909 }
19910
19911 state.activeTexture( _gl.TEXTURE0 + slot );
19912 state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__image__webglTextureCube );
19913
19914 _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
19915
19916 var isCompressed = ( texture && texture.isCompressedTexture );
19917 var isDataTexture = ( texture.image[ 0 ] && texture.image[ 0 ].isDataTexture );
19918
19919 var cubeImage = [];
19920
19921 for ( var i = 0; i < 6; i ++ ) {
19922
19923 if ( ! isCompressed && ! isDataTexture ) {
19924
19925 cubeImage[ i ] = clampToMaxSize( texture.image[ i ], capabilities.maxCubemapSize );
19926
19927 } else {
19928
19929 cubeImage[ i ] = isDataTexture ? texture.image[ i ].image : texture.image[ i ];
19930
19931 }
19932
19933 }
19934
19935 var image = cubeImage[ 0 ],
19936 isPowerOfTwoImage = isPowerOfTwo( image ),
19937 glFormat = utils.convert( texture.format ),
19938 glType = utils.convert( texture.type );
19939
19940 setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, isPowerOfTwoImage );
19941
19942 for ( var i = 0; i < 6; i ++ ) {
19943
19944 if ( ! isCompressed ) {
19945
19946 if ( isDataTexture ) {
19947
19948 state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data );
19949
19950 } else {
19951
19952 state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, glFormat, glType, cubeImage[ i ] );
19953
19954 }
19955
19956 } else {
19957
19958 var mipmap, mipmaps = cubeImage[ i ].mipmaps;
19959
19960 for ( var j = 0, jl = mipmaps.length; j < jl; j ++ ) {
19961
19962 mipmap = mipmaps[ j ];
19963
19964 if ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) {
19965
19966 if ( state.getCompressedTextureFormats().indexOf( glFormat ) > - 1 ) {
19967
19968 state.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, mipmap.data );
19969
19970 } else {
19971
19972 console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()' );
19973
19974 }
19975
19976 } else {
19977
19978 state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
19979
19980 }
19981
19982 }
19983
19984 }
19985
19986 }
19987
19988 if ( ! isCompressed ) {
19989
19990 textureProperties.__maxMipLevel = 0;
19991
19992 } else {
19993
19994 textureProperties.__maxMipLevel = mipmaps.length - 1;
19995
19996 }
19997
19998 if ( textureNeedsGenerateMipmaps( texture, isPowerOfTwoImage ) ) {
19999
20000 // We assume images for cube map have the same size.
20001 generateMipmap( _gl.TEXTURE_CUBE_MAP, texture, image.width, image.height );
20002
20003 }
20004
20005 textureProperties.__version = texture.version;
20006
20007 if ( texture.onUpdate ) texture.onUpdate( texture );
20008
20009 } else {
20010
20011 state.activeTexture( _gl.TEXTURE0 + slot );
20012 state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__image__webglTextureCube );
20013
20014 }
20015
20016 }
20017
20018 }
20019
20020 function setTextureCubeDynamic( texture, slot ) {
20021
20022 state.activeTexture( _gl.TEXTURE0 + slot );
20023 state.bindTexture( _gl.TEXTURE_CUBE_MAP, properties.get( texture ).__webglTexture );
20024
20025 }
20026
20027 function setTextureParameters( textureType, texture, isPowerOfTwoImage ) {
20028
20029 var extension;
20030
20031 if ( isPowerOfTwoImage ) {
20032
20033 _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, utils.convert( texture.wrapS ) );
20034 _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, utils.convert( texture.wrapT ) );
20035
20036 _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, utils.convert( texture.magFilter ) );
20037 _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, utils.convert( texture.minFilter ) );
20038
20039 } else {
20040
20041 _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE );
20042 _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE );
20043
20044 if ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) {
20045
20046 console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping.', texture );
20047
20048 }
20049
20050 _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterFallback( texture.magFilter ) );
20051 _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterFallback( texture.minFilter ) );
20052
20053 if ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ) {
20054
20055 console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.', texture );
20056
20057 }
20058
20059 }
20060
20061 extension = extensions.get( 'EXT_texture_filter_anisotropic' );
20062
20063 if ( extension ) {
20064
20065 if ( texture.type === FloatType && extensions.get( 'OES_texture_float_linear' ) === null ) return;
20066 if ( texture.type === HalfFloatType && extensions.get( 'OES_texture_half_float_linear' ) === null ) return;
20067
20068 if ( texture.anisotropy > 1 || properties.get( texture ).__currentAnisotropy ) {
20069
20070 _gl.texParameterf( textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, capabilities.getMaxAnisotropy() ) );
20071 properties.get( texture ).__currentAnisotropy = texture.anisotropy;
20072
20073 }
20074
20075 }
20076
20077 }
20078
20079 function uploadTexture( textureProperties, texture, slot ) {
20080
20081 if ( textureProperties.__webglInit === undefined ) {
20082
20083 textureProperties.__webglInit = true;
20084
20085 texture.addEventListener( 'dispose', onTextureDispose );
20086
20087 textureProperties.__webglTexture = _gl.createTexture();
20088
20089 info.memory.textures ++;
20090
20091 }
20092
20093 state.activeTexture( _gl.TEXTURE0 + slot );
20094 state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture );
20095
20096 _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
20097 _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha );
20098 _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment );
20099
20100 var image = clampToMaxSize( texture.image, capabilities.maxTextureSize );
20101
20102 if ( textureNeedsPowerOfTwo( texture ) && isPowerOfTwo( image ) === false ) {
20103
20104 image = makePowerOfTwo( image );
20105
20106 }
20107
20108 var isPowerOfTwoImage = isPowerOfTwo( image ),
20109 glFormat = utils.convert( texture.format ),
20110 glType = utils.convert( texture.type );
20111
20112 setTextureParameters( _gl.TEXTURE_2D, texture, isPowerOfTwoImage );
20113
20114 var mipmap, mipmaps = texture.mipmaps;
20115
20116 if ( texture.isDepthTexture ) {
20117
20118 // populate depth texture with dummy data
20119
20120 var internalFormat = _gl.DEPTH_COMPONENT;
20121
20122 if ( texture.type === FloatType ) {
20123
20124 if ( ! _isWebGL2 ) throw new Error( 'Float Depth Texture only supported in WebGL2.0' );
20125 internalFormat = _gl.DEPTH_COMPONENT32F;
20126
20127 } else if ( _isWebGL2 ) {
20128
20129 // WebGL 2.0 requires signed internalformat for glTexImage2D
20130 internalFormat = _gl.DEPTH_COMPONENT16;
20131
20132 }
20133
20134 if ( texture.format === DepthFormat && internalFormat === _gl.DEPTH_COMPONENT ) {
20135
20136 // The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
20137 // DEPTH_COMPONENT and type is not UNSIGNED_SHORT or UNSIGNED_INT
20138 // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
20139 if ( texture.type !== UnsignedShortType && texture.type !== UnsignedIntType ) {
20140
20141 console.warn( 'THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture.' );
20142
20143 texture.type = UnsignedShortType;
20144 glType = utils.convert( texture.type );
20145
20146 }
20147
20148 }
20149
20150 // Depth stencil textures need the DEPTH_STENCIL internal format
20151 // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
20152 if ( texture.format === DepthStencilFormat ) {
20153
20154 internalFormat = _gl.DEPTH_STENCIL;
20155
20156 // The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
20157 // DEPTH_STENCIL and type is not UNSIGNED_INT_24_8_WEBGL.
20158 // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
20159 if ( texture.type !== UnsignedInt248Type ) {
20160
20161 console.warn( 'THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture.' );
20162
20163 texture.type = UnsignedInt248Type;
20164 glType = utils.convert( texture.type );
20165
20166 }
20167
20168 }
20169
20170 state.texImage2D( _gl.TEXTURE_2D, 0, internalFormat, image.width, image.height, 0, glFormat, glType, null );
20171
20172 } else if ( texture.isDataTexture ) {
20173
20174 // use manually created mipmaps if available
20175 // if there are no manual mipmaps
20176 // set 0 level mipmap and then use GL to generate other mipmap levels
20177
20178 if ( mipmaps.length > 0 && isPowerOfTwoImage ) {
20179
20180 for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
20181
20182 mipmap = mipmaps[ i ];
20183 state.texImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
20184
20185 }
20186
20187 texture.generateMipmaps = false;
20188 textureProperties.__maxMipLevel = mipmaps.length - 1;
20189
20190 } else {
20191
20192 state.texImage2D( _gl.TEXTURE_2D, 0, glFormat, image.width, image.height, 0, glFormat, glType, image.data );
20193 textureProperties.__maxMipLevel = 0;
20194
20195 }
20196
20197 } else if ( texture.isCompressedTexture ) {
20198
20199 for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
20200
20201 mipmap = mipmaps[ i ];
20202
20203 if ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) {
20204
20205 if ( state.getCompressedTextureFormats().indexOf( glFormat ) > - 1 ) {
20206
20207 state.compressedTexImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, mipmap.data );
20208
20209 } else {
20210
20211 console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' );
20212
20213 }
20214
20215 } else {
20216
20217 state.texImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
20218
20219 }
20220
20221 }
20222
20223 textureProperties.__maxMipLevel = mipmaps.length - 1;
20224
20225 } else {
20226
20227 // regular Texture (image, video, canvas)
20228
20229 // use manually created mipmaps if available
20230 // if there are no manual mipmaps
20231 // set 0 level mipmap and then use GL to generate other mipmap levels
20232
20233 if ( mipmaps.length > 0 && isPowerOfTwoImage ) {
20234
20235 for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
20236
20237 mipmap = mipmaps[ i ];
20238 state.texImage2D( _gl.TEXTURE_2D, i, glFormat, glFormat, glType, mipmap );
20239
20240 }
20241
20242 texture.generateMipmaps = false;
20243 textureProperties.__maxMipLevel = mipmaps.length - 1;
20244
20245 } else {
20246
20247 state.texImage2D( _gl.TEXTURE_2D, 0, glFormat, glFormat, glType, image );
20248 textureProperties.__maxMipLevel = 0;
20249
20250 }
20251
20252 }
20253
20254 if ( textureNeedsGenerateMipmaps( texture, isPowerOfTwoImage ) ) {
20255
20256 generateMipmap( _gl.TEXTURE_2D, texture, image.width, image.height );
20257
20258 }
20259
20260 textureProperties.__version = texture.version;
20261
20262 if ( texture.onUpdate ) texture.onUpdate( texture );
20263
20264 }
20265
20266 // Render targets
20267
20268 // Setup storage for target texture and bind it to correct framebuffer
20269 function setupFrameBufferTexture( framebuffer, renderTarget, attachment, textureTarget ) {
20270
20271 var glFormat = utils.convert( renderTarget.texture.format );
20272 var glType = utils.convert( renderTarget.texture.type );
20273 state.texImage2D( textureTarget, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
20274 _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
20275 _gl.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( renderTarget.texture ).__webglTexture, 0 );
20276 _gl.bindFramebuffer( _gl.FRAMEBUFFER, null );
20277
20278 }
20279
20280 // Setup storage for internal depth/stencil buffers and bind to correct framebuffer
20281 function setupRenderBufferStorage( renderbuffer, renderTarget ) {
20282
20283 _gl.bindRenderbuffer( _gl.RENDERBUFFER, renderbuffer );
20284
20285 if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) {
20286
20287 _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_COMPONENT16, renderTarget.width, renderTarget.height );
20288 _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
20289
20290 } else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
20291
20292 _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_STENCIL, renderTarget.width, renderTarget.height );
20293 _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
20294
20295 } else {
20296
20297 // FIXME: We don't support !depth !stencil
20298 _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.RGBA4, renderTarget.width, renderTarget.height );
20299
20300 }
20301
20302 _gl.bindRenderbuffer( _gl.RENDERBUFFER, null );
20303
20304 }
20305
20306 // Setup resources for a Depth Texture for a FBO (needs an extension)
20307 function setupDepthTexture( framebuffer, renderTarget ) {
20308
20309 var isCube = ( renderTarget && renderTarget.isWebGLRenderTargetCube );
20310 if ( isCube ) throw new Error( 'Depth Texture with cube render targets is not supported' );
20311
20312 _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
20313
20314 if ( ! ( renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture ) ) {
20315
20316 throw new Error( 'renderTarget.depthTexture must be an instance of THREE.DepthTexture' );
20317
20318 }
20319
20320 // upload an empty depth texture with framebuffer size
20321 if ( ! properties.get( renderTarget.depthTexture ).__webglTexture ||
20322 renderTarget.depthTexture.image.width !== renderTarget.width ||
20323 renderTarget.depthTexture.image.height !== renderTarget.height ) {
20324
20325 renderTarget.depthTexture.image.width = renderTarget.width;
20326 renderTarget.depthTexture.image.height = renderTarget.height;
20327 renderTarget.depthTexture.needsUpdate = true;
20328
20329 }
20330
20331 setTexture2D( renderTarget.depthTexture, 0 );
20332
20333 var webglDepthTexture = properties.get( renderTarget.depthTexture ).__webglTexture;
20334
20335 if ( renderTarget.depthTexture.format === DepthFormat ) {
20336
20337 _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 );
20338
20339 } else if ( renderTarget.depthTexture.format === DepthStencilFormat ) {
20340
20341 _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 );
20342
20343 } else {
20344
20345 throw new Error( 'Unknown depthTexture format' );
20346
20347 }
20348
20349 }
20350
20351 // Setup GL resources for a non-texture depth buffer
20352 function setupDepthRenderbuffer( renderTarget ) {
20353
20354 var renderTargetProperties = properties.get( renderTarget );
20355
20356 var isCube = ( renderTarget.isWebGLRenderTargetCube === true );
20357
20358 if ( renderTarget.depthTexture ) {
20359
20360 if ( isCube ) throw new Error( 'target.depthTexture not supported in Cube render targets' );
20361
20362 setupDepthTexture( renderTargetProperties.__webglFramebuffer, renderTarget );
20363
20364 } else {
20365
20366 if ( isCube ) {
20367
20368 renderTargetProperties.__webglDepthbuffer = [];
20369
20370 for ( var i = 0; i < 6; i ++ ) {
20371
20372 _gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer[ i ] );
20373 renderTargetProperties.__webglDepthbuffer[ i ] = _gl.createRenderbuffer();
20374 setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer[ i ], renderTarget );
20375
20376 }
20377
20378 } else {
20379
20380 _gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer );
20381 renderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer();
20382 setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer, renderTarget );
20383
20384 }
20385
20386 }
20387
20388 _gl.bindFramebuffer( _gl.FRAMEBUFFER, null );
20389
20390 }
20391
20392 // Set up GL resources for the render target
20393 function setupRenderTarget( renderTarget ) {
20394
20395 var renderTargetProperties = properties.get( renderTarget );
20396 var textureProperties = properties.get( renderTarget.texture );
20397
20398 renderTarget.addEventListener( 'dispose', onRenderTargetDispose );
20399
20400 textureProperties.__webglTexture = _gl.createTexture();
20401
20402 info.memory.textures ++;
20403
20404 var isCube = ( renderTarget.isWebGLRenderTargetCube === true );
20405 var isTargetPowerOfTwo = isPowerOfTwo( renderTarget );
20406
20407 // Setup framebuffer
20408
20409 if ( isCube ) {
20410
20411 renderTargetProperties.__webglFramebuffer = [];
20412
20413 for ( var i = 0; i < 6; i ++ ) {
20414
20415 renderTargetProperties.__webglFramebuffer[ i ] = _gl.createFramebuffer();
20416
20417 }
20418
20419 } else {
20420
20421 renderTargetProperties.__webglFramebuffer = _gl.createFramebuffer();
20422
20423 }
20424
20425 // Setup color buffer
20426
20427 if ( isCube ) {
20428
20429 state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture );
20430 setTextureParameters( _gl.TEXTURE_CUBE_MAP, renderTarget.texture, isTargetPowerOfTwo );
20431
20432 for ( var i = 0; i < 6; i ++ ) {
20433
20434 setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ], renderTarget, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i );
20435
20436 }
20437
20438 if ( textureNeedsGenerateMipmaps( renderTarget.texture, isTargetPowerOfTwo ) ) {
20439
20440 generateMipmap( _gl.TEXTURE_CUBE_MAP, renderTarget.texture, renderTarget.width, renderTarget.height );
20441
20442 }
20443
20444 state.bindTexture( _gl.TEXTURE_CUBE_MAP, null );
20445
20446 } else {
20447
20448 state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture );
20449 setTextureParameters( _gl.TEXTURE_2D, renderTarget.texture, isTargetPowerOfTwo );
20450 setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D );
20451
20452 if ( textureNeedsGenerateMipmaps( renderTarget.texture, isTargetPowerOfTwo ) ) {
20453
20454 generateMipmap( _gl.TEXTURE_2D, renderTarget.texture, renderTarget.width, renderTarget.height );
20455
20456 }
20457
20458 state.bindTexture( _gl.TEXTURE_2D, null );
20459
20460 }
20461
20462 // Setup depth and stencil buffers
20463
20464 if ( renderTarget.depthBuffer ) {
20465
20466 setupDepthRenderbuffer( renderTarget );
20467
20468 }
20469
20470 }
20471
20472 function updateRenderTargetMipmap( renderTarget ) {
20473
20474 var texture = renderTarget.texture;
20475 var isTargetPowerOfTwo = isPowerOfTwo( renderTarget );
20476
20477 if ( textureNeedsGenerateMipmaps( texture, isTargetPowerOfTwo ) ) {
20478
20479 var target = renderTarget.isWebGLRenderTargetCube ? _gl.TEXTURE_CUBE_MAP : _gl.TEXTURE_2D;
20480 var webglTexture = properties.get( texture ).__webglTexture;
20481
20482 state.bindTexture( target, webglTexture );
20483 generateMipmap( target, texture, renderTarget.width, renderTarget.height );
20484 state.bindTexture( target, null );
20485
20486 }
20487
20488 }
20489
20490 function updateVideoTexture( texture ) {
20491
20492 var id = texture.id;
20493 var frame = info.render.frame;
20494
20495 // Check the last frame we updated the VideoTexture
20496
20497 if ( _videoTextures[ id ] !== frame ) {
20498
20499 _videoTextures[ id ] = frame;
20500 texture.update();
20501
20502 }
20503
20504 }
20505
20506 this.setTexture2D = setTexture2D;
20507 this.setTextureCube = setTextureCube;
20508 this.setTextureCubeDynamic = setTextureCubeDynamic;
20509 this.setupRenderTarget = setupRenderTarget;
20510 this.updateRenderTargetMipmap = updateRenderTargetMipmap;
20511
20512 }
20513
20514 /**
20515 * @author thespite / http://www.twitter.com/thespite
20516 */
20517
20518 function WebGLUtils( gl, extensions ) {
20519
20520 function convert( p ) {
20521
20522 var extension;
20523
20524 if ( p === RepeatWrapping ) return gl.REPEAT;
20525 if ( p === ClampToEdgeWrapping ) return gl.CLAMP_TO_EDGE;
20526 if ( p === MirroredRepeatWrapping ) return gl.MIRRORED_REPEAT;
20527
20528 if ( p === NearestFilter ) return gl.NEAREST;
20529 if ( p === NearestMipMapNearestFilter ) return gl.NEAREST_MIPMAP_NEAREST;
20530 if ( p === NearestMipMapLinearFilter ) return gl.NEAREST_MIPMAP_LINEAR;
20531
20532 if ( p === LinearFilter ) return gl.LINEAR;
20533 if ( p === LinearMipMapNearestFilter ) return gl.LINEAR_MIPMAP_NEAREST;
20534 if ( p === LinearMipMapLinearFilter ) return gl.LINEAR_MIPMAP_LINEAR;
20535
20536 if ( p === UnsignedByteType ) return gl.UNSIGNED_BYTE;
20537 if ( p === UnsignedShort4444Type ) return gl.UNSIGNED_SHORT_4_4_4_4;
20538 if ( p === UnsignedShort5551Type ) return gl.UNSIGNED_SHORT_5_5_5_1;
20539 if ( p === UnsignedShort565Type ) return gl.UNSIGNED_SHORT_5_6_5;
20540
20541 if ( p === ByteType ) return gl.BYTE;
20542 if ( p === ShortType ) return gl.SHORT;
20543 if ( p === UnsignedShortType ) return gl.UNSIGNED_SHORT;
20544 if ( p === IntType ) return gl.INT;
20545 if ( p === UnsignedIntType ) return gl.UNSIGNED_INT;
20546 if ( p === FloatType ) return gl.FLOAT;
20547
20548 if ( p === HalfFloatType ) {
20549
20550 extension = extensions.get( 'OES_texture_half_float' );
20551
20552 if ( extension !== null ) return extension.HALF_FLOAT_OES;
20553
20554 }
20555
20556 if ( p === AlphaFormat ) return gl.ALPHA;
20557 if ( p === RGBFormat ) return gl.RGB;
20558 if ( p === RGBAFormat ) return gl.RGBA;
20559 if ( p === LuminanceFormat ) return gl.LUMINANCE;
20560 if ( p === LuminanceAlphaFormat ) return gl.LUMINANCE_ALPHA;
20561 if ( p === DepthFormat ) return gl.DEPTH_COMPONENT;
20562 if ( p === DepthStencilFormat ) return gl.DEPTH_STENCIL;
20563
20564 if ( p === AddEquation ) return gl.FUNC_ADD;
20565 if ( p === SubtractEquation ) return gl.FUNC_SUBTRACT;
20566 if ( p === ReverseSubtractEquation ) return gl.FUNC_REVERSE_SUBTRACT;
20567
20568 if ( p === ZeroFactor ) return gl.ZERO;
20569 if ( p === OneFactor ) return gl.ONE;
20570 if ( p === SrcColorFactor ) return gl.SRC_COLOR;
20571 if ( p === OneMinusSrcColorFactor ) return gl.ONE_MINUS_SRC_COLOR;
20572 if ( p === SrcAlphaFactor ) return gl.SRC_ALPHA;
20573 if ( p === OneMinusSrcAlphaFactor ) return gl.ONE_MINUS_SRC_ALPHA;
20574 if ( p === DstAlphaFactor ) return gl.DST_ALPHA;
20575 if ( p === OneMinusDstAlphaFactor ) return gl.ONE_MINUS_DST_ALPHA;
20576
20577 if ( p === DstColorFactor ) return gl.DST_COLOR;
20578 if ( p === OneMinusDstColorFactor ) return gl.ONE_MINUS_DST_COLOR;
20579 if ( p === SrcAlphaSaturateFactor ) return gl.SRC_ALPHA_SATURATE;
20580
20581 if ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format ||
20582 p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) {
20583
20584 extension = extensions.get( 'WEBGL_compressed_texture_s3tc' );
20585
20586 if ( extension !== null ) {
20587
20588 if ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT;
20589 if ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT;
20590 if ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT;
20591 if ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT;
20592
20593 }
20594
20595 }
20596
20597 if ( p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format ||
20598 p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format ) {
20599
20600 extension = extensions.get( 'WEBGL_compressed_texture_pvrtc' );
20601
20602 if ( extension !== null ) {
20603
20604 if ( p === RGB_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
20605 if ( p === RGB_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
20606 if ( p === RGBA_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
20607 if ( p === RGBA_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
20608
20609 }
20610
20611 }
20612
20613 if ( p === RGB_ETC1_Format ) {
20614
20615 extension = extensions.get( 'WEBGL_compressed_texture_etc1' );
20616
20617 if ( extension !== null ) return extension.COMPRESSED_RGB_ETC1_WEBGL;
20618
20619 }
20620
20621 if ( p === RGBA_ASTC_4x4_Format || p === RGBA_ASTC_5x4_Format || p === RGBA_ASTC_5x5_Format ||
20622 p === RGBA_ASTC_6x5_Format || p === RGBA_ASTC_6x6_Format || p === RGBA_ASTC_8x5_Format ||
20623 p === RGBA_ASTC_8x6_Format || p === RGBA_ASTC_8x8_Format || p === RGBA_ASTC_10x5_Format ||
20624 p === RGBA_ASTC_10x6_Format || p === RGBA_ASTC_10x8_Format || p === RGBA_ASTC_10x10_Format ||
20625 p === RGBA_ASTC_12x10_Format || p === RGBA_ASTC_12x12_Format ) {
20626
20627 extension = extensions.get( 'WEBGL_compressed_texture_astc' );
20628
20629 if ( extension !== null ) {
20630
20631 return p;
20632
20633 }
20634
20635 }
20636
20637 if ( p === MinEquation || p === MaxEquation ) {
20638
20639 extension = extensions.get( 'EXT_blend_minmax' );
20640
20641 if ( extension !== null ) {
20642
20643 if ( p === MinEquation ) return extension.MIN_EXT;
20644 if ( p === MaxEquation ) return extension.MAX_EXT;
20645
20646 }
20647
20648 }
20649
20650 if ( p === UnsignedInt248Type ) {
20651
20652 extension = extensions.get( 'WEBGL_depth_texture' );
20653
20654 if ( extension !== null ) return extension.UNSIGNED_INT_24_8_WEBGL;
20655
20656 }
20657
20658 return 0;
20659
20660 }
20661
20662 return { convert: convert };
20663
20664 }
20665
20666 /**
20667 * @author mrdoob / http://mrdoob.com/
20668 * @author greggman / http://games.greggman.com/
20669 * @author zz85 / http://www.lab4games.net/zz85/blog
20670 * @author tschw
20671 */
20672
20673 function PerspectiveCamera( fov, aspect, near, far ) {
20674
20675 Camera.call( this );
20676
20677 this.type = 'PerspectiveCamera';
20678
20679 this.fov = fov !== undefined ? fov : 50;
20680 this.zoom = 1;
20681
20682 this.near = near !== undefined ? near : 0.1;
20683 this.far = far !== undefined ? far : 2000;
20684 this.focus = 10;
20685
20686 this.aspect = aspect !== undefined ? aspect : 1;
20687 this.view = null;
20688
20689 this.filmGauge = 35; // width of the film (default in millimeters)
20690 this.filmOffset = 0; // horizontal film offset (same unit as gauge)
20691
20692 this.updateProjectionMatrix();
20693
20694 }
20695
20696 PerspectiveCamera.prototype = Object.assign( Object.create( Camera.prototype ), {
20697
20698 constructor: PerspectiveCamera,
20699
20700 isPerspectiveCamera: true,
20701
20702 copy: function ( source, recursive ) {
20703
20704 Camera.prototype.copy.call( this, source, recursive );
20705
20706 this.fov = source.fov;
20707 this.zoom = source.zoom;
20708
20709 this.near = source.near;
20710 this.far = source.far;
20711 this.focus = source.focus;
20712
20713 this.aspect = source.aspect;
20714 this.view = source.view === null ? null : Object.assign( {}, source.view );
20715
20716 this.filmGauge = source.filmGauge;
20717 this.filmOffset = source.filmOffset;
20718
20719 return this;
20720
20721 },
20722
20723 /**
20724 * Sets the FOV by focal length in respect to the current .filmGauge.
20725 *
20726 * The default film gauge is 35, so that the focal length can be specified for
20727 * a 35mm (full frame) camera.
20728 *
20729 * Values for focal length and film gauge must have the same unit.
20730 */
20731 setFocalLength: function ( focalLength ) {
20732
20733 // see http://www.bobatkins.com/photography/technical/field_of_view.html
20734 var vExtentSlope = 0.5 * this.getFilmHeight() / focalLength;
20735
20736 this.fov = _Math.RAD2DEG * 2 * Math.atan( vExtentSlope );
20737 this.updateProjectionMatrix();
20738
20739 },
20740
20741 /**
20742 * Calculates the focal length from the current .fov and .filmGauge.
20743 */
20744 getFocalLength: function () {
20745
20746 var vExtentSlope = Math.tan( _Math.DEG2RAD * 0.5 * this.fov );
20747
20748 return 0.5 * this.getFilmHeight() / vExtentSlope;
20749
20750 },
20751
20752 getEffectiveFOV: function () {
20753
20754 return _Math.RAD2DEG * 2 * Math.atan(
20755 Math.tan( _Math.DEG2RAD * 0.5 * this.fov ) / this.zoom );
20756
20757 },
20758
20759 getFilmWidth: function () {
20760
20761 // film not completely covered in portrait format (aspect < 1)
20762 return this.filmGauge * Math.min( this.aspect, 1 );
20763
20764 },
20765
20766 getFilmHeight: function () {
20767
20768 // film not completely covered in landscape format (aspect > 1)
20769 return this.filmGauge / Math.max( this.aspect, 1 );
20770
20771 },
20772
20773 /**
20774 * Sets an offset in a larger frustum. This is useful for multi-window or
20775 * multi-monitor/multi-machine setups.
20776 *
20777 * For example, if you have 3x2 monitors and each monitor is 1920x1080 and
20778 * the monitors are in grid like this
20779 *
20780 * +---+---+---+
20781 * | A | B | C |
20782 * +---+---+---+
20783 * | D | E | F |
20784 * +---+---+---+
20785 *
20786 * then for each monitor you would call it like this
20787 *
20788 * var w = 1920;
20789 * var h = 1080;
20790 * var fullWidth = w * 3;
20791 * var fullHeight = h * 2;
20792 *
20793 * --A--
20794 * camera.setOffset( fullWidth, fullHeight, w * 0, h * 0, w, h );
20795 * --B--
20796 * camera.setOffset( fullWidth, fullHeight, w * 1, h * 0, w, h );
20797 * --C--
20798 * camera.setOffset( fullWidth, fullHeight, w * 2, h * 0, w, h );
20799 * --D--
20800 * camera.setOffset( fullWidth, fullHeight, w * 0, h * 1, w, h );
20801 * --E--
20802 * camera.setOffset( fullWidth, fullHeight, w * 1, h * 1, w, h );
20803 * --F--
20804 * camera.setOffset( fullWidth, fullHeight, w * 2, h * 1, w, h );
20805 *
20806 * Note there is no reason monitors have to be the same size or in a grid.
20807 */
20808 setViewOffset: function ( fullWidth, fullHeight, x, y, width, height ) {
20809
20810 this.aspect = fullWidth / fullHeight;
20811
20812 if ( this.view === null ) {
20813
20814 this.view = {
20815 enabled: true,
20816 fullWidth: 1,
20817 fullHeight: 1,
20818 offsetX: 0,
20819 offsetY: 0,
20820 width: 1,
20821 height: 1
20822 };
20823
20824 }
20825
20826 this.view.enabled = true;
20827 this.view.fullWidth = fullWidth;
20828 this.view.fullHeight = fullHeight;
20829 this.view.offsetX = x;
20830 this.view.offsetY = y;
20831 this.view.width = width;
20832 this.view.height = height;
20833
20834 this.updateProjectionMatrix();
20835
20836 },
20837
20838 clearViewOffset: function () {
20839
20840 if ( this.view !== null ) {
20841
20842 this.view.enabled = false;
20843
20844 }
20845
20846 this.updateProjectionMatrix();
20847
20848 },
20849
20850 updateProjectionMatrix: function () {
20851
20852 var near = this.near,
20853 top = near * Math.tan(
20854 _Math.DEG2RAD * 0.5 * this.fov ) / this.zoom,
20855 height = 2 * top,
20856 width = this.aspect * height,
20857 left = - 0.5 * width,
20858 view = this.view;
20859
20860 if ( this.view !== null && this.view.enabled ) {
20861
20862 var fullWidth = view.fullWidth,
20863 fullHeight = view.fullHeight;
20864
20865 left += view.offsetX * width / fullWidth;
20866 top -= view.offsetY * height / fullHeight;
20867 width *= view.width / fullWidth;
20868 height *= view.height / fullHeight;
20869
20870 }
20871
20872 var skew = this.filmOffset;
20873 if ( skew !== 0 ) left += near * skew / this.getFilmWidth();
20874
20875 this.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far );
20876
20877 },
20878
20879 toJSON: function ( meta ) {
20880
20881 var data = Object3D.prototype.toJSON.call( this, meta );
20882
20883 data.object.fov = this.fov;
20884 data.object.zoom = this.zoom;
20885
20886 data.object.near = this.near;
20887 data.object.far = this.far;
20888 data.object.focus = this.focus;
20889
20890 data.object.aspect = this.aspect;
20891
20892 if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
20893
20894 data.object.filmGauge = this.filmGauge;
20895 data.object.filmOffset = this.filmOffset;
20896
20897 return data;
20898
20899 }
20900
20901 } );
20902
20903 /**
20904 * @author mrdoob / http://mrdoob.com/
20905 */
20906
20907 function ArrayCamera( array ) {
20908
20909 PerspectiveCamera.call( this );
20910
20911 this.cameras = array || [];
20912
20913 }
20914
20915 ArrayCamera.prototype = Object.assign( Object.create( PerspectiveCamera.prototype ), {
20916
20917 constructor: ArrayCamera,
20918
20919 isArrayCamera: true
20920
20921 } );
20922
20923 /**
20924 * @author mrdoob / http://mrdoob.com/
20925 */
20926
20927 function WebVRManager( renderer ) {
20928
20929 var scope = this;
20930
20931 var device = null;
20932 var frameData = null;
20933
20934 var poseTarget = null;
20935
20936 var standingMatrix = new Matrix4();
20937 var standingMatrixInverse = new Matrix4();
20938
20939 if ( typeof window !== 'undefined' && 'VRFrameData' in window ) {
20940
20941 frameData = new window.VRFrameData();
20942 window.addEventListener( 'vrdisplaypresentchange', onVRDisplayPresentChange, false );
20943
20944 }
20945
20946 var matrixWorldInverse = new Matrix4();
20947 var tempQuaternion = new Quaternion();
20948 var tempPosition = new Vector3();
20949
20950 var cameraL = new PerspectiveCamera();
20951 cameraL.bounds = new Vector4( 0.0, 0.0, 0.5, 1.0 );
20952 cameraL.layers.enable( 1 );
20953
20954 var cameraR = new PerspectiveCamera();
20955 cameraR.bounds = new Vector4( 0.5, 0.0, 0.5, 1.0 );
20956 cameraR.layers.enable( 2 );
20957
20958 var cameraVR = new ArrayCamera( [ cameraL, cameraR ] );
20959 cameraVR.layers.enable( 1 );
20960 cameraVR.layers.enable( 2 );
20961
20962 //
20963
20964 function isPresenting() {
20965
20966 return device !== null && device.isPresenting === true;
20967
20968 }
20969
20970 var currentSize, currentPixelRatio;
20971
20972 function onVRDisplayPresentChange() {
20973
20974 if ( isPresenting() ) {
20975
20976 var eyeParameters = device.getEyeParameters( 'left' );
20977 var renderWidth = eyeParameters.renderWidth;
20978 var renderHeight = eyeParameters.renderHeight;
20979
20980 currentPixelRatio = renderer.getPixelRatio();
20981 currentSize = renderer.getSize();
20982
20983 renderer.setDrawingBufferSize( renderWidth * 2, renderHeight, 1 );
20984
20985 } else if ( scope.enabled ) {
20986
20987 renderer.setDrawingBufferSize( currentSize.width, currentSize.height, currentPixelRatio );
20988
20989 }
20990
20991 }
20992
20993 //
20994
20995 this.enabled = false;
20996 this.userHeight = 1.6;
20997
20998 this.getDevice = function () {
20999
21000 return device;
21001
21002 };
21003
21004 this.setDevice = function ( value ) {
21005
21006 if ( value !== undefined ) device = value;
21007
21008 };
21009
21010 this.setPoseTarget = function ( object ) {
21011
21012 if ( object !== undefined ) poseTarget = object;
21013
21014 };
21015
21016 this.getCamera = function ( camera ) {
21017
21018 if ( device === null ) return camera;
21019
21020 device.depthNear = camera.near;
21021 device.depthFar = camera.far;
21022
21023 device.getFrameData( frameData );
21024
21025 //
21026
21027 var stageParameters = device.stageParameters;
21028
21029 if ( stageParameters ) {
21030
21031 standingMatrix.fromArray( stageParameters.sittingToStandingTransform );
21032
21033 } else {
21034
21035 standingMatrix.makeTranslation( 0, scope.userHeight, 0 );
21036
21037 }
21038
21039
21040 var pose = frameData.pose;
21041 var poseObject = poseTarget !== null ? poseTarget : camera;
21042
21043 // We want to manipulate poseObject by its position and quaternion components since users may rely on them.
21044 poseObject.matrix.copy( standingMatrix );
21045 poseObject.matrix.decompose( poseObject.position, poseObject.quaternion, poseObject.scale );
21046
21047 if ( pose.orientation !== null ) {
21048
21049 tempQuaternion.fromArray( pose.orientation );
21050 poseObject.quaternion.multiply( tempQuaternion );
21051
21052 }
21053
21054 if ( pose.position !== null ) {
21055
21056 tempQuaternion.setFromRotationMatrix( standingMatrix );
21057 tempPosition.fromArray( pose.position );
21058 tempPosition.applyQuaternion( tempQuaternion );
21059 poseObject.position.add( tempPosition );
21060
21061 }
21062
21063 poseObject.updateMatrixWorld();
21064
21065 if ( device.isPresenting === false ) return camera;
21066
21067 //
21068
21069 cameraL.near = camera.near;
21070 cameraR.near = camera.near;
21071
21072 cameraL.far = camera.far;
21073 cameraR.far = camera.far;
21074
21075 cameraVR.matrixWorld.copy( camera.matrixWorld );
21076 cameraVR.matrixWorldInverse.copy( camera.matrixWorldInverse );
21077
21078 cameraL.matrixWorldInverse.fromArray( frameData.leftViewMatrix );
21079 cameraR.matrixWorldInverse.fromArray( frameData.rightViewMatrix );
21080
21081 // TODO (mrdoob) Double check this code
21082
21083 standingMatrixInverse.getInverse( standingMatrix );
21084
21085 cameraL.matrixWorldInverse.multiply( standingMatrixInverse );
21086 cameraR.matrixWorldInverse.multiply( standingMatrixInverse );
21087
21088 var parent = poseObject.parent;
21089
21090 if ( parent !== null ) {
21091
21092 matrixWorldInverse.getInverse( parent.matrixWorld );
21093
21094 cameraL.matrixWorldInverse.multiply( matrixWorldInverse );
21095 cameraR.matrixWorldInverse.multiply( matrixWorldInverse );
21096
21097 }
21098
21099 // envMap and Mirror needs camera.matrixWorld
21100
21101 cameraL.matrixWorld.getInverse( cameraL.matrixWorldInverse );
21102 cameraR.matrixWorld.getInverse( cameraR.matrixWorldInverse );
21103
21104 cameraL.projectionMatrix.fromArray( frameData.leftProjectionMatrix );
21105 cameraR.projectionMatrix.fromArray( frameData.rightProjectionMatrix );
21106
21107 // HACK (mrdoob)
21108 // https://github.com/w3c/webvr/issues/203
21109
21110 cameraVR.projectionMatrix.copy( cameraL.projectionMatrix );
21111
21112 //
21113
21114 var layers = device.getLayers();
21115
21116 if ( layers.length ) {
21117
21118 var layer = layers[ 0 ];
21119
21120 if ( layer.leftBounds !== null && layer.leftBounds.length === 4 ) {
21121
21122 cameraL.bounds.fromArray( layer.leftBounds );
21123
21124 }
21125
21126 if ( layer.rightBounds !== null && layer.rightBounds.length === 4 ) {
21127
21128 cameraR.bounds.fromArray( layer.rightBounds );
21129
21130 }
21131
21132 }
21133
21134 return cameraVR;
21135
21136 };
21137
21138 this.getStandingMatrix = function () {
21139
21140 return standingMatrix;
21141
21142 };
21143
21144 this.submitFrame = function () {
21145
21146 if ( isPresenting() ) device.submitFrame();
21147
21148 };
21149
21150 this.dispose = function () {
21151
21152 if ( typeof window !== 'undefined' ) {
21153
21154 window.removeEventListener( 'vrdisplaypresentchange', onVRDisplayPresentChange );
21155
21156 }
21157
21158 };
21159
21160 }
21161
21162 /**
21163 * @author supereggbert / http://www.paulbrunt.co.uk/
21164 * @author mrdoob / http://mrdoob.com/
21165 * @author alteredq / http://alteredqualia.com/
21166 * @author szimek / https://github.com/szimek/
21167 * @author tschw
21168 */
21169
21170 function WebGLRenderer( parameters ) {
21171
21172 console.log( 'THREE.WebGLRenderer', REVISION );
21173
21174 parameters = parameters || {};
21175
21176 var _canvas = parameters.canvas !== undefined ? parameters.canvas : document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ),
21177 _context = parameters.context !== undefined ? parameters.context : null,
21178
21179 _alpha = parameters.alpha !== undefined ? parameters.alpha : false,
21180 _depth = parameters.depth !== undefined ? parameters.depth : true,
21181 _stencil = parameters.stencil !== undefined ? parameters.stencil : true,
21182 _antialias = parameters.antialias !== undefined ? parameters.antialias : false,
21183 _premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true,
21184 _preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false,
21185 _powerPreference = parameters.powerPreference !== undefined ? parameters.powerPreference : 'default';
21186
21187 var currentRenderList = null;
21188 var currentRenderState = null;
21189
21190 // public properties
21191
21192 this.domElement = _canvas;
21193 this.context = null;
21194
21195 // clearing
21196
21197 this.autoClear = true;
21198 this.autoClearColor = true;
21199 this.autoClearDepth = true;
21200 this.autoClearStencil = true;
21201
21202 // scene graph
21203
21204 this.sortObjects = true;
21205
21206 // user-defined clipping
21207
21208 this.clippingPlanes = [];
21209 this.localClippingEnabled = false;
21210
21211 // physically based shading
21212
21213 this.gammaFactor = 2.0; // for backwards compatibility
21214 this.gammaInput = false;
21215 this.gammaOutput = false;
21216
21217 // physical lights
21218
21219 this.physicallyCorrectLights = false;
21220
21221 // tone mapping
21222
21223 this.toneMapping = LinearToneMapping;
21224 this.toneMappingExposure = 1.0;
21225 this.toneMappingWhitePoint = 1.0;
21226
21227 // morphs
21228
21229 this.maxMorphTargets = 8;
21230 this.maxMorphNormals = 4;
21231
21232 // internal properties
21233
21234 var _this = this,
21235
21236 _isContextLost = false,
21237
21238 // internal state cache
21239
21240 _currentRenderTarget = null,
21241 _currentFramebuffer = null,
21242 _currentMaterialId = - 1,
21243 _currentGeometryProgram = '',
21244
21245 _currentCamera = null,
21246 _currentArrayCamera = null,
21247
21248 _currentViewport = new Vector4(),
21249 _currentScissor = new Vector4(),
21250 _currentScissorTest = null,
21251
21252 //
21253
21254 _usedTextureUnits = 0,
21255
21256 //
21257
21258 _width = _canvas.width,
21259 _height = _canvas.height,
21260
21261 _pixelRatio = 1,
21262
21263 _viewport = new Vector4( 0, 0, _width, _height ),
21264 _scissor = new Vector4( 0, 0, _width, _height ),
21265 _scissorTest = false,
21266
21267 // frustum
21268
21269 _frustum = new Frustum(),
21270
21271 // clipping
21272
21273 _clipping = new WebGLClipping(),
21274 _clippingEnabled = false,
21275 _localClippingEnabled = false,
21276
21277 // camera matrices cache
21278
21279 _projScreenMatrix = new Matrix4(),
21280
21281 _vector3 = new Vector3();
21282
21283 function getTargetPixelRatio() {
21284
21285 return _currentRenderTarget === null ? _pixelRatio : 1;
21286
21287 }
21288
21289 // initialize
21290
21291 var _gl;
21292
21293 try {
21294
21295 var contextAttributes = {
21296 alpha: _alpha,
21297 depth: _depth,
21298 stencil: _stencil,
21299 antialias: _antialias,
21300 premultipliedAlpha: _premultipliedAlpha,
21301 preserveDrawingBuffer: _preserveDrawingBuffer,
21302 powerPreference: _powerPreference
21303 };
21304
21305 // event listeners must be registered before WebGL context is created, see #12753
21306
21307 _canvas.addEventListener( 'webglcontextlost', onContextLost, false );
21308 _canvas.addEventListener( 'webglcontextrestored', onContextRestore, false );
21309
21310 _gl = _context || _canvas.getContext( 'webgl', contextAttributes ) || _canvas.getContext( 'experimental-webgl', contextAttributes );
21311
21312 if ( _gl === null ) {
21313
21314 if ( _canvas.getContext( 'webgl' ) !== null ) {
21315
21316 throw new Error( 'Error creating WebGL context with your selected attributes.' );
21317
21318 } else {
21319
21320 throw new Error( 'Error creating WebGL context.' );
21321
21322 }
21323
21324 }
21325
21326 // Some experimental-webgl implementations do not have getShaderPrecisionFormat
21327
21328 if ( _gl.getShaderPrecisionFormat === undefined ) {
21329
21330 _gl.getShaderPrecisionFormat = function () {
21331
21332 return { 'rangeMin': 1, 'rangeMax': 1, 'precision': 1 };
21333
21334 };
21335
21336 }
21337
21338 } catch ( error ) {
21339
21340 console.error( 'THREE.WebGLRenderer: ' + error.message );
21341
21342 }
21343
21344 var extensions, capabilities, state, info;
21345 var properties, textures, attributes, geometries, objects;
21346 var programCache, renderLists, renderStates;
21347
21348 var background, morphtargets, bufferRenderer, indexedBufferRenderer;
21349 var spriteRenderer;
21350
21351 var utils;
21352
21353 function initGLContext() {
21354
21355 extensions = new WebGLExtensions( _gl );
21356 extensions.get( 'WEBGL_depth_texture' );
21357 extensions.get( 'OES_texture_float' );
21358 extensions.get( 'OES_texture_float_linear' );
21359 extensions.get( 'OES_texture_half_float' );
21360 extensions.get( 'OES_texture_half_float_linear' );
21361 extensions.get( 'OES_standard_derivatives' );
21362 extensions.get( 'OES_element_index_uint' );
21363 extensions.get( 'ANGLE_instanced_arrays' );
21364
21365 utils = new WebGLUtils( _gl, extensions );
21366
21367 capabilities = new WebGLCapabilities( _gl, extensions, parameters );
21368
21369 state = new WebGLState( _gl, extensions, utils );
21370 state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ) );
21371 state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ) );
21372
21373 info = new WebGLInfo( _gl );
21374 properties = new WebGLProperties();
21375 textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info );
21376 attributes = new WebGLAttributes( _gl );
21377 geometries = new WebGLGeometries( _gl, attributes, info );
21378 objects = new WebGLObjects( geometries, info );
21379 morphtargets = new WebGLMorphtargets( _gl );
21380 programCache = new WebGLPrograms( _this, extensions, capabilities );
21381 renderLists = new WebGLRenderLists();
21382 renderStates = new WebGLRenderStates();
21383
21384 background = new WebGLBackground( _this, state, geometries, _premultipliedAlpha );
21385
21386 bufferRenderer = new WebGLBufferRenderer( _gl, extensions, info );
21387 indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, info );
21388
21389 spriteRenderer = new WebGLSpriteRenderer( _this, _gl, state, textures, capabilities );
21390
21391 info.programs = programCache.programs;
21392
21393 _this.context = _gl;
21394 _this.capabilities = capabilities;
21395 _this.extensions = extensions;
21396 _this.properties = properties;
21397 _this.renderLists = renderLists;
21398 _this.state = state;
21399 _this.info = info;
21400
21401 }
21402
21403 initGLContext();
21404
21405 // vr
21406
21407 var vr = new WebVRManager( _this );
21408
21409 this.vr = vr;
21410
21411 // shadow map
21412
21413 var shadowMap = new WebGLShadowMap( _this, objects, capabilities.maxTextureSize );
21414
21415 this.shadowMap = shadowMap;
21416
21417 // API
21418
21419 this.getContext = function () {
21420
21421 return _gl;
21422
21423 };
21424
21425 this.getContextAttributes = function () {
21426
21427 return _gl.getContextAttributes();
21428
21429 };
21430
21431 this.forceContextLoss = function () {
21432
21433 var extension = extensions.get( 'WEBGL_lose_context' );
21434 if ( extension ) extension.loseContext();
21435
21436 };
21437
21438 this.forceContextRestore = function () {
21439
21440 var extension = extensions.get( 'WEBGL_lose_context' );
21441 if ( extension ) extension.restoreContext();
21442
21443 };
21444
21445 this.getPixelRatio = function () {
21446
21447 return _pixelRatio;
21448
21449 };
21450
21451 this.setPixelRatio = function ( value ) {
21452
21453 if ( value === undefined ) return;
21454
21455 _pixelRatio = value;
21456
21457 this.setSize( _width, _height, false );
21458
21459 };
21460
21461 this.getSize = function () {
21462
21463 return {
21464 width: _width,
21465 height: _height
21466 };
21467
21468 };
21469
21470 this.setSize = function ( width, height, updateStyle ) {
21471
21472 var device = vr.getDevice();
21473
21474 if ( device && device.isPresenting ) {
21475
21476 console.warn( 'THREE.WebGLRenderer: Can\'t change size while VR device is presenting.' );
21477 return;
21478
21479 }
21480
21481 _width = width;
21482 _height = height;
21483
21484 _canvas.width = width * _pixelRatio;
21485 _canvas.height = height * _pixelRatio;
21486
21487 if ( updateStyle !== false ) {
21488
21489 _canvas.style.width = width + 'px';
21490 _canvas.style.height = height + 'px';
21491
21492 }
21493
21494 this.setViewport( 0, 0, width, height );
21495
21496 };
21497
21498 this.getDrawingBufferSize = function () {
21499
21500 return {
21501 width: _width * _pixelRatio,
21502 height: _height * _pixelRatio
21503 };
21504
21505 };
21506
21507 this.setDrawingBufferSize = function ( width, height, pixelRatio ) {
21508
21509 _width = width;
21510 _height = height;
21511
21512 _pixelRatio = pixelRatio;
21513
21514 _canvas.width = width * pixelRatio;
21515 _canvas.height = height * pixelRatio;
21516
21517 this.setViewport( 0, 0, width, height );
21518
21519 };
21520
21521 this.getCurrentViewport = function () {
21522
21523 return _currentViewport;
21524
21525 };
21526
21527 this.setViewport = function ( x, y, width, height ) {
21528
21529 _viewport.set( x, _height - y - height, width, height );
21530 state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ) );
21531
21532 };
21533
21534 this.setScissor = function ( x, y, width, height ) {
21535
21536 _scissor.set( x, _height - y - height, width, height );
21537 state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ) );
21538
21539 };
21540
21541 this.setScissorTest = function ( boolean ) {
21542
21543 state.setScissorTest( _scissorTest = boolean );
21544
21545 };
21546
21547 // Clearing
21548
21549 this.getClearColor = function () {
21550
21551 return background.getClearColor();
21552
21553 };
21554
21555 this.setClearColor = function () {
21556
21557 background.setClearColor.apply( background, arguments );
21558
21559 };
21560
21561 this.getClearAlpha = function () {
21562
21563 return background.getClearAlpha();
21564
21565 };
21566
21567 this.setClearAlpha = function () {
21568
21569 background.setClearAlpha.apply( background, arguments );
21570
21571 };
21572
21573 this.clear = function ( color, depth, stencil ) {
21574
21575 var bits = 0;
21576
21577 if ( color === undefined || color ) bits |= _gl.COLOR_BUFFER_BIT;
21578 if ( depth === undefined || depth ) bits |= _gl.DEPTH_BUFFER_BIT;
21579 if ( stencil === undefined || stencil ) bits |= _gl.STENCIL_BUFFER_BIT;
21580
21581 _gl.clear( bits );
21582
21583 };
21584
21585 this.clearColor = function () {
21586
21587 this.clear( true, false, false );
21588
21589 };
21590
21591 this.clearDepth = function () {
21592
21593 this.clear( false, true, false );
21594
21595 };
21596
21597 this.clearStencil = function () {
21598
21599 this.clear( false, false, true );
21600
21601 };
21602
21603 this.clearTarget = function ( renderTarget, color, depth, stencil ) {
21604
21605 this.setRenderTarget( renderTarget );
21606 this.clear( color, depth, stencil );
21607
21608 };
21609
21610 //
21611
21612 this.dispose = function () {
21613
21614 _canvas.removeEventListener( 'webglcontextlost', onContextLost, false );
21615 _canvas.removeEventListener( 'webglcontextrestored', onContextRestore, false );
21616
21617 renderLists.dispose();
21618 renderStates.dispose();
21619 properties.dispose();
21620 objects.dispose();
21621
21622 vr.dispose();
21623
21624 stopAnimation();
21625
21626 };
21627
21628 // Events
21629
21630 function onContextLost( event ) {
21631
21632 event.preventDefault();
21633
21634 console.log( 'THREE.WebGLRenderer: Context Lost.' );
21635
21636 _isContextLost = true;
21637
21638 }
21639
21640 function onContextRestore( /* event */ ) {
21641
21642 console.log( 'THREE.WebGLRenderer: Context Restored.' );
21643
21644 _isContextLost = false;
21645
21646 initGLContext();
21647
21648 }
21649
21650 function onMaterialDispose( event ) {
21651
21652 var material = event.target;
21653
21654 material.removeEventListener( 'dispose', onMaterialDispose );
21655
21656 deallocateMaterial( material );
21657
21658 }
21659
21660 // Buffer deallocation
21661
21662 function deallocateMaterial( material ) {
21663
21664 releaseMaterialProgramReference( material );
21665
21666 properties.remove( material );
21667
21668 }
21669
21670
21671 function releaseMaterialProgramReference( material ) {
21672
21673 var programInfo = properties.get( material ).program;
21674
21675 material.program = undefined;
21676
21677 if ( programInfo !== undefined ) {
21678
21679 programCache.releaseProgram( programInfo );
21680
21681 }
21682
21683 }
21684
21685 // Buffer rendering
21686
21687 function renderObjectImmediate( object, program, material ) {
21688
21689 object.render( function ( object ) {
21690
21691 _this.renderBufferImmediate( object, program, material );
21692
21693 } );
21694
21695 }
21696
21697 this.renderBufferImmediate = function ( object, program, material ) {
21698
21699 state.initAttributes();
21700
21701 var buffers = properties.get( object );
21702
21703 if ( object.hasPositions && ! buffers.position ) buffers.position = _gl.createBuffer();
21704 if ( object.hasNormals && ! buffers.normal ) buffers.normal = _gl.createBuffer();
21705 if ( object.hasUvs && ! buffers.uv ) buffers.uv = _gl.createBuffer();
21706 if ( object.hasColors && ! buffers.color ) buffers.color = _gl.createBuffer();
21707
21708 var programAttributes = program.getAttributes();
21709
21710 if ( object.hasPositions ) {
21711
21712 _gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.position );
21713 _gl.bufferData( _gl.ARRAY_BUFFER, object.positionArray, _gl.DYNAMIC_DRAW );
21714
21715 state.enableAttribute( programAttributes.position );
21716 _gl.vertexAttribPointer( programAttributes.position, 3, _gl.FLOAT, false, 0, 0 );
21717
21718 }
21719
21720 if ( object.hasNormals ) {
21721
21722 _gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.normal );
21723
21724 if ( ! material.isMeshPhongMaterial &&
21725 ! material.isMeshStandardMaterial &&
21726 ! material.isMeshNormalMaterial &&
21727 material.flatShading === true ) {
21728
21729 for ( var i = 0, l = object.count * 3; i < l; i += 9 ) {
21730
21731 var array = object.normalArray;
21732
21733 var nx = ( array[ i + 0 ] + array[ i + 3 ] + array[ i + 6 ] ) / 3;
21734 var ny = ( array[ i + 1 ] + array[ i + 4 ] + array[ i + 7 ] ) / 3;
21735 var nz = ( array[ i + 2 ] + array[ i + 5 ] + array[ i + 8 ] ) / 3;
21736
21737 array[ i + 0 ] = nx;
21738 array[ i + 1 ] = ny;
21739 array[ i + 2 ] = nz;
21740
21741 array[ i + 3 ] = nx;
21742 array[ i + 4 ] = ny;
21743 array[ i + 5 ] = nz;
21744
21745 array[ i + 6 ] = nx;
21746 array[ i + 7 ] = ny;
21747 array[ i + 8 ] = nz;
21748
21749 }
21750
21751 }
21752
21753 _gl.bufferData( _gl.ARRAY_BUFFER, object.normalArray, _gl.DYNAMIC_DRAW );
21754
21755 state.enableAttribute( programAttributes.normal );
21756
21757 _gl.vertexAttribPointer( programAttributes.normal, 3, _gl.FLOAT, false, 0, 0 );
21758
21759 }
21760
21761 if ( object.hasUvs && material.map ) {
21762
21763 _gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.uv );
21764 _gl.bufferData( _gl.ARRAY_BUFFER, object.uvArray, _gl.DYNAMIC_DRAW );
21765
21766 state.enableAttribute( programAttributes.uv );
21767
21768 _gl.vertexAttribPointer( programAttributes.uv, 2, _gl.FLOAT, false, 0, 0 );
21769
21770 }
21771
21772 if ( object.hasColors && material.vertexColors !== NoColors ) {
21773
21774 _gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.color );
21775 _gl.bufferData( _gl.ARRAY_BUFFER, object.colorArray, _gl.DYNAMIC_DRAW );
21776
21777 state.enableAttribute( programAttributes.color );
21778
21779 _gl.vertexAttribPointer( programAttributes.color, 3, _gl.FLOAT, false, 0, 0 );
21780
21781 }
21782
21783 state.disableUnusedAttributes();
21784
21785 _gl.drawArrays( _gl.TRIANGLES, 0, object.count );
21786
21787 object.count = 0;
21788
21789 };
21790
21791 this.renderBufferDirect = function ( camera, fog, geometry, material, object, group ) {
21792
21793 var frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 );
21794
21795 state.setMaterial( material, frontFaceCW );
21796
21797 var program = setProgram( camera, fog, material, object );
21798 var geometryProgram = geometry.id + '_' + program.id + '_' + ( material.wireframe === true );
21799
21800 var updateBuffers = false;
21801
21802 if ( geometryProgram !== _currentGeometryProgram ) {
21803
21804 _currentGeometryProgram = geometryProgram;
21805 updateBuffers = true;
21806
21807 }
21808
21809 if ( object.morphTargetInfluences ) {
21810
21811 morphtargets.update( object, geometry, material, program );
21812
21813 updateBuffers = true;
21814
21815 }
21816
21817 //
21818
21819 var index = geometry.index;
21820 var position = geometry.attributes.position;
21821 var rangeFactor = 1;
21822
21823 if ( material.wireframe === true ) {
21824
21825 index = geometries.getWireframeAttribute( geometry );
21826 rangeFactor = 2;
21827
21828 }
21829
21830 var attribute;
21831 var renderer = bufferRenderer;
21832
21833 if ( index !== null ) {
21834
21835 attribute = attributes.get( index );
21836
21837 renderer = indexedBufferRenderer;
21838 renderer.setIndex( attribute );
21839
21840 }
21841
21842 if ( updateBuffers ) {
21843
21844 setupVertexAttributes( material, program, geometry );
21845
21846 if ( index !== null ) {
21847
21848 _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, attribute.buffer );
21849
21850 }
21851
21852 }
21853
21854 //
21855
21856 var dataCount = Infinity;
21857
21858 if ( index !== null ) {
21859
21860 dataCount = index.count;
21861
21862 } else if ( position !== undefined ) {
21863
21864 dataCount = position.count;
21865
21866 }
21867
21868 var rangeStart = geometry.drawRange.start * rangeFactor;
21869 var rangeCount = geometry.drawRange.count * rangeFactor;
21870
21871 var groupStart = group !== null ? group.start * rangeFactor : 0;
21872 var groupCount = group !== null ? group.count * rangeFactor : Infinity;
21873
21874 var drawStart = Math.max( rangeStart, groupStart );
21875 var drawEnd = Math.min( dataCount, rangeStart + rangeCount, groupStart + groupCount ) - 1;
21876
21877 var drawCount = Math.max( 0, drawEnd - drawStart + 1 );
21878
21879 if ( drawCount === 0 ) return;
21880
21881 //
21882
21883 if ( object.isMesh ) {
21884
21885 if ( material.wireframe === true ) {
21886
21887 state.setLineWidth( material.wireframeLinewidth * getTargetPixelRatio() );
21888 renderer.setMode( _gl.LINES );
21889
21890 } else {
21891
21892 switch ( object.drawMode ) {
21893
21894 case TrianglesDrawMode:
21895 renderer.setMode( _gl.TRIANGLES );
21896 break;
21897
21898 case TriangleStripDrawMode:
21899 renderer.setMode( _gl.TRIANGLE_STRIP );
21900 break;
21901
21902 case TriangleFanDrawMode:
21903 renderer.setMode( _gl.TRIANGLE_FAN );
21904 break;
21905
21906 }
21907
21908 }
21909
21910
21911 } else if ( object.isLine ) {
21912
21913 var lineWidth = material.linewidth;
21914
21915 if ( lineWidth === undefined ) lineWidth = 1; // Not using Line*Material
21916
21917 state.setLineWidth( lineWidth * getTargetPixelRatio() );
21918
21919 if ( object.isLineSegments ) {
21920
21921 renderer.setMode( _gl.LINES );
21922
21923 } else if ( object.isLineLoop ) {
21924
21925 renderer.setMode( _gl.LINE_LOOP );
21926
21927 } else {
21928
21929 renderer.setMode( _gl.LINE_STRIP );
21930
21931 }
21932
21933 } else if ( object.isPoints ) {
21934
21935 renderer.setMode( _gl.POINTS );
21936
21937 }
21938
21939 if ( geometry && geometry.isInstancedBufferGeometry ) {
21940
21941 if ( geometry.maxInstancedCount > 0 ) {
21942
21943 renderer.renderInstances( geometry, drawStart, drawCount );
21944
21945 }
21946
21947 } else {
21948
21949 renderer.render( drawStart, drawCount );
21950
21951 }
21952
21953 };
21954
21955 function setupVertexAttributes( material, program, geometry ) {
21956
21957 if ( geometry && geometry.isInstancedBufferGeometry ) {
21958
21959 if ( extensions.get( 'ANGLE_instanced_arrays' ) === null ) {
21960
21961 console.error( 'THREE.WebGLRenderer.setupVertexAttributes: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
21962 return;
21963
21964 }
21965
21966 }
21967
21968 state.initAttributes();
21969
21970 var geometryAttributes = geometry.attributes;
21971
21972 var programAttributes = program.getAttributes();
21973
21974 var materialDefaultAttributeValues = material.defaultAttributeValues;
21975
21976 for ( var name in programAttributes ) {
21977
21978 var programAttribute = programAttributes[ name ];
21979
21980 if ( programAttribute >= 0 ) {
21981
21982 var geometryAttribute = geometryAttributes[ name ];
21983
21984 if ( geometryAttribute !== undefined ) {
21985
21986 var normalized = geometryAttribute.normalized;
21987 var size = geometryAttribute.itemSize;
21988
21989 var attribute = attributes.get( geometryAttribute );
21990
21991 // TODO Attribute may not be available on context restore
21992
21993 if ( attribute === undefined ) continue;
21994
21995 var buffer = attribute.buffer;
21996 var type = attribute.type;
21997 var bytesPerElement = attribute.bytesPerElement;
21998
21999 if ( geometryAttribute.isInterleavedBufferAttribute ) {
22000
22001 var data = geometryAttribute.data;
22002 var stride = data.stride;
22003 var offset = geometryAttribute.offset;
22004
22005 if ( data && data.isInstancedInterleavedBuffer ) {
22006
22007 state.enableAttributeAndDivisor( programAttribute, data.meshPerAttribute );
22008
22009 if ( geometry.maxInstancedCount === undefined ) {
22010
22011 geometry.maxInstancedCount = data.meshPerAttribute * data.count;
22012
22013 }
22014
22015 } else {
22016
22017 state.enableAttribute( programAttribute );
22018
22019 }
22020
22021 _gl.bindBuffer( _gl.ARRAY_BUFFER, buffer );
22022 _gl.vertexAttribPointer( programAttribute, size, type, normalized, stride * bytesPerElement, offset * bytesPerElement );
22023
22024 } else {
22025
22026 if ( geometryAttribute.isInstancedBufferAttribute ) {
22027
22028 state.enableAttributeAndDivisor( programAttribute, geometryAttribute.meshPerAttribute );
22029
22030 if ( geometry.maxInstancedCount === undefined ) {
22031
22032 geometry.maxInstancedCount = geometryAttribute.meshPerAttribute * geometryAttribute.count;
22033
22034 }
22035
22036 } else {
22037
22038 state.enableAttribute( programAttribute );
22039
22040 }
22041
22042 _gl.bindBuffer( _gl.ARRAY_BUFFER, buffer );
22043 _gl.vertexAttribPointer( programAttribute, size, type, normalized, 0, 0 );
22044
22045 }
22046
22047 } else if ( materialDefaultAttributeValues !== undefined ) {
22048
22049 var value = materialDefaultAttributeValues[ name ];
22050
22051 if ( value !== undefined ) {
22052
22053 switch ( value.length ) {
22054
22055 case 2:
22056 _gl.vertexAttrib2fv( programAttribute, value );
22057 break;
22058
22059 case 3:
22060 _gl.vertexAttrib3fv( programAttribute, value );
22061 break;
22062
22063 case 4:
22064 _gl.vertexAttrib4fv( programAttribute, value );
22065 break;
22066
22067 default:
22068 _gl.vertexAttrib1fv( programAttribute, value );
22069
22070 }
22071
22072 }
22073
22074 }
22075
22076 }
22077
22078 }
22079
22080 state.disableUnusedAttributes();
22081
22082 }
22083
22084 // Compile
22085
22086 this.compile = function ( scene, camera ) {
22087
22088 currentRenderState = renderStates.get( scene, camera );
22089 currentRenderState.init();
22090
22091 scene.traverse( function ( object ) {
22092
22093 if ( object.isLight ) {
22094
22095 currentRenderState.pushLight( object );
22096
22097 if ( object.castShadow ) {
22098
22099 currentRenderState.pushShadow( object );
22100
22101 }
22102
22103 }
22104
22105 } );
22106
22107 currentRenderState.setupLights( camera );
22108
22109 scene.traverse( function ( object ) {
22110
22111 if ( object.material ) {
22112
22113 if ( Array.isArray( object.material ) ) {
22114
22115 for ( var i = 0; i < object.material.length; i ++ ) {
22116
22117 initMaterial( object.material[ i ], scene.fog, object );
22118
22119 }
22120
22121 } else {
22122
22123 initMaterial( object.material, scene.fog, object );
22124
22125 }
22126
22127 }
22128
22129 } );
22130
22131 };
22132
22133 // Animation Loop
22134
22135 var isAnimating = false;
22136 var onAnimationFrame = null;
22137
22138 function startAnimation() {
22139
22140 if ( isAnimating ) return;
22141
22142 requestAnimationLoopFrame();
22143
22144 isAnimating = true;
22145
22146 }
22147
22148 function stopAnimation() {
22149
22150 isAnimating = false;
22151
22152 }
22153
22154 function requestAnimationLoopFrame() {
22155
22156 var device = vr.getDevice();
22157
22158 if ( device && device.isPresenting ) {
22159
22160 device.requestAnimationFrame( animationLoop );
22161
22162 } else {
22163
22164 window.requestAnimationFrame( animationLoop );
22165
22166 }
22167
22168 }
22169
22170 function animationLoop( time ) {
22171
22172 if ( isAnimating === false ) return;
22173
22174 onAnimationFrame( time );
22175
22176 requestAnimationLoopFrame();
22177
22178 }
22179
22180 this.animate = function ( callback ) {
22181
22182 onAnimationFrame = callback;
22183 onAnimationFrame !== null ? startAnimation() : stopAnimation();
22184
22185 };
22186
22187 // Rendering
22188
22189 this.render = function ( scene, camera, renderTarget, forceClear ) {
22190
22191 if ( ! ( camera && camera.isCamera ) ) {
22192
22193 console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' );
22194 return;
22195
22196 }
22197
22198 if ( _isContextLost ) return;
22199
22200 // reset caching for this frame
22201
22202 _currentGeometryProgram = '';
22203 _currentMaterialId = - 1;
22204 _currentCamera = null;
22205
22206 // update scene graph
22207
22208 if ( scene.autoUpdate === true ) scene.updateMatrixWorld();
22209
22210 // update camera matrices and frustum
22211
22212 if ( camera.parent === null ) camera.updateMatrixWorld();
22213
22214 if ( vr.enabled ) {
22215
22216 camera = vr.getCamera( camera );
22217
22218 }
22219
22220 //
22221
22222 currentRenderState = renderStates.get( scene, camera );
22223 currentRenderState.init();
22224
22225 scene.onBeforeRender( _this, scene, camera, renderTarget );
22226
22227 _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
22228 _frustum.setFromMatrix( _projScreenMatrix );
22229
22230 _localClippingEnabled = this.localClippingEnabled;
22231 _clippingEnabled = _clipping.init( this.clippingPlanes, _localClippingEnabled, camera );
22232
22233 currentRenderList = renderLists.get( scene, camera );
22234 currentRenderList.init();
22235
22236 projectObject( scene, camera, _this.sortObjects );
22237
22238 if ( _this.sortObjects === true ) {
22239
22240 currentRenderList.sort();
22241
22242 }
22243
22244 //
22245
22246 if ( _clippingEnabled ) _clipping.beginShadows();
22247
22248 var shadowsArray = currentRenderState.state.shadowsArray;
22249
22250 shadowMap.render( shadowsArray, scene, camera );
22251
22252 currentRenderState.setupLights( camera );
22253
22254 if ( _clippingEnabled ) _clipping.endShadows();
22255
22256 //
22257
22258 if ( this.info.autoReset ) this.info.reset();
22259
22260 if ( renderTarget === undefined ) {
22261
22262 renderTarget = null;
22263
22264 }
22265
22266 this.setRenderTarget( renderTarget );
22267
22268 //
22269
22270 background.render( currentRenderList, scene, camera, forceClear );
22271
22272 // render scene
22273
22274 var opaqueObjects = currentRenderList.opaque;
22275 var transparentObjects = currentRenderList.transparent;
22276
22277 if ( scene.overrideMaterial ) {
22278
22279 var overrideMaterial = scene.overrideMaterial;
22280
22281 if ( opaqueObjects.length ) renderObjects( opaqueObjects, scene, camera, overrideMaterial );
22282 if ( transparentObjects.length ) renderObjects( transparentObjects, scene, camera, overrideMaterial );
22283
22284 } else {
22285
22286 // opaque pass (front-to-back order)
22287
22288 if ( opaqueObjects.length ) renderObjects( opaqueObjects, scene, camera );
22289
22290 // transparent pass (back-to-front order)
22291
22292 if ( transparentObjects.length ) renderObjects( transparentObjects, scene, camera );
22293
22294 }
22295
22296 // custom renderers
22297
22298 var spritesArray = currentRenderState.state.spritesArray;
22299
22300 spriteRenderer.render( spritesArray, scene, camera );
22301
22302 // Generate mipmap if we're using any kind of mipmap filtering
22303
22304 if ( renderTarget ) {
22305
22306 textures.updateRenderTargetMipmap( renderTarget );
22307
22308 }
22309
22310 // Ensure depth buffer writing is enabled so it can be cleared on next render
22311
22312 state.buffers.depth.setTest( true );
22313 state.buffers.depth.setMask( true );
22314 state.buffers.color.setMask( true );
22315
22316 state.setPolygonOffset( false );
22317
22318 scene.onAfterRender( _this, scene, camera );
22319
22320 if ( vr.enabled ) {
22321
22322 vr.submitFrame();
22323
22324 }
22325
22326 // _gl.finish();
22327
22328 currentRenderList = null;
22329 currentRenderState = null;
22330
22331 };
22332
22333 /*
22334 // TODO Duplicated code (Frustum)
22335
22336 var _sphere = new Sphere();
22337
22338 function isObjectViewable( object ) {
22339
22340 var geometry = object.geometry;
22341
22342 if ( geometry.boundingSphere === null )
22343 geometry.computeBoundingSphere();
22344
22345 _sphere.copy( geometry.boundingSphere ).
22346 applyMatrix4( object.matrixWorld );
22347
22348 return isSphereViewable( _sphere );
22349
22350 }
22351
22352 function isSpriteViewable( sprite ) {
22353
22354 _sphere.center.set( 0, 0, 0 );
22355 _sphere.radius = 0.7071067811865476;
22356 _sphere.applyMatrix4( sprite.matrixWorld );
22357
22358 return isSphereViewable( _sphere );
22359
22360 }
22361
22362 function isSphereViewable( sphere ) {
22363
22364 if ( ! _frustum.intersectsSphere( sphere ) ) return false;
22365
22366 var numPlanes = _clipping.numPlanes;
22367
22368 if ( numPlanes === 0 ) return true;
22369
22370 var planes = _this.clippingPlanes,
22371
22372 center = sphere.center,
22373 negRad = - sphere.radius,
22374 i = 0;
22375
22376 do {
22377
22378 // out when deeper than radius in the negative halfspace
22379 if ( planes[ i ].distanceToPoint( center ) < negRad ) return false;
22380
22381 } while ( ++ i !== numPlanes );
22382
22383 return true;
22384
22385 }
22386 */
22387
22388 function projectObject( object, camera, sortObjects ) {
22389
22390 if ( object.visible === false ) return;
22391
22392 var visible = object.layers.test( camera.layers );
22393
22394 if ( visible ) {
22395
22396 if ( object.isLight ) {
22397
22398 currentRenderState.pushLight( object );
22399
22400 if ( object.castShadow ) {
22401
22402 currentRenderState.pushShadow( object );
22403
22404 }
22405
22406 } else if ( object.isSprite ) {
22407
22408 if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) {
22409
22410 currentRenderState.pushSprite( object );
22411
22412 }
22413
22414 } else if ( object.isImmediateRenderObject ) {
22415
22416 if ( sortObjects ) {
22417
22418 _vector3.setFromMatrixPosition( object.matrixWorld )
22419 .applyMatrix4( _projScreenMatrix );
22420
22421 }
22422
22423 currentRenderList.push( object, null, object.material, _vector3.z, null );
22424
22425 } else if ( object.isMesh || object.isLine || object.isPoints ) {
22426
22427 if ( object.isSkinnedMesh ) {
22428
22429 object.skeleton.update();
22430
22431 }
22432
22433 if ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) {
22434
22435 if ( sortObjects ) {
22436
22437 _vector3.setFromMatrixPosition( object.matrixWorld )
22438 .applyMatrix4( _projScreenMatrix );
22439
22440 }
22441
22442 var geometry = objects.update( object );
22443 var material = object.material;
22444
22445 if ( Array.isArray( material ) ) {
22446
22447 var groups = geometry.groups;
22448
22449 for ( var i = 0, l = groups.length; i < l; i ++ ) {
22450
22451 var group = groups[ i ];
22452 var groupMaterial = material[ group.materialIndex ];
22453
22454 if ( groupMaterial && groupMaterial.visible ) {
22455
22456 currentRenderList.push( object, geometry, groupMaterial, _vector3.z, group );
22457
22458 }
22459
22460 }
22461
22462 } else if ( material.visible ) {
22463
22464 currentRenderList.push( object, geometry, material, _vector3.z, null );
22465
22466 }
22467
22468 }
22469
22470 }
22471
22472 }
22473
22474 var children = object.children;
22475
22476 for ( var i = 0, l = children.length; i < l; i ++ ) {
22477
22478 projectObject( children[ i ], camera, sortObjects );
22479
22480 }
22481
22482 }
22483
22484 function renderObjects( renderList, scene, camera, overrideMaterial ) {
22485
22486 for ( var i = 0, l = renderList.length; i < l; i ++ ) {
22487
22488 var renderItem = renderList[ i ];
22489
22490 var object = renderItem.object;
22491 var geometry = renderItem.geometry;
22492 var material = overrideMaterial === undefined ? renderItem.material : overrideMaterial;
22493 var group = renderItem.group;
22494
22495 if ( camera.isArrayCamera ) {
22496
22497 _currentArrayCamera = camera;
22498
22499 var cameras = camera.cameras;
22500
22501 for ( var j = 0, jl = cameras.length; j < jl; j ++ ) {
22502
22503 var camera2 = cameras[ j ];
22504
22505 if ( object.layers.test( camera2.layers ) ) {
22506
22507 var bounds = camera2.bounds;
22508
22509 var x = bounds.x * _width;
22510 var y = bounds.y * _height;
22511 var width = bounds.z * _width;
22512 var height = bounds.w * _height;
22513
22514 state.viewport( _currentViewport.set( x, y, width, height ).multiplyScalar( _pixelRatio ) );
22515
22516 renderObject( object, scene, camera2, geometry, material, group );
22517
22518 }
22519
22520 }
22521
22522 } else {
22523
22524 _currentArrayCamera = null;
22525
22526 renderObject( object, scene, camera, geometry, material, group );
22527
22528 }
22529
22530 }
22531
22532 }
22533
22534 function renderObject( object, scene, camera, geometry, material, group ) {
22535
22536 object.onBeforeRender( _this, scene, camera, geometry, material, group );
22537 currentRenderState = renderStates.get( scene, _currentArrayCamera || camera );
22538
22539 object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
22540 object.normalMatrix.getNormalMatrix( object.modelViewMatrix );
22541
22542 if ( object.isImmediateRenderObject ) {
22543
22544 var frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 );
22545
22546 state.setMaterial( material, frontFaceCW );
22547
22548 var program = setProgram( camera, scene.fog, material, object );
22549
22550 _currentGeometryProgram = '';
22551
22552 renderObjectImmediate( object, program, material );
22553
22554 } else {
22555
22556 _this.renderBufferDirect( camera, scene.fog, geometry, material, object, group );
22557
22558 }
22559
22560 object.onAfterRender( _this, scene, camera, geometry, material, group );
22561 currentRenderState = renderStates.get( scene, _currentArrayCamera || camera );
22562
22563 }
22564
22565 function initMaterial( material, fog, object ) {
22566
22567 var materialProperties = properties.get( material );
22568
22569 var lights = currentRenderState.state.lights;
22570 var shadowsArray = currentRenderState.state.shadowsArray;
22571
22572 var parameters = programCache.getParameters(
22573 material, lights.state, shadowsArray, fog, _clipping.numPlanes, _clipping.numIntersection, object );
22574
22575 var code = programCache.getProgramCode( material, parameters );
22576
22577 var program = materialProperties.program;
22578 var programChange = true;
22579
22580 if ( program === undefined ) {
22581
22582 // new material
22583 material.addEventListener( 'dispose', onMaterialDispose );
22584
22585 } else if ( program.code !== code ) {
22586
22587 // changed glsl or parameters
22588 releaseMaterialProgramReference( material );
22589
22590 } else if ( materialProperties.lightsHash !== lights.state.hash ) {
22591
22592 properties.update( material, 'lightsHash', lights.state.hash );
22593 programChange = false;
22594
22595 } else if ( parameters.shaderID !== undefined ) {
22596
22597 // same glsl and uniform list
22598 return;
22599
22600 } else {
22601
22602 // only rebuild uniform list
22603 programChange = false;
22604
22605 }
22606
22607 if ( programChange ) {
22608
22609 if ( parameters.shaderID ) {
22610
22611 var shader = ShaderLib[ parameters.shaderID ];
22612
22613 materialProperties.shader = {
22614 name: material.type,
22615 uniforms: UniformsUtils.clone( shader.uniforms ),
22616 vertexShader: shader.vertexShader,
22617 fragmentShader: shader.fragmentShader
22618 };
22619
22620 } else {
22621
22622 materialProperties.shader = {
22623 name: material.type,
22624 uniforms: material.uniforms,
22625 vertexShader: material.vertexShader,
22626 fragmentShader: material.fragmentShader
22627 };
22628
22629 }
22630
22631 material.onBeforeCompile( materialProperties.shader, _this );
22632
22633 program = programCache.acquireProgram( material, materialProperties.shader, parameters, code );
22634
22635 materialProperties.program = program;
22636 material.program = program;
22637
22638 }
22639
22640 var programAttributes = program.getAttributes();
22641
22642 if ( material.morphTargets ) {
22643
22644 material.numSupportedMorphTargets = 0;
22645
22646 for ( var i = 0; i < _this.maxMorphTargets; i ++ ) {
22647
22648 if ( programAttributes[ 'morphTarget' + i ] >= 0 ) {
22649
22650 material.numSupportedMorphTargets ++;
22651
22652 }
22653
22654 }
22655
22656 }
22657
22658 if ( material.morphNormals ) {
22659
22660 material.numSupportedMorphNormals = 0;
22661
22662 for ( var i = 0; i < _this.maxMorphNormals; i ++ ) {
22663
22664 if ( programAttributes[ 'morphNormal' + i ] >= 0 ) {
22665
22666 material.numSupportedMorphNormals ++;
22667
22668 }
22669
22670 }
22671
22672 }
22673
22674 var uniforms = materialProperties.shader.uniforms;
22675
22676 if ( ! material.isShaderMaterial &&
22677 ! material.isRawShaderMaterial ||
22678 material.clipping === true ) {
22679
22680 materialProperties.numClippingPlanes = _clipping.numPlanes;
22681 materialProperties.numIntersection = _clipping.numIntersection;
22682 uniforms.clippingPlanes = _clipping.uniform;
22683
22684 }
22685
22686 materialProperties.fog = fog;
22687
22688 // store the light setup it was created for
22689
22690 materialProperties.lightsHash = lights.state.hash;
22691
22692 if ( material.lights ) {
22693
22694 // wire up the material to this renderer's lighting state
22695
22696 uniforms.ambientLightColor.value = lights.state.ambient;
22697 uniforms.directionalLights.value = lights.state.directional;
22698 uniforms.spotLights.value = lights.state.spot;
22699 uniforms.rectAreaLights.value = lights.state.rectArea;
22700 uniforms.pointLights.value = lights.state.point;
22701 uniforms.hemisphereLights.value = lights.state.hemi;
22702
22703 uniforms.directionalShadowMap.value = lights.state.directionalShadowMap;
22704 uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix;
22705 uniforms.spotShadowMap.value = lights.state.spotShadowMap;
22706 uniforms.spotShadowMatrix.value = lights.state.spotShadowMatrix;
22707 uniforms.pointShadowMap.value = lights.state.pointShadowMap;
22708 uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix;
22709 // TODO (abelnation): add area lights shadow info to uniforms
22710
22711 }
22712
22713 var progUniforms = materialProperties.program.getUniforms(),
22714 uniformsList =
22715 WebGLUniforms.seqWithValue( progUniforms.seq, uniforms );
22716
22717 materialProperties.uniformsList = uniformsList;
22718
22719 }
22720
22721 function setProgram( camera, fog, material, object ) {
22722
22723 _usedTextureUnits = 0;
22724
22725 var materialProperties = properties.get( material );
22726 var lights = currentRenderState.state.lights;
22727
22728 if ( _clippingEnabled ) {
22729
22730 if ( _localClippingEnabled || camera !== _currentCamera ) {
22731
22732 var useCache =
22733 camera === _currentCamera &&
22734 material.id === _currentMaterialId;
22735
22736 // we might want to call this function with some ClippingGroup
22737 // object instead of the material, once it becomes feasible
22738 // (#8465, #8379)
22739 _clipping.setState(
22740 material.clippingPlanes, material.clipIntersection, material.clipShadows,
22741 camera, materialProperties, useCache );
22742
22743 }
22744
22745 }
22746
22747 if ( material.needsUpdate === false ) {
22748
22749 if ( materialProperties.program === undefined ) {
22750
22751 material.needsUpdate = true;
22752
22753 } else if ( material.fog && materialProperties.fog !== fog ) {
22754
22755 material.needsUpdate = true;
22756
22757 } else if ( material.lights && materialProperties.lightsHash !== lights.state.hash ) {
22758
22759 material.needsUpdate = true;
22760
22761 } else if ( materialProperties.numClippingPlanes !== undefined &&
22762 ( materialProperties.numClippingPlanes !== _clipping.numPlanes ||
22763 materialProperties.numIntersection !== _clipping.numIntersection ) ) {
22764
22765 material.needsUpdate = true;
22766
22767 }
22768
22769 }
22770
22771 if ( material.needsUpdate ) {
22772
22773 initMaterial( material, fog, object );
22774 material.needsUpdate = false;
22775
22776 }
22777
22778 var refreshProgram = false;
22779 var refreshMaterial = false;
22780 var refreshLights = false;
22781
22782 var program = materialProperties.program,
22783 p_uniforms = program.getUniforms(),
22784 m_uniforms = materialProperties.shader.uniforms;
22785
22786 if ( state.useProgram( program.program ) ) {
22787
22788 refreshProgram = true;
22789 refreshMaterial = true;
22790 refreshLights = true;
22791
22792 }
22793
22794 if ( material.id !== _currentMaterialId ) {
22795
22796 _currentMaterialId = material.id;
22797
22798 refreshMaterial = true;
22799
22800 }
22801
22802 if ( refreshProgram || camera !== _currentCamera ) {
22803
22804 p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix );
22805
22806 if ( capabilities.logarithmicDepthBuffer ) {
22807
22808 p_uniforms.setValue( _gl, 'logDepthBufFC',
22809 2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) );
22810
22811 }
22812
22813 // Avoid unneeded uniform updates per ArrayCamera's sub-camera
22814
22815 if ( _currentCamera !== ( _currentArrayCamera || camera ) ) {
22816
22817 _currentCamera = ( _currentArrayCamera || camera );
22818
22819 // lighting uniforms depend on the camera so enforce an update
22820 // now, in case this material supports lights - or later, when
22821 // the next material that does gets activated:
22822
22823 refreshMaterial = true; // set to true on material change
22824 refreshLights = true; // remains set until update done
22825
22826 }
22827
22828 // load material specific uniforms
22829 // (shader material also gets them for the sake of genericity)
22830
22831 if ( material.isShaderMaterial ||
22832 material.isMeshPhongMaterial ||
22833 material.isMeshStandardMaterial ||
22834 material.envMap ) {
22835
22836 var uCamPos = p_uniforms.map.cameraPosition;
22837
22838 if ( uCamPos !== undefined ) {
22839
22840 uCamPos.setValue( _gl,
22841 _vector3.setFromMatrixPosition( camera.matrixWorld ) );
22842
22843 }
22844
22845 }
22846
22847 if ( material.isMeshPhongMaterial ||
22848 material.isMeshLambertMaterial ||
22849 material.isMeshBasicMaterial ||
22850 material.isMeshStandardMaterial ||
22851 material.isShaderMaterial ||
22852 material.skinning ) {
22853
22854 p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse );
22855
22856 }
22857
22858 }
22859
22860 // skinning uniforms must be set even if material didn't change
22861 // auto-setting of texture unit for bone texture must go before other textures
22862 // not sure why, but otherwise weird things happen
22863
22864 if ( material.skinning ) {
22865
22866 p_uniforms.setOptional( _gl, object, 'bindMatrix' );
22867 p_uniforms.setOptional( _gl, object, 'bindMatrixInverse' );
22868
22869 var skeleton = object.skeleton;
22870
22871 if ( skeleton ) {
22872
22873 var bones = skeleton.bones;
22874
22875 if ( capabilities.floatVertexTextures ) {
22876
22877 if ( skeleton.boneTexture === undefined ) {
22878
22879 // layout (1 matrix = 4 pixels)
22880 // RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)
22881 // with 8x8 pixel texture max 16 bones * 4 pixels = (8 * 8)
22882 // 16x16 pixel texture max 64 bones * 4 pixels = (16 * 16)
22883 // 32x32 pixel texture max 256 bones * 4 pixels = (32 * 32)
22884 // 64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64)
22885
22886
22887 var size = Math.sqrt( bones.length * 4 ); // 4 pixels needed for 1 matrix
22888 size = _Math.ceilPowerOfTwo( size );
22889 size = Math.max( size, 4 );
22890
22891 var boneMatrices = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel
22892 boneMatrices.set( skeleton.boneMatrices ); // copy current values
22893
22894 var boneTexture = new DataTexture( boneMatrices, size, size, RGBAFormat, FloatType );
22895 boneTexture.needsUpdate = true;
22896
22897 skeleton.boneMatrices = boneMatrices;
22898 skeleton.boneTexture = boneTexture;
22899 skeleton.boneTextureSize = size;
22900
22901 }
22902
22903 p_uniforms.setValue( _gl, 'boneTexture', skeleton.boneTexture );
22904 p_uniforms.setValue( _gl, 'boneTextureSize', skeleton.boneTextureSize );
22905
22906 } else {
22907
22908 p_uniforms.setOptional( _gl, skeleton, 'boneMatrices' );
22909
22910 }
22911
22912 }
22913
22914 }
22915
22916 if ( refreshMaterial ) {
22917
22918 p_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure );
22919 p_uniforms.setValue( _gl, 'toneMappingWhitePoint', _this.toneMappingWhitePoint );
22920
22921 if ( material.lights ) {
22922
22923 // the current material requires lighting info
22924
22925 // note: all lighting uniforms are always set correctly
22926 // they simply reference the renderer's state for their
22927 // values
22928 //
22929 // use the current material's .needsUpdate flags to set
22930 // the GL state when required
22931
22932 markUniformsLightsNeedsUpdate( m_uniforms, refreshLights );
22933
22934 }
22935
22936 // refresh uniforms common to several materials
22937
22938 if ( fog && material.fog ) {
22939
22940 refreshUniformsFog( m_uniforms, fog );
22941
22942 }
22943
22944 if ( material.isMeshBasicMaterial ) {
22945
22946 refreshUniformsCommon( m_uniforms, material );
22947
22948 } else if ( material.isMeshLambertMaterial ) {
22949
22950 refreshUniformsCommon( m_uniforms, material );
22951 refreshUniformsLambert( m_uniforms, material );
22952
22953 } else if ( material.isMeshPhongMaterial ) {
22954
22955 refreshUniformsCommon( m_uniforms, material );
22956
22957 if ( material.isMeshToonMaterial ) {
22958
22959 refreshUniformsToon( m_uniforms, material );
22960
22961 } else {
22962
22963 refreshUniformsPhong( m_uniforms, material );
22964
22965 }
22966
22967 } else if ( material.isMeshStandardMaterial ) {
22968
22969 refreshUniformsCommon( m_uniforms, material );
22970
22971 if ( material.isMeshPhysicalMaterial ) {
22972
22973 refreshUniformsPhysical( m_uniforms, material );
22974
22975 } else {
22976
22977 refreshUniformsStandard( m_uniforms, material );
22978
22979 }
22980
22981 } else if ( material.isMeshDepthMaterial ) {
22982
22983 refreshUniformsCommon( m_uniforms, material );
22984 refreshUniformsDepth( m_uniforms, material );
22985
22986 } else if ( material.isMeshDistanceMaterial ) {
22987
22988 refreshUniformsCommon( m_uniforms, material );
22989 refreshUniformsDistance( m_uniforms, material );
22990
22991 } else if ( material.isMeshNormalMaterial ) {
22992
22993 refreshUniformsCommon( m_uniforms, material );
22994 refreshUniformsNormal( m_uniforms, material );
22995
22996 } else if ( material.isLineBasicMaterial ) {
22997
22998 refreshUniformsLine( m_uniforms, material );
22999
23000 if ( material.isLineDashedMaterial ) {
23001
23002 refreshUniformsDash( m_uniforms, material );
23003
23004 }
23005
23006 } else if ( material.isPointsMaterial ) {
23007
23008 refreshUniformsPoints( m_uniforms, material );
23009
23010 } else if ( material.isShadowMaterial ) {
23011
23012 m_uniforms.color.value = material.color;
23013 m_uniforms.opacity.value = material.opacity;
23014
23015 }
23016
23017 // RectAreaLight Texture
23018 // TODO (mrdoob): Find a nicer implementation
23019
23020 if ( m_uniforms.ltc_1 !== undefined ) m_uniforms.ltc_1.value = UniformsLib.LTC_1;
23021 if ( m_uniforms.ltc_2 !== undefined ) m_uniforms.ltc_2.value = UniformsLib.LTC_2;
23022
23023 WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, _this );
23024
23025 }
23026
23027 if ( material.isShaderMaterial && material.uniformsNeedUpdate === true ) {
23028
23029 WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, _this );
23030 material.uniformsNeedUpdate = false;
23031
23032 }
23033
23034 // common matrices
23035
23036 p_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix );
23037 p_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix );
23038 p_uniforms.setValue( _gl, 'modelMatrix', object.matrixWorld );
23039
23040 return program;
23041
23042 }
23043
23044 // Uniforms (refresh uniforms objects)
23045
23046 function refreshUniformsCommon( uniforms, material ) {
23047
23048 uniforms.opacity.value = material.opacity;
23049
23050 if ( material.color ) {
23051
23052 uniforms.diffuse.value = material.color;
23053
23054 }
23055
23056 if ( material.emissive ) {
23057
23058 uniforms.emissive.value.copy( material.emissive ).multiplyScalar( material.emissiveIntensity );
23059
23060 }
23061
23062 if ( material.map ) {
23063
23064 uniforms.map.value = material.map;
23065
23066 }
23067
23068 if ( material.alphaMap ) {
23069
23070 uniforms.alphaMap.value = material.alphaMap;
23071
23072 }
23073
23074 if ( material.specularMap ) {
23075
23076 uniforms.specularMap.value = material.specularMap;
23077
23078 }
23079
23080 if ( material.envMap ) {
23081
23082 uniforms.envMap.value = material.envMap;
23083
23084 // don't flip CubeTexture envMaps, flip everything else:
23085 // WebGLRenderTargetCube will be flipped for backwards compatibility
23086 // WebGLRenderTargetCube.texture will be flipped because it's a Texture and NOT a CubeTexture
23087 // this check must be handled differently, or removed entirely, if WebGLRenderTargetCube uses a CubeTexture in the future
23088 uniforms.flipEnvMap.value = ( ! ( material.envMap && material.envMap.isCubeTexture ) ) ? 1 : - 1;
23089
23090 uniforms.reflectivity.value = material.reflectivity;
23091 uniforms.refractionRatio.value = material.refractionRatio;
23092
23093 uniforms.maxMipLevel.value = properties.get( material.envMap ).__maxMipLevel;
23094
23095 }
23096
23097 if ( material.lightMap ) {
23098
23099 uniforms.lightMap.value = material.lightMap;
23100 uniforms.lightMapIntensity.value = material.lightMapIntensity;
23101
23102 }
23103
23104 if ( material.aoMap ) {
23105
23106 uniforms.aoMap.value = material.aoMap;
23107 uniforms.aoMapIntensity.value = material.aoMapIntensity;
23108
23109 }
23110
23111 // uv repeat and offset setting priorities
23112 // 1. color map
23113 // 2. specular map
23114 // 3. normal map
23115 // 4. bump map
23116 // 5. alpha map
23117 // 6. emissive map
23118
23119 var uvScaleMap;
23120
23121 if ( material.map ) {
23122
23123 uvScaleMap = material.map;
23124
23125 } else if ( material.specularMap ) {
23126
23127 uvScaleMap = material.specularMap;
23128
23129 } else if ( material.displacementMap ) {
23130
23131 uvScaleMap = material.displacementMap;
23132
23133 } else if ( material.normalMap ) {
23134
23135 uvScaleMap = material.normalMap;
23136
23137 } else if ( material.bumpMap ) {
23138
23139 uvScaleMap = material.bumpMap;
23140
23141 } else if ( material.roughnessMap ) {
23142
23143 uvScaleMap = material.roughnessMap;
23144
23145 } else if ( material.metalnessMap ) {
23146
23147 uvScaleMap = material.metalnessMap;
23148
23149 } else if ( material.alphaMap ) {
23150
23151 uvScaleMap = material.alphaMap;
23152
23153 } else if ( material.emissiveMap ) {
23154
23155 uvScaleMap = material.emissiveMap;
23156
23157 }
23158
23159 if ( uvScaleMap !== undefined ) {
23160
23161 // backwards compatibility
23162 if ( uvScaleMap.isWebGLRenderTarget ) {
23163
23164 uvScaleMap = uvScaleMap.texture;
23165
23166 }
23167
23168 if ( uvScaleMap.matrixAutoUpdate === true ) {
23169
23170 uvScaleMap.updateMatrix();
23171
23172 }
23173
23174 uniforms.uvTransform.value.copy( uvScaleMap.matrix );
23175
23176 }
23177
23178 }
23179
23180 function refreshUniformsLine( uniforms, material ) {
23181
23182 uniforms.diffuse.value = material.color;
23183 uniforms.opacity.value = material.opacity;
23184
23185 }
23186
23187 function refreshUniformsDash( uniforms, material ) {
23188
23189 uniforms.dashSize.value = material.dashSize;
23190 uniforms.totalSize.value = material.dashSize + material.gapSize;
23191 uniforms.scale.value = material.scale;
23192
23193 }
23194
23195 function refreshUniformsPoints( uniforms, material ) {
23196
23197 uniforms.diffuse.value = material.color;
23198 uniforms.opacity.value = material.opacity;
23199 uniforms.size.value = material.size * _pixelRatio;
23200 uniforms.scale.value = _height * 0.5;
23201
23202 uniforms.map.value = material.map;
23203
23204 if ( material.map !== null ) {
23205
23206 if ( material.map.matrixAutoUpdate === true ) {
23207
23208 material.map.updateMatrix();
23209
23210 }
23211
23212 uniforms.uvTransform.value.copy( material.map.matrix );
23213
23214 }
23215
23216 }
23217
23218 function refreshUniformsFog( uniforms, fog ) {
23219
23220 uniforms.fogColor.value = fog.color;
23221
23222 if ( fog.isFog ) {
23223
23224 uniforms.fogNear.value = fog.near;
23225 uniforms.fogFar.value = fog.far;
23226
23227 } else if ( fog.isFogExp2 ) {
23228
23229 uniforms.fogDensity.value = fog.density;
23230
23231 }
23232
23233 }
23234
23235 function refreshUniformsLambert( uniforms, material ) {
23236
23237 if ( material.emissiveMap ) {
23238
23239 uniforms.emissiveMap.value = material.emissiveMap;
23240
23241 }
23242
23243 }
23244
23245 function refreshUniformsPhong( uniforms, material ) {
23246
23247 uniforms.specular.value = material.specular;
23248 uniforms.shininess.value = Math.max( material.shininess, 1e-4 ); // to prevent pow( 0.0, 0.0 )
23249
23250 if ( material.emissiveMap ) {
23251
23252 uniforms.emissiveMap.value = material.emissiveMap;
23253
23254 }
23255
23256 if ( material.bumpMap ) {
23257
23258 uniforms.bumpMap.value = material.bumpMap;
23259 uniforms.bumpScale.value = material.bumpScale;
23260
23261 }
23262
23263 if ( material.normalMap ) {
23264
23265 uniforms.normalMap.value = material.normalMap;
23266 uniforms.normalScale.value.copy( material.normalScale );
23267
23268 }
23269
23270 if ( material.displacementMap ) {
23271
23272 uniforms.displacementMap.value = material.displacementMap;
23273 uniforms.displacementScale.value = material.displacementScale;
23274 uniforms.displacementBias.value = material.displacementBias;
23275
23276 }
23277
23278 }
23279
23280 function refreshUniformsToon( uniforms, material ) {
23281
23282 refreshUniformsPhong( uniforms, material );
23283
23284 if ( material.gradientMap ) {
23285
23286 uniforms.gradientMap.value = material.gradientMap;
23287
23288 }
23289
23290 }
23291
23292 function refreshUniformsStandard( uniforms, material ) {
23293
23294 uniforms.roughness.value = material.roughness;
23295 uniforms.metalness.value = material.metalness;
23296
23297 if ( material.roughnessMap ) {
23298
23299 uniforms.roughnessMap.value = material.roughnessMap;
23300
23301 }
23302
23303 if ( material.metalnessMap ) {
23304
23305 uniforms.metalnessMap.value = material.metalnessMap;
23306
23307 }
23308
23309 if ( material.emissiveMap ) {
23310
23311 uniforms.emissiveMap.value = material.emissiveMap;
23312
23313 }
23314
23315 if ( material.bumpMap ) {
23316
23317 uniforms.bumpMap.value = material.bumpMap;
23318 uniforms.bumpScale.value = material.bumpScale;
23319
23320 }
23321
23322 if ( material.normalMap ) {
23323
23324 uniforms.normalMap.value = material.normalMap;
23325 uniforms.normalScale.value.copy( material.normalScale );
23326
23327 }
23328
23329 if ( material.displacementMap ) {
23330
23331 uniforms.displacementMap.value = material.displacementMap;
23332 uniforms.displacementScale.value = material.displacementScale;
23333 uniforms.displacementBias.value = material.displacementBias;
23334
23335 }
23336
23337 if ( material.envMap ) {
23338
23339 //uniforms.envMap.value = material.envMap; // part of uniforms common
23340 uniforms.envMapIntensity.value = material.envMapIntensity;
23341
23342 }
23343
23344 }
23345
23346 function refreshUniformsPhysical( uniforms, material ) {
23347
23348 uniforms.clearCoat.value = material.clearCoat;
23349 uniforms.clearCoatRoughness.value = material.clearCoatRoughness;
23350
23351 refreshUniformsStandard( uniforms, material );
23352
23353 }
23354
23355 function refreshUniformsDepth( uniforms, material ) {
23356
23357 if ( material.displacementMap ) {
23358
23359 uniforms.displacementMap.value = material.displacementMap;
23360 uniforms.displacementScale.value = material.displacementScale;
23361 uniforms.displacementBias.value = material.displacementBias;
23362
23363 }
23364
23365 }
23366
23367 function refreshUniformsDistance( uniforms, material ) {
23368
23369 if ( material.displacementMap ) {
23370
23371 uniforms.displacementMap.value = material.displacementMap;
23372 uniforms.displacementScale.value = material.displacementScale;
23373 uniforms.displacementBias.value = material.displacementBias;
23374
23375 }
23376
23377 uniforms.referencePosition.value.copy( material.referencePosition );
23378 uniforms.nearDistance.value = material.nearDistance;
23379 uniforms.farDistance.value = material.farDistance;
23380
23381 }
23382
23383 function refreshUniformsNormal( uniforms, material ) {
23384
23385 if ( material.bumpMap ) {
23386
23387 uniforms.bumpMap.value = material.bumpMap;
23388 uniforms.bumpScale.value = material.bumpScale;
23389
23390 }
23391
23392 if ( material.normalMap ) {
23393
23394 uniforms.normalMap.value = material.normalMap;
23395 uniforms.normalScale.value.copy( material.normalScale );
23396
23397 }
23398
23399 if ( material.displacementMap ) {
23400
23401 uniforms.displacementMap.value = material.displacementMap;
23402 uniforms.displacementScale.value = material.displacementScale;
23403 uniforms.displacementBias.value = material.displacementBias;
23404
23405 }
23406
23407 }
23408
23409 // If uniforms are marked as clean, they don't need to be loaded to the GPU.
23410
23411 function markUniformsLightsNeedsUpdate( uniforms, value ) {
23412
23413 uniforms.ambientLightColor.needsUpdate = value;
23414
23415 uniforms.directionalLights.needsUpdate = value;
23416 uniforms.pointLights.needsUpdate = value;
23417 uniforms.spotLights.needsUpdate = value;
23418 uniforms.rectAreaLights.needsUpdate = value;
23419 uniforms.hemisphereLights.needsUpdate = value;
23420
23421 }
23422
23423 // Textures
23424
23425 function allocTextureUnit() {
23426
23427 var textureUnit = _usedTextureUnits;
23428
23429 if ( textureUnit >= capabilities.maxTextures ) {
23430
23431 console.warn( 'THREE.WebGLRenderer: Trying to use ' + textureUnit + ' texture units while this GPU supports only ' + capabilities.maxTextures );
23432
23433 }
23434
23435 _usedTextureUnits += 1;
23436
23437 return textureUnit;
23438
23439 }
23440
23441 this.allocTextureUnit = allocTextureUnit;
23442
23443 // this.setTexture2D = setTexture2D;
23444 this.setTexture2D = ( function () {
23445
23446 var warned = false;
23447
23448 // backwards compatibility: peel texture.texture
23449 return function setTexture2D( texture, slot ) {
23450
23451 if ( texture && texture.isWebGLRenderTarget ) {
23452
23453 if ( ! warned ) {
23454
23455 console.warn( "THREE.WebGLRenderer.setTexture2D: don't use render targets as textures. Use their .texture property instead." );
23456 warned = true;
23457
23458 }
23459
23460 texture = texture.texture;
23461
23462 }
23463
23464 textures.setTexture2D( texture, slot );
23465
23466 };
23467
23468 }() );
23469
23470 this.setTexture = ( function () {
23471
23472 var warned = false;
23473
23474 return function setTexture( texture, slot ) {
23475
23476 if ( ! warned ) {
23477
23478 console.warn( "THREE.WebGLRenderer: .setTexture is deprecated, use setTexture2D instead." );
23479 warned = true;
23480
23481 }
23482
23483 textures.setTexture2D( texture, slot );
23484
23485 };
23486
23487 }() );
23488
23489 this.setTextureCube = ( function () {
23490
23491 var warned = false;
23492
23493 return function setTextureCube( texture, slot ) {
23494
23495 // backwards compatibility: peel texture.texture
23496 if ( texture && texture.isWebGLRenderTargetCube ) {
23497
23498 if ( ! warned ) {
23499
23500 console.warn( "THREE.WebGLRenderer.setTextureCube: don't use cube render targets as textures. Use their .texture property instead." );
23501 warned = true;
23502
23503 }
23504
23505 texture = texture.texture;
23506
23507 }
23508
23509 // currently relying on the fact that WebGLRenderTargetCube.texture is a Texture and NOT a CubeTexture
23510 // TODO: unify these code paths
23511 if ( ( texture && texture.isCubeTexture ) ||
23512 ( Array.isArray( texture.image ) && texture.image.length === 6 ) ) {
23513
23514 // CompressedTexture can have Array in image :/
23515
23516 // this function alone should take care of cube textures
23517 textures.setTextureCube( texture, slot );
23518
23519 } else {
23520
23521 // assumed: texture property of THREE.WebGLRenderTargetCube
23522
23523 textures.setTextureCubeDynamic( texture, slot );
23524
23525 }
23526
23527 };
23528
23529 }() );
23530
23531 this.getRenderTarget = function () {
23532
23533 return _currentRenderTarget;
23534
23535 };
23536
23537 this.setRenderTarget = function ( renderTarget ) {
23538
23539 _currentRenderTarget = renderTarget;
23540
23541 if ( renderTarget && properties.get( renderTarget ).__webglFramebuffer === undefined ) {
23542
23543 textures.setupRenderTarget( renderTarget );
23544
23545 }
23546
23547 var framebuffer = null;
23548 var isCube = false;
23549
23550 if ( renderTarget ) {
23551
23552 var __webglFramebuffer = properties.get( renderTarget ).__webglFramebuffer;
23553
23554 if ( renderTarget.isWebGLRenderTargetCube ) {
23555
23556 framebuffer = __webglFramebuffer[ renderTarget.activeCubeFace ];
23557 isCube = true;
23558
23559 } else {
23560
23561 framebuffer = __webglFramebuffer;
23562
23563 }
23564
23565 _currentViewport.copy( renderTarget.viewport );
23566 _currentScissor.copy( renderTarget.scissor );
23567 _currentScissorTest = renderTarget.scissorTest;
23568
23569 } else {
23570
23571 _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio );
23572 _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio );
23573 _currentScissorTest = _scissorTest;
23574
23575 }
23576
23577 if ( _currentFramebuffer !== framebuffer ) {
23578
23579 _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
23580 _currentFramebuffer = framebuffer;
23581
23582 }
23583
23584 state.viewport( _currentViewport );
23585 state.scissor( _currentScissor );
23586 state.setScissorTest( _currentScissorTest );
23587
23588 if ( isCube ) {
23589
23590 var textureProperties = properties.get( renderTarget.texture );
23591 _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + renderTarget.activeCubeFace, textureProperties.__webglTexture, renderTarget.activeMipMapLevel );
23592
23593 }
23594
23595 };
23596
23597 this.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer ) {
23598
23599 if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) {
23600
23601 console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' );
23602 return;
23603
23604 }
23605
23606 var framebuffer = properties.get( renderTarget ).__webglFramebuffer;
23607
23608 if ( framebuffer ) {
23609
23610 var restore = false;
23611
23612 if ( framebuffer !== _currentFramebuffer ) {
23613
23614 _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
23615
23616 restore = true;
23617
23618 }
23619
23620 try {
23621
23622 var texture = renderTarget.texture;
23623 var textureFormat = texture.format;
23624 var textureType = texture.type;
23625
23626 if ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_FORMAT ) ) {
23627
23628 console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' );
23629 return;
23630
23631 }
23632
23633 if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_TYPE ) && // IE11, Edge and Chrome Mac < 52 (#9513)
23634 ! ( textureType === FloatType && ( extensions.get( 'OES_texture_float' ) || extensions.get( 'WEBGL_color_buffer_float' ) ) ) && // Chrome Mac >= 52 and Firefox
23635 ! ( textureType === HalfFloatType && extensions.get( 'EXT_color_buffer_half_float' ) ) ) {
23636
23637 console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' );
23638 return;
23639
23640 }
23641
23642 if ( _gl.checkFramebufferStatus( _gl.FRAMEBUFFER ) === _gl.FRAMEBUFFER_COMPLETE ) {
23643
23644 // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604)
23645
23646 if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) {
23647
23648 _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer );
23649
23650 }
23651
23652 } else {
23653
23654 console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.' );
23655
23656 }
23657
23658 } finally {
23659
23660 if ( restore ) {
23661
23662 _gl.bindFramebuffer( _gl.FRAMEBUFFER, _currentFramebuffer );
23663
23664 }
23665
23666 }
23667
23668 }
23669
23670 };
23671
23672 this.copyFramebufferToTexture = function ( position, texture, level ) {
23673
23674 var width = texture.image.width;
23675 var height = texture.image.height;
23676 var glFormat = utils.convert( texture.format );
23677
23678 this.setTexture2D( texture, 0 );
23679
23680 _gl.copyTexImage2D( _gl.TEXTURE_2D, level || 0, glFormat, position.x, position.y, width, height, 0 );
23681
23682 };
23683
23684 this.copyTextureToTexture = function ( position, srcTexture, dstTexture, level ) {
23685
23686 var width = srcTexture.image.width;
23687 var height = srcTexture.image.height;
23688 var glFormat = utils.convert( dstTexture.format );
23689 var glType = utils.convert( dstTexture.type );
23690 var pixels = srcTexture.isDataTexture ? srcTexture.image.data : srcTexture.image;
23691
23692 this.setTexture2D( dstTexture, 0 );
23693
23694 _gl.texSubImage2D( _gl.TEXTURE_2D, level || 0, position.x, position.y, width, height, glFormat, glType, pixels );
23695
23696 };
23697
23698 }
23699
23700 /**
23701 * @author mrdoob / http://mrdoob.com/
23702 * @author alteredq / http://alteredqualia.com/
23703 */
23704
23705 function FogExp2( color, density ) {
23706
23707 this.name = '';
23708
23709 this.color = new Color( color );
23710 this.density = ( density !== undefined ) ? density : 0.00025;
23711
23712 }
23713
23714 FogExp2.prototype.isFogExp2 = true;
23715
23716 FogExp2.prototype.clone = function () {
23717
23718 return new FogExp2( this.color.getHex(), this.density );
23719
23720 };
23721
23722 FogExp2.prototype.toJSON = function ( /* meta */ ) {
23723
23724 return {
23725 type: 'FogExp2',
23726 color: this.color.getHex(),
23727 density: this.density
23728 };
23729
23730 };
23731
23732 /**
23733 * @author mrdoob / http://mrdoob.com/
23734 * @author alteredq / http://alteredqualia.com/
23735 */
23736
23737 function Fog( color, near, far ) {
23738
23739 this.name = '';
23740
23741 this.color = new Color( color );
23742
23743 this.near = ( near !== undefined ) ? near : 1;
23744 this.far = ( far !== undefined ) ? far : 1000;
23745
23746 }
23747
23748 Fog.prototype.isFog = true;
23749
23750 Fog.prototype.clone = function () {
23751
23752 return new Fog( this.color.getHex(), this.near, this.far );
23753
23754 };
23755
23756 Fog.prototype.toJSON = function ( /* meta */ ) {
23757
23758 return {
23759 type: 'Fog',
23760 color: this.color.getHex(),
23761 near: this.near,
23762 far: this.far
23763 };
23764
23765 };
23766
23767 /**
23768 * @author mrdoob / http://mrdoob.com/
23769 */
23770
23771 function Scene() {
23772
23773 Object3D.call( this );
23774
23775 this.type = 'Scene';
23776
23777 this.background = null;
23778 this.fog = null;
23779 this.overrideMaterial = null;
23780
23781 this.autoUpdate = true; // checked by the renderer
23782
23783 }
23784
23785 Scene.prototype = Object.assign( Object.create( Object3D.prototype ), {
23786
23787 constructor: Scene,
23788
23789 copy: function ( source, recursive ) {
23790
23791 Object3D.prototype.copy.call( this, source, recursive );
23792
23793 if ( source.background !== null ) this.background = source.background.clone();
23794 if ( source.fog !== null ) this.fog = source.fog.clone();
23795 if ( source.overrideMaterial !== null ) this.overrideMaterial = source.overrideMaterial.clone();
23796
23797 this.autoUpdate = source.autoUpdate;
23798 this.matrixAutoUpdate = source.matrixAutoUpdate;
23799
23800 return this;
23801
23802 },
23803
23804 toJSON: function ( meta ) {
23805
23806 var data = Object3D.prototype.toJSON.call( this, meta );
23807
23808 if ( this.background !== null ) data.object.background = this.background.toJSON( meta );
23809 if ( this.fog !== null ) data.object.fog = this.fog.toJSON();
23810
23811 return data;
23812
23813 }
23814
23815 } );
23816
23817 /**
23818 * @author alteredq / http://alteredqualia.com/
23819 *
23820 * parameters = {
23821 * color: <hex>,
23822 * opacity: <float>,
23823 * map: new THREE.Texture( <Image> ),
23824 *
23825 * uvOffset: new THREE.Vector2(),
23826 * uvScale: new THREE.Vector2()
23827 * }
23828 */
23829
23830 function SpriteMaterial( parameters ) {
23831
23832 Material.call( this );
23833
23834 this.type = 'SpriteMaterial';
23835
23836 this.color = new Color( 0xffffff );
23837 this.map = null;
23838
23839 this.rotation = 0;
23840
23841 this.fog = false;
23842 this.lights = false;
23843
23844 this.setValues( parameters );
23845
23846 }
23847
23848 SpriteMaterial.prototype = Object.create( Material.prototype );
23849 SpriteMaterial.prototype.constructor = SpriteMaterial;
23850 SpriteMaterial.prototype.isSpriteMaterial = true;
23851
23852 SpriteMaterial.prototype.copy = function ( source ) {
23853
23854 Material.prototype.copy.call( this, source );
23855
23856 this.color.copy( source.color );
23857 this.map = source.map;
23858
23859 this.rotation = source.rotation;
23860
23861 return this;
23862
23863 };
23864
23865 /**
23866 * @author mikael emtinger / http://gomo.se/
23867 * @author alteredq / http://alteredqualia.com/
23868 */
23869
23870 function Sprite( material ) {
23871
23872 Object3D.call( this );
23873
23874 this.type = 'Sprite';
23875
23876 this.material = ( material !== undefined ) ? material : new SpriteMaterial();
23877
23878 this.center = new Vector2( 0.5, 0.5 );
23879
23880 }
23881
23882 Sprite.prototype = Object.assign( Object.create( Object3D.prototype ), {
23883
23884 constructor: Sprite,
23885
23886 isSprite: true,
23887
23888 raycast: ( function () {
23889
23890 var intersectPoint = new Vector3();
23891 var worldPosition = new Vector3();
23892 var worldScale = new Vector3();
23893
23894 return function raycast( raycaster, intersects ) {
23895
23896 worldPosition.setFromMatrixPosition( this.matrixWorld );
23897 raycaster.ray.closestPointToPoint( worldPosition, intersectPoint );
23898
23899 worldScale.setFromMatrixScale( this.matrixWorld );
23900 var guessSizeSq = worldScale.x * worldScale.y / 4;
23901
23902 if ( worldPosition.distanceToSquared( intersectPoint ) > guessSizeSq ) return;
23903
23904 var distance = raycaster.ray.origin.distanceTo( intersectPoint );
23905
23906 if ( distance < raycaster.near || distance > raycaster.far ) return;
23907
23908 intersects.push( {
23909
23910 distance: distance,
23911 point: intersectPoint.clone(),
23912 face: null,
23913 object: this
23914
23915 } );
23916
23917 };
23918
23919 }() ),
23920
23921 clone: function () {
23922
23923 return new this.constructor( this.material ).copy( this );
23924
23925 },
23926
23927 copy: function ( source ) {
23928
23929 Object3D.prototype.copy.call( this, source );
23930
23931 if ( source.center !== undefined ) this.center.copy( source.center );
23932
23933 return this;
23934
23935 }
23936
23937
23938 } );
23939
23940 /**
23941 * @author mikael emtinger / http://gomo.se/
23942 * @author alteredq / http://alteredqualia.com/
23943 * @author mrdoob / http://mrdoob.com/
23944 */
23945
23946 function LOD() {
23947
23948 Object3D.call( this );
23949
23950 this.type = 'LOD';
23951
23952 Object.defineProperties( this, {
23953 levels: {
23954 enumerable: true,
23955 value: []
23956 }
23957 } );
23958
23959 }
23960
23961 LOD.prototype = Object.assign( Object.create( Object3D.prototype ), {
23962
23963 constructor: LOD,
23964
23965 copy: function ( source ) {
23966
23967 Object3D.prototype.copy.call( this, source, false );
23968
23969 var levels = source.levels;
23970
23971 for ( var i = 0, l = levels.length; i < l; i ++ ) {
23972
23973 var level = levels[ i ];
23974
23975 this.addLevel( level.object.clone(), level.distance );
23976
23977 }
23978
23979 return this;
23980
23981 },
23982
23983 addLevel: function ( object, distance ) {
23984
23985 if ( distance === undefined ) distance = 0;
23986
23987 distance = Math.abs( distance );
23988
23989 var levels = this.levels;
23990
23991 for ( var l = 0; l < levels.length; l ++ ) {
23992
23993 if ( distance < levels[ l ].distance ) {
23994
23995 break;
23996
23997 }
23998
23999 }
24000
24001 levels.splice( l, 0, { distance: distance, object: object } );
24002
24003 this.add( object );
24004
24005 },
24006
24007 getObjectForDistance: function ( distance ) {
24008
24009 var levels = this.levels;
24010
24011 for ( var i = 1, l = levels.length; i < l; i ++ ) {
24012
24013 if ( distance < levels[ i ].distance ) {
24014
24015 break;
24016
24017 }
24018
24019 }
24020
24021 return levels[ i - 1 ].object;
24022
24023 },
24024
24025 raycast: ( function () {
24026
24027 var matrixPosition = new Vector3();
24028
24029 return function raycast( raycaster, intersects ) {
24030
24031 matrixPosition.setFromMatrixPosition( this.matrixWorld );
24032
24033 var distance = raycaster.ray.origin.distanceTo( matrixPosition );
24034
24035 this.getObjectForDistance( distance ).raycast( raycaster, intersects );
24036
24037 };
24038
24039 }() ),
24040
24041 update: function () {
24042
24043 var v1 = new Vector3();
24044 var v2 = new Vector3();
24045
24046 return function update( camera ) {
24047
24048 var levels = this.levels;
24049
24050 if ( levels.length > 1 ) {
24051
24052 v1.setFromMatrixPosition( camera.matrixWorld );
24053 v2.setFromMatrixPosition( this.matrixWorld );
24054
24055 var distance = v1.distanceTo( v2 );
24056
24057 levels[ 0 ].object.visible = true;
24058
24059 for ( var i = 1, l = levels.length; i < l; i ++ ) {
24060
24061 if ( distance >= levels[ i ].distance ) {
24062
24063 levels[ i - 1 ].object.visible = false;
24064 levels[ i ].object.visible = true;
24065
24066 } else {
24067
24068 break;
24069
24070 }
24071
24072 }
24073
24074 for ( ; i < l; i ++ ) {
24075
24076 levels[ i ].object.visible = false;
24077
24078 }
24079
24080 }
24081
24082 };
24083
24084 }(),
24085
24086 toJSON: function ( meta ) {
24087
24088 var data = Object3D.prototype.toJSON.call( this, meta );
24089
24090 data.object.levels = [];
24091
24092 var levels = this.levels;
24093
24094 for ( var i = 0, l = levels.length; i < l; i ++ ) {
24095
24096 var level = levels[ i ];
24097
24098 data.object.levels.push( {
24099 object: level.object.uuid,
24100 distance: level.distance
24101 } );
24102
24103 }
24104
24105 return data;
24106
24107 }
24108
24109 } );
24110
24111 /**
24112 * @author mikael emtinger / http://gomo.se/
24113 * @author alteredq / http://alteredqualia.com/
24114 * @author michael guerrero / http://realitymeltdown.com
24115 * @author ikerr / http://verold.com
24116 */
24117
24118 function Skeleton( bones, boneInverses ) {
24119
24120 // copy the bone array
24121
24122 bones = bones || [];
24123
24124 this.bones = bones.slice( 0 );
24125 this.boneMatrices = new Float32Array( this.bones.length * 16 );
24126
24127 // use the supplied bone inverses or calculate the inverses
24128
24129 if ( boneInverses === undefined ) {
24130
24131 this.calculateInverses();
24132
24133 } else {
24134
24135 if ( this.bones.length === boneInverses.length ) {
24136
24137 this.boneInverses = boneInverses.slice( 0 );
24138
24139 } else {
24140
24141 console.warn( 'THREE.Skeleton boneInverses is the wrong length.' );
24142
24143 this.boneInverses = [];
24144
24145 for ( var i = 0, il = this.bones.length; i < il; i ++ ) {
24146
24147 this.boneInverses.push( new Matrix4() );
24148
24149 }
24150
24151 }
24152
24153 }
24154
24155 }
24156
24157 Object.assign( Skeleton.prototype, {
24158
24159 calculateInverses: function () {
24160
24161 this.boneInverses = [];
24162
24163 for ( var i = 0, il = this.bones.length; i < il; i ++ ) {
24164
24165 var inverse = new Matrix4();
24166
24167 if ( this.bones[ i ] ) {
24168
24169 inverse.getInverse( this.bones[ i ].matrixWorld );
24170
24171 }
24172
24173 this.boneInverses.push( inverse );
24174
24175 }
24176
24177 },
24178
24179 pose: function () {
24180
24181 var bone, i, il;
24182
24183 // recover the bind-time world matrices
24184
24185 for ( i = 0, il = this.bones.length; i < il; i ++ ) {
24186
24187 bone = this.bones[ i ];
24188
24189 if ( bone ) {
24190
24191 bone.matrixWorld.getInverse( this.boneInverses[ i ] );
24192
24193 }
24194
24195 }
24196
24197 // compute the local matrices, positions, rotations and scales
24198
24199 for ( i = 0, il = this.bones.length; i < il; i ++ ) {
24200
24201 bone = this.bones[ i ];
24202
24203 if ( bone ) {
24204
24205 if ( bone.parent && bone.parent.isBone ) {
24206
24207 bone.matrix.getInverse( bone.parent.matrixWorld );
24208 bone.matrix.multiply( bone.matrixWorld );
24209
24210 } else {
24211
24212 bone.matrix.copy( bone.matrixWorld );
24213
24214 }
24215
24216 bone.matrix.decompose( bone.position, bone.quaternion, bone.scale );
24217
24218 }
24219
24220 }
24221
24222 },
24223
24224 update: ( function () {
24225
24226 var offsetMatrix = new Matrix4();
24227 var identityMatrix = new Matrix4();
24228
24229 return function update() {
24230
24231 var bones = this.bones;
24232 var boneInverses = this.boneInverses;
24233 var boneMatrices = this.boneMatrices;
24234 var boneTexture = this.boneTexture;
24235
24236 // flatten bone matrices to array
24237
24238 for ( var i = 0, il = bones.length; i < il; i ++ ) {
24239
24240 // compute the offset between the current and the original transform
24241
24242 var matrix = bones[ i ] ? bones[ i ].matrixWorld : identityMatrix;
24243
24244 offsetMatrix.multiplyMatrices( matrix, boneInverses[ i ] );
24245 offsetMatrix.toArray( boneMatrices, i * 16 );
24246
24247 }
24248
24249 if ( boneTexture !== undefined ) {
24250
24251 boneTexture.needsUpdate = true;
24252
24253 }
24254
24255 };
24256
24257 } )(),
24258
24259 clone: function () {
24260
24261 return new Skeleton( this.bones, this.boneInverses );
24262
24263 },
24264
24265 getBoneByName: function ( name ) {
24266
24267 for ( var i = 0, il = this.bones.length; i < il; i ++ ) {
24268
24269 var bone = this.bones[ i ];
24270
24271 if ( bone.name === name ) {
24272
24273 return bone;
24274
24275 }
24276
24277 }
24278
24279 return undefined;
24280
24281 }
24282
24283 } );
24284
24285 /**
24286 * @author mikael emtinger / http://gomo.se/
24287 * @author alteredq / http://alteredqualia.com/
24288 * @author ikerr / http://verold.com
24289 */
24290
24291 function Bone() {
24292
24293 Object3D.call( this );
24294
24295 this.type = 'Bone';
24296
24297 }
24298
24299 Bone.prototype = Object.assign( Object.create( Object3D.prototype ), {
24300
24301 constructor: Bone,
24302
24303 isBone: true
24304
24305 } );
24306
24307 /**
24308 * @author mikael emtinger / http://gomo.se/
24309 * @author alteredq / http://alteredqualia.com/
24310 * @author ikerr / http://verold.com
24311 */
24312
24313 function SkinnedMesh( geometry, material ) {
24314
24315 Mesh.call( this, geometry, material );
24316
24317 this.type = 'SkinnedMesh';
24318
24319 this.bindMode = 'attached';
24320 this.bindMatrix = new Matrix4();
24321 this.bindMatrixInverse = new Matrix4();
24322
24323 var bones = this.initBones();
24324 var skeleton = new Skeleton( bones );
24325
24326 this.bind( skeleton, this.matrixWorld );
24327
24328 this.normalizeSkinWeights();
24329
24330 }
24331
24332 SkinnedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), {
24333
24334 constructor: SkinnedMesh,
24335
24336 isSkinnedMesh: true,
24337
24338 initBones: function () {
24339
24340 var bones = [], bone, gbone;
24341 var i, il;
24342
24343 if ( this.geometry && this.geometry.bones !== undefined ) {
24344
24345 // first, create array of 'Bone' objects from geometry data
24346
24347 for ( i = 0, il = this.geometry.bones.length; i < il; i ++ ) {
24348
24349 gbone = this.geometry.bones[ i ];
24350
24351 // create new 'Bone' object
24352
24353 bone = new Bone();
24354 bones.push( bone );
24355
24356 // apply values
24357
24358 bone.name = gbone.name;
24359 bone.position.fromArray( gbone.pos );
24360 bone.quaternion.fromArray( gbone.rotq );
24361 if ( gbone.scl !== undefined ) bone.scale.fromArray( gbone.scl );
24362
24363 }
24364
24365 // second, create bone hierarchy
24366
24367 for ( i = 0, il = this.geometry.bones.length; i < il; i ++ ) {
24368
24369 gbone = this.geometry.bones[ i ];
24370
24371 if ( ( gbone.parent !== - 1 ) && ( gbone.parent !== null ) && ( bones[ gbone.parent ] !== undefined ) ) {
24372
24373 // subsequent bones in the hierarchy
24374
24375 bones[ gbone.parent ].add( bones[ i ] );
24376
24377 } else {
24378
24379 // topmost bone, immediate child of the skinned mesh
24380
24381 this.add( bones[ i ] );
24382
24383 }
24384
24385 }
24386
24387 }
24388
24389 // now the bones are part of the scene graph and children of the skinned mesh.
24390 // let's update the corresponding matrices
24391
24392 this.updateMatrixWorld( true );
24393
24394 return bones;
24395
24396 },
24397
24398 bind: function ( skeleton, bindMatrix ) {
24399
24400 this.skeleton = skeleton;
24401
24402 if ( bindMatrix === undefined ) {
24403
24404 this.updateMatrixWorld( true );
24405
24406 this.skeleton.calculateInverses();
24407
24408 bindMatrix = this.matrixWorld;
24409
24410 }
24411
24412 this.bindMatrix.copy( bindMatrix );
24413 this.bindMatrixInverse.getInverse( bindMatrix );
24414
24415 },
24416
24417 pose: function () {
24418
24419 this.skeleton.pose();
24420
24421 },
24422
24423 normalizeSkinWeights: function () {
24424
24425 var scale, i;
24426
24427 if ( this.geometry && this.geometry.isGeometry ) {
24428
24429 for ( i = 0; i < this.geometry.skinWeights.length; i ++ ) {
24430
24431 var sw = this.geometry.skinWeights[ i ];
24432
24433 scale = 1.0 / sw.manhattanLength();
24434
24435 if ( scale !== Infinity ) {
24436
24437 sw.multiplyScalar( scale );
24438
24439 } else {
24440
24441 sw.set( 1, 0, 0, 0 ); // do something reasonable
24442
24443 }
24444
24445 }
24446
24447 } else if ( this.geometry && this.geometry.isBufferGeometry ) {
24448
24449 var vec = new Vector4();
24450
24451 var skinWeight = this.geometry.attributes.skinWeight;
24452
24453 for ( i = 0; i < skinWeight.count; i ++ ) {
24454
24455 vec.x = skinWeight.getX( i );
24456 vec.y = skinWeight.getY( i );
24457 vec.z = skinWeight.getZ( i );
24458 vec.w = skinWeight.getW( i );
24459
24460 scale = 1.0 / vec.manhattanLength();
24461
24462 if ( scale !== Infinity ) {
24463
24464 vec.multiplyScalar( scale );
24465
24466 } else {
24467
24468 vec.set( 1, 0, 0, 0 ); // do something reasonable
24469
24470 }
24471
24472 skinWeight.setXYZW( i, vec.x, vec.y, vec.z, vec.w );
24473
24474 }
24475
24476 }
24477
24478 },
24479
24480 updateMatrixWorld: function ( force ) {
24481
24482 Mesh.prototype.updateMatrixWorld.call( this, force );
24483
24484 if ( this.bindMode === 'attached' ) {
24485
24486 this.bindMatrixInverse.getInverse( this.matrixWorld );
24487
24488 } else if ( this.bindMode === 'detached' ) {
24489
24490 this.bindMatrixInverse.getInverse( this.bindMatrix );
24491
24492 } else {
24493
24494 console.warn( 'THREE.SkinnedMesh: Unrecognized bindMode: ' + this.bindMode );
24495
24496 }
24497
24498 },
24499
24500 clone: function () {
24501
24502 return new this.constructor( this.geometry, this.material ).copy( this );
24503
24504 }
24505
24506 } );
24507
24508 /**
24509 * @author mrdoob / http://mrdoob.com/
24510 * @author alteredq / http://alteredqualia.com/
24511 *
24512 * parameters = {
24513 * color: <hex>,
24514 * opacity: <float>,
24515 *
24516 * linewidth: <float>,
24517 * linecap: "round",
24518 * linejoin: "round"
24519 * }
24520 */
24521
24522 function LineBasicMaterial( parameters ) {
24523
24524 Material.call( this );
24525
24526 this.type = 'LineBasicMaterial';
24527
24528 this.color = new Color( 0xffffff );
24529
24530 this.linewidth = 1;
24531 this.linecap = 'round';
24532 this.linejoin = 'round';
24533
24534 this.lights = false;
24535
24536 this.setValues( parameters );
24537
24538 }
24539
24540 LineBasicMaterial.prototype = Object.create( Material.prototype );
24541 LineBasicMaterial.prototype.constructor = LineBasicMaterial;
24542
24543 LineBasicMaterial.prototype.isLineBasicMaterial = true;
24544
24545 LineBasicMaterial.prototype.copy = function ( source ) {
24546
24547 Material.prototype.copy.call( this, source );
24548
24549 this.color.copy( source.color );
24550
24551 this.linewidth = source.linewidth;
24552 this.linecap = source.linecap;
24553 this.linejoin = source.linejoin;
24554
24555 return this;
24556
24557 };
24558
24559 /**
24560 * @author mrdoob / http://mrdoob.com/
24561 */
24562
24563 function Line( geometry, material, mode ) {
24564
24565 if ( mode === 1 ) {
24566
24567 console.warn( 'THREE.Line: parameter THREE.LinePieces no longer supported. Created THREE.LineSegments instead.' );
24568 return new LineSegments( geometry, material );
24569
24570 }
24571
24572 Object3D.call( this );
24573
24574 this.type = 'Line';
24575
24576 this.geometry = geometry !== undefined ? geometry : new BufferGeometry();
24577 this.material = material !== undefined ? material : new LineBasicMaterial( { color: Math.random() * 0xffffff } );
24578
24579 }
24580
24581 Line.prototype = Object.assign( Object.create( Object3D.prototype ), {
24582
24583 constructor: Line,
24584
24585 isLine: true,
24586
24587 computeLineDistances: ( function () {
24588
24589 var start = new Vector3();
24590 var end = new Vector3();
24591
24592 return function computeLineDistances() {
24593
24594 var geometry = this.geometry;
24595
24596 if ( geometry.isBufferGeometry ) {
24597
24598 // we assume non-indexed geometry
24599
24600 if ( geometry.index === null ) {
24601
24602 var positionAttribute = geometry.attributes.position;
24603 var lineDistances = [ 0 ];
24604
24605 for ( var i = 1, l = positionAttribute.count; i < l; i ++ ) {
24606
24607 start.fromBufferAttribute( positionAttribute, i - 1 );
24608 end.fromBufferAttribute( positionAttribute, i );
24609
24610 lineDistances[ i ] = lineDistances[ i - 1 ];
24611 lineDistances[ i ] += start.distanceTo( end );
24612
24613 }
24614
24615 geometry.addAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );
24616
24617 } else {
24618
24619 console.warn( 'THREE.Line.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );
24620
24621 }
24622
24623 } else if ( geometry.isGeometry ) {
24624
24625 var vertices = geometry.vertices;
24626 var lineDistances = geometry.lineDistances;
24627
24628 lineDistances[ 0 ] = 0;
24629
24630 for ( var i = 1, l = vertices.length; i < l; i ++ ) {
24631
24632 lineDistances[ i ] = lineDistances[ i - 1 ];
24633 lineDistances[ i ] += vertices[ i - 1 ].distanceTo( vertices[ i ] );
24634
24635 }
24636
24637 }
24638
24639 return this;
24640
24641 };
24642
24643 }() ),
24644
24645 raycast: ( function () {
24646
24647 var inverseMatrix = new Matrix4();
24648 var ray = new Ray();
24649 var sphere = new Sphere();
24650
24651 return function raycast( raycaster, intersects ) {
24652
24653 var precision = raycaster.linePrecision;
24654 var precisionSq = precision * precision;
24655
24656 var geometry = this.geometry;
24657 var matrixWorld = this.matrixWorld;
24658
24659 // Checking boundingSphere distance to ray
24660
24661 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
24662
24663 sphere.copy( geometry.boundingSphere );
24664 sphere.applyMatrix4( matrixWorld );
24665
24666 if ( raycaster.ray.intersectsSphere( sphere ) === false ) return;
24667
24668 //
24669
24670 inverseMatrix.getInverse( matrixWorld );
24671 ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix );
24672
24673 var vStart = new Vector3();
24674 var vEnd = new Vector3();
24675 var interSegment = new Vector3();
24676 var interRay = new Vector3();
24677 var step = ( this && this.isLineSegments ) ? 2 : 1;
24678
24679 if ( geometry.isBufferGeometry ) {
24680
24681 var index = geometry.index;
24682 var attributes = geometry.attributes;
24683 var positions = attributes.position.array;
24684
24685 if ( index !== null ) {
24686
24687 var indices = index.array;
24688
24689 for ( var i = 0, l = indices.length - 1; i < l; i += step ) {
24690
24691 var a = indices[ i ];
24692 var b = indices[ i + 1 ];
24693
24694 vStart.fromArray( positions, a * 3 );
24695 vEnd.fromArray( positions, b * 3 );
24696
24697 var distSq = ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
24698
24699 if ( distSq > precisionSq ) continue;
24700
24701 interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
24702
24703 var distance = raycaster.ray.origin.distanceTo( interRay );
24704
24705 if ( distance < raycaster.near || distance > raycaster.far ) continue;
24706
24707 intersects.push( {
24708
24709 distance: distance,
24710 // What do we want? intersection point on the ray or on the segment??
24711 // point: raycaster.ray.at( distance ),
24712 point: interSegment.clone().applyMatrix4( this.matrixWorld ),
24713 index: i,
24714 face: null,
24715 faceIndex: null,
24716 object: this
24717
24718 } );
24719
24720 }
24721
24722 } else {
24723
24724 for ( var i = 0, l = positions.length / 3 - 1; i < l; i += step ) {
24725
24726 vStart.fromArray( positions, 3 * i );
24727 vEnd.fromArray( positions, 3 * i + 3 );
24728
24729 var distSq = ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
24730
24731 if ( distSq > precisionSq ) continue;
24732
24733 interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
24734
24735 var distance = raycaster.ray.origin.distanceTo( interRay );
24736
24737 if ( distance < raycaster.near || distance > raycaster.far ) continue;
24738
24739 intersects.push( {
24740
24741 distance: distance,
24742 // What do we want? intersection point on the ray or on the segment??
24743 // point: raycaster.ray.at( distance ),
24744 point: interSegment.clone().applyMatrix4( this.matrixWorld ),
24745 index: i,
24746 face: null,
24747 faceIndex: null,
24748 object: this
24749
24750 } );
24751
24752 }
24753
24754 }
24755
24756 } else if ( geometry.isGeometry ) {
24757
24758 var vertices = geometry.vertices;
24759 var nbVertices = vertices.length;
24760
24761 for ( var i = 0; i < nbVertices - 1; i += step ) {
24762
24763 var distSq = ray.distanceSqToSegment( vertices[ i ], vertices[ i + 1 ], interRay, interSegment );
24764
24765 if ( distSq > precisionSq ) continue;
24766
24767 interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
24768
24769 var distance = raycaster.ray.origin.distanceTo( interRay );
24770
24771 if ( distance < raycaster.near || distance > raycaster.far ) continue;
24772
24773 intersects.push( {
24774
24775 distance: distance,
24776 // What do we want? intersection point on the ray or on the segment??
24777 // point: raycaster.ray.at( distance ),
24778 point: interSegment.clone().applyMatrix4( this.matrixWorld ),
24779 index: i,
24780 face: null,
24781 faceIndex: null,
24782 object: this
24783
24784 } );
24785
24786 }
24787
24788 }
24789
24790 };
24791
24792 }() ),
24793
24794 clone: function () {
24795
24796 return new this.constructor( this.geometry, this.material ).copy( this );
24797
24798 }
24799
24800 } );
24801
24802 /**
24803 * @author mrdoob / http://mrdoob.com/
24804 */
24805
24806 function LineSegments( geometry, material ) {
24807
24808 Line.call( this, geometry, material );
24809
24810 this.type = 'LineSegments';
24811
24812 }
24813
24814 LineSegments.prototype = Object.assign( Object.create( Line.prototype ), {
24815
24816 constructor: LineSegments,
24817
24818 isLineSegments: true,
24819
24820 computeLineDistances: ( function () {
24821
24822 var start = new Vector3();
24823 var end = new Vector3();
24824
24825 return function computeLineDistances() {
24826
24827 var geometry = this.geometry;
24828
24829 if ( geometry.isBufferGeometry ) {
24830
24831 // we assume non-indexed geometry
24832
24833 if ( geometry.index === null ) {
24834
24835 var positionAttribute = geometry.attributes.position;
24836 var lineDistances = [];
24837
24838 for ( var i = 0, l = positionAttribute.count; i < l; i += 2 ) {
24839
24840 start.fromBufferAttribute( positionAttribute, i );
24841 end.fromBufferAttribute( positionAttribute, i + 1 );
24842
24843 lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ];
24844 lineDistances[ i + 1 ] = lineDistances[ i ] + start.distanceTo( end );
24845
24846 }
24847
24848 geometry.addAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );
24849
24850 } else {
24851
24852 console.warn( 'THREE.LineSegments.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );
24853
24854 }
24855
24856 } else if ( geometry.isGeometry ) {
24857
24858 var vertices = geometry.vertices;
24859 var lineDistances = geometry.lineDistances;
24860
24861 for ( var i = 0, l = vertices.length; i < l; i += 2 ) {
24862
24863 start.copy( vertices[ i ] );
24864 end.copy( vertices[ i + 1 ] );
24865
24866 lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ];
24867 lineDistances[ i + 1 ] = lineDistances[ i ] + start.distanceTo( end );
24868
24869 }
24870
24871 }
24872
24873 return this;
24874
24875 };
24876
24877 }() )
24878
24879 } );
24880
24881 /**
24882 * @author mgreter / http://github.com/mgreter
24883 */
24884
24885 function LineLoop( geometry, material ) {
24886
24887 Line.call( this, geometry, material );
24888
24889 this.type = 'LineLoop';
24890
24891 }
24892
24893 LineLoop.prototype = Object.assign( Object.create( Line.prototype ), {
24894
24895 constructor: LineLoop,
24896
24897 isLineLoop: true,
24898
24899 } );
24900
24901 /**
24902 * @author mrdoob / http://mrdoob.com/
24903 * @author alteredq / http://alteredqualia.com/
24904 *
24905 * parameters = {
24906 * color: <hex>,
24907 * opacity: <float>,
24908 * map: new THREE.Texture( <Image> ),
24909 *
24910 * size: <float>,
24911 * sizeAttenuation: <bool>
24912 * }
24913 */
24914
24915 function PointsMaterial( parameters ) {
24916
24917 Material.call( this );
24918
24919 this.type = 'PointsMaterial';
24920
24921 this.color = new Color( 0xffffff );
24922
24923 this.map = null;
24924
24925 this.size = 1;
24926 this.sizeAttenuation = true;
24927
24928 this.lights = false;
24929
24930 this.setValues( parameters );
24931
24932 }
24933
24934 PointsMaterial.prototype = Object.create( Material.prototype );
24935 PointsMaterial.prototype.constructor = PointsMaterial;
24936
24937 PointsMaterial.prototype.isPointsMaterial = true;
24938
24939 PointsMaterial.prototype.copy = function ( source ) {
24940
24941 Material.prototype.copy.call( this, source );
24942
24943 this.color.copy( source.color );
24944
24945 this.map = source.map;
24946
24947 this.size = source.size;
24948 this.sizeAttenuation = source.sizeAttenuation;
24949
24950 return this;
24951
24952 };
24953
24954 /**
24955 * @author alteredq / http://alteredqualia.com/
24956 */
24957
24958 function Points( geometry, material ) {
24959
24960 Object3D.call( this );
24961
24962 this.type = 'Points';
24963
24964 this.geometry = geometry !== undefined ? geometry : new BufferGeometry();
24965 this.material = material !== undefined ? material : new PointsMaterial( { color: Math.random() * 0xffffff } );
24966
24967 }
24968
24969 Points.prototype = Object.assign( Object.create( Object3D.prototype ), {
24970
24971 constructor: Points,
24972
24973 isPoints: true,
24974
24975 raycast: ( function () {
24976
24977 var inverseMatrix = new Matrix4();
24978 var ray = new Ray();
24979 var sphere = new Sphere();
24980
24981 return function raycast( raycaster, intersects ) {
24982
24983 var object = this;
24984 var geometry = this.geometry;
24985 var matrixWorld = this.matrixWorld;
24986 var threshold = raycaster.params.Points.threshold;
24987
24988 // Checking boundingSphere distance to ray
24989
24990 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
24991
24992 sphere.copy( geometry.boundingSphere );
24993 sphere.applyMatrix4( matrixWorld );
24994 sphere.radius += threshold;
24995
24996 if ( raycaster.ray.intersectsSphere( sphere ) === false ) return;
24997
24998 //
24999
25000 inverseMatrix.getInverse( matrixWorld );
25001 ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix );
25002
25003 var localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
25004 var localThresholdSq = localThreshold * localThreshold;
25005 var position = new Vector3();
25006 var intersectPoint = new Vector3();
25007
25008 function testPoint( point, index ) {
25009
25010 var rayPointDistanceSq = ray.distanceSqToPoint( point );
25011
25012 if ( rayPointDistanceSq < localThresholdSq ) {
25013
25014 ray.closestPointToPoint( point, intersectPoint );
25015 intersectPoint.applyMatrix4( matrixWorld );
25016
25017 var distance = raycaster.ray.origin.distanceTo( intersectPoint );
25018
25019 if ( distance < raycaster.near || distance > raycaster.far ) return;
25020
25021 intersects.push( {
25022
25023 distance: distance,
25024 distanceToRay: Math.sqrt( rayPointDistanceSq ),
25025 point: intersectPoint.clone(),
25026 index: index,
25027 face: null,
25028 object: object
25029
25030 } );
25031
25032 }
25033
25034 }
25035
25036 if ( geometry.isBufferGeometry ) {
25037
25038 var index = geometry.index;
25039 var attributes = geometry.attributes;
25040 var positions = attributes.position.array;
25041
25042 if ( index !== null ) {
25043
25044 var indices = index.array;
25045
25046 for ( var i = 0, il = indices.length; i < il; i ++ ) {
25047
25048 var a = indices[ i ];
25049
25050 position.fromArray( positions, a * 3 );
25051
25052 testPoint( position, a );
25053
25054 }
25055
25056 } else {
25057
25058 for ( var i = 0, l = positions.length / 3; i < l; i ++ ) {
25059
25060 position.fromArray( positions, i * 3 );
25061
25062 testPoint( position, i );
25063
25064 }
25065
25066 }
25067
25068 } else {
25069
25070 var vertices = geometry.vertices;
25071
25072 for ( var i = 0, l = vertices.length; i < l; i ++ ) {
25073
25074 testPoint( vertices[ i ], i );
25075
25076 }
25077
25078 }
25079
25080 };
25081
25082 }() ),
25083
25084 clone: function () {
25085
25086 return new this.constructor( this.geometry, this.material ).copy( this );
25087
25088 }
25089
25090 } );
25091
25092 /**
25093 * @author mrdoob / http://mrdoob.com/
25094 */
25095
25096 function Group() {
25097
25098 Object3D.call( this );
25099
25100 this.type = 'Group';
25101
25102 }
25103
25104 Group.prototype = Object.assign( Object.create( Object3D.prototype ), {
25105
25106 constructor: Group,
25107
25108 isGroup: true
25109
25110 } );
25111
25112 /**
25113 * @author mrdoob / http://mrdoob.com/
25114 */
25115
25116 function VideoTexture( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
25117
25118 Texture.call( this, video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
25119
25120 this.generateMipmaps = false;
25121
25122 }
25123
25124 VideoTexture.prototype = Object.assign( Object.create( Texture.prototype ), {
25125
25126 constructor: VideoTexture,
25127
25128 isVideoTexture: true,
25129
25130 update: function () {
25131
25132 var video = this.image;
25133
25134 if ( video.readyState >= video.HAVE_CURRENT_DATA ) {
25135
25136 this.needsUpdate = true;
25137
25138 }
25139
25140 }
25141
25142 } );
25143
25144 /**
25145 * @author alteredq / http://alteredqualia.com/
25146 */
25147
25148 function CompressedTexture( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) {
25149
25150 Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
25151
25152 this.image = { width: width, height: height };
25153 this.mipmaps = mipmaps;
25154
25155 // no flipping for cube textures
25156 // (also flipping doesn't work for compressed textures )
25157
25158 this.flipY = false;
25159
25160 // can't generate mipmaps for compressed textures
25161 // mips must be embedded in DDS files
25162
25163 this.generateMipmaps = false;
25164
25165 }
25166
25167 CompressedTexture.prototype = Object.create( Texture.prototype );
25168 CompressedTexture.prototype.constructor = CompressedTexture;
25169
25170 CompressedTexture.prototype.isCompressedTexture = true;
25171
25172 /**
25173 * @author Matt DesLauriers / @mattdesl
25174 * @author atix / arthursilber.de
25175 */
25176
25177 function DepthTexture( width, height, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format ) {
25178
25179 format = format !== undefined ? format : DepthFormat;
25180
25181 if ( format !== DepthFormat && format !== DepthStencilFormat ) {
25182
25183 throw new Error( 'DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat' );
25184
25185 }
25186
25187 if ( type === undefined && format === DepthFormat ) type = UnsignedShortType;
25188 if ( type === undefined && format === DepthStencilFormat ) type = UnsignedInt248Type;
25189
25190 Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
25191
25192 this.image = { width: width, height: height };
25193
25194 this.magFilter = magFilter !== undefined ? magFilter : NearestFilter;
25195 this.minFilter = minFilter !== undefined ? minFilter : NearestFilter;
25196
25197 this.flipY = false;
25198 this.generateMipmaps = false;
25199
25200 }
25201
25202 DepthTexture.prototype = Object.create( Texture.prototype );
25203 DepthTexture.prototype.constructor = DepthTexture;
25204 DepthTexture.prototype.isDepthTexture = true;
25205
25206 /**
25207 * @author mrdoob / http://mrdoob.com/
25208 * @author Mugen87 / https://github.com/Mugen87
25209 */
25210
25211 function WireframeGeometry( geometry ) {
25212
25213 BufferGeometry.call( this );
25214
25215 this.type = 'WireframeGeometry';
25216
25217 // buffer
25218
25219 var vertices = [];
25220
25221 // helper variables
25222
25223 var i, j, l, o, ol;
25224 var edge = [ 0, 0 ], edges = {}, e, edge1, edge2;
25225 var key, keys = [ 'a', 'b', 'c' ];
25226 var vertex;
25227
25228 // different logic for Geometry and BufferGeometry
25229
25230 if ( geometry && geometry.isGeometry ) {
25231
25232 // create a data structure that contains all edges without duplicates
25233
25234 var faces = geometry.faces;
25235
25236 for ( i = 0, l = faces.length; i < l; i ++ ) {
25237
25238 var face = faces[ i ];
25239
25240 for ( j = 0; j < 3; j ++ ) {
25241
25242 edge1 = face[ keys[ j ] ];
25243 edge2 = face[ keys[ ( j + 1 ) % 3 ] ];
25244 edge[ 0 ] = Math.min( edge1, edge2 ); // sorting prevents duplicates
25245 edge[ 1 ] = Math.max( edge1, edge2 );
25246
25247 key = edge[ 0 ] + ',' + edge[ 1 ];
25248
25249 if ( edges[ key ] === undefined ) {
25250
25251 edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ] };
25252
25253 }
25254
25255 }
25256
25257 }
25258
25259 // generate vertices
25260
25261 for ( key in edges ) {
25262
25263 e = edges[ key ];
25264
25265 vertex = geometry.vertices[ e.index1 ];
25266 vertices.push( vertex.x, vertex.y, vertex.z );
25267
25268 vertex = geometry.vertices[ e.index2 ];
25269 vertices.push( vertex.x, vertex.y, vertex.z );
25270
25271 }
25272
25273 } else if ( geometry && geometry.isBufferGeometry ) {
25274
25275 var position, indices, groups;
25276 var group, start, count;
25277 var index1, index2;
25278
25279 vertex = new Vector3();
25280
25281 if ( geometry.index !== null ) {
25282
25283 // indexed BufferGeometry
25284
25285 position = geometry.attributes.position;
25286 indices = geometry.index;
25287 groups = geometry.groups;
25288
25289 if ( groups.length === 0 ) {
25290
25291 groups = [ { start: 0, count: indices.count, materialIndex: 0 } ];
25292
25293 }
25294
25295 // create a data structure that contains all eges without duplicates
25296
25297 for ( o = 0, ol = groups.length; o < ol; ++ o ) {
25298
25299 group = groups[ o ];
25300
25301 start = group.start;
25302 count = group.count;
25303
25304 for ( i = start, l = ( start + count ); i < l; i += 3 ) {
25305
25306 for ( j = 0; j < 3; j ++ ) {
25307
25308 edge1 = indices.getX( i + j );
25309 edge2 = indices.getX( i + ( j + 1 ) % 3 );
25310 edge[ 0 ] = Math.min( edge1, edge2 ); // sorting prevents duplicates
25311 edge[ 1 ] = Math.max( edge1, edge2 );
25312
25313 key = edge[ 0 ] + ',' + edge[ 1 ];
25314
25315 if ( edges[ key ] === undefined ) {
25316
25317 edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ] };
25318
25319 }
25320
25321 }
25322
25323 }
25324
25325 }
25326
25327 // generate vertices
25328
25329 for ( key in edges ) {
25330
25331 e = edges[ key ];
25332
25333 vertex.fromBufferAttribute( position, e.index1 );
25334 vertices.push( vertex.x, vertex.y, vertex.z );
25335
25336 vertex.fromBufferAttribute( position, e.index2 );
25337 vertices.push( vertex.x, vertex.y, vertex.z );
25338
25339 }
25340
25341 } else {
25342
25343 // non-indexed BufferGeometry
25344
25345 position = geometry.attributes.position;
25346
25347 for ( i = 0, l = ( position.count / 3 ); i < l; i ++ ) {
25348
25349 for ( j = 0; j < 3; j ++ ) {
25350
25351 // three edges per triangle, an edge is represented as (index1, index2)
25352 // e.g. the first triangle has the following edges: (0,1),(1,2),(2,0)
25353
25354 index1 = 3 * i + j;
25355 vertex.fromBufferAttribute( position, index1 );
25356 vertices.push( vertex.x, vertex.y, vertex.z );
25357
25358 index2 = 3 * i + ( ( j + 1 ) % 3 );
25359 vertex.fromBufferAttribute( position, index2 );
25360 vertices.push( vertex.x, vertex.y, vertex.z );
25361
25362 }
25363
25364 }
25365
25366 }
25367
25368 }
25369
25370 // build geometry
25371
25372 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
25373
25374 }
25375
25376 WireframeGeometry.prototype = Object.create( BufferGeometry.prototype );
25377 WireframeGeometry.prototype.constructor = WireframeGeometry;
25378
25379 /**
25380 * @author zz85 / https://github.com/zz85
25381 * @author Mugen87 / https://github.com/Mugen87
25382 *
25383 * Parametric Surfaces Geometry
25384 * based on the brilliant article by @prideout http://prideout.net/blog/?p=44
25385 */
25386
25387 // ParametricGeometry
25388
25389 function ParametricGeometry( func, slices, stacks ) {
25390
25391 Geometry.call( this );
25392
25393 this.type = 'ParametricGeometry';
25394
25395 this.parameters = {
25396 func: func,
25397 slices: slices,
25398 stacks: stacks
25399 };
25400
25401 this.fromBufferGeometry( new ParametricBufferGeometry( func, slices, stacks ) );
25402 this.mergeVertices();
25403
25404 }
25405
25406 ParametricGeometry.prototype = Object.create( Geometry.prototype );
25407 ParametricGeometry.prototype.constructor = ParametricGeometry;
25408
25409 // ParametricBufferGeometry
25410
25411 function ParametricBufferGeometry( func, slices, stacks ) {
25412
25413 BufferGeometry.call( this );
25414
25415 this.type = 'ParametricBufferGeometry';
25416
25417 this.parameters = {
25418 func: func,
25419 slices: slices,
25420 stacks: stacks
25421 };
25422
25423 // buffers
25424
25425 var indices = [];
25426 var vertices = [];
25427 var normals = [];
25428 var uvs = [];
25429
25430 var EPS = 0.00001;
25431
25432 var normal = new Vector3();
25433
25434 var p0 = new Vector3(), p1 = new Vector3();
25435 var pu = new Vector3(), pv = new Vector3();
25436
25437 var i, j;
25438
25439 // generate vertices, normals and uvs
25440
25441 var sliceCount = slices + 1;
25442
25443 for ( i = 0; i <= stacks; i ++ ) {
25444
25445 var v = i / stacks;
25446
25447 for ( j = 0; j <= slices; j ++ ) {
25448
25449 var u = j / slices;
25450
25451 // vertex
25452
25453 func( u, v, p0 );
25454 vertices.push( p0.x, p0.y, p0.z );
25455
25456 // normal
25457
25458 // approximate tangent vectors via finite differences
25459
25460 if ( u - EPS >= 0 ) {
25461
25462 func( u - EPS, v, p1 );
25463 pu.subVectors( p0, p1 );
25464
25465 } else {
25466
25467 func( u + EPS, v, p1 );
25468 pu.subVectors( p1, p0 );
25469
25470 }
25471
25472 if ( v - EPS >= 0 ) {
25473
25474 func( u, v - EPS, p1 );
25475 pv.subVectors( p0, p1 );
25476
25477 } else {
25478
25479 func( u, v + EPS, p1 );
25480 pv.subVectors( p1, p0 );
25481
25482 }
25483
25484 // cross product of tangent vectors returns surface normal
25485
25486 normal.crossVectors( pu, pv ).normalize();
25487 normals.push( normal.x, normal.y, normal.z );
25488
25489 // uv
25490
25491 uvs.push( u, v );
25492
25493 }
25494
25495 }
25496
25497 // generate indices
25498
25499 for ( i = 0; i < stacks; i ++ ) {
25500
25501 for ( j = 0; j < slices; j ++ ) {
25502
25503 var a = i * sliceCount + j;
25504 var b = i * sliceCount + j + 1;
25505 var c = ( i + 1 ) * sliceCount + j + 1;
25506 var d = ( i + 1 ) * sliceCount + j;
25507
25508 // faces one and two
25509
25510 indices.push( a, b, d );
25511 indices.push( b, c, d );
25512
25513 }
25514
25515 }
25516
25517 // build geometry
25518
25519 this.setIndex( indices );
25520 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
25521 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
25522 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
25523
25524 }
25525
25526 ParametricBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
25527 ParametricBufferGeometry.prototype.constructor = ParametricBufferGeometry;
25528
25529 /**
25530 * @author clockworkgeek / https://github.com/clockworkgeek
25531 * @author timothypratley / https://github.com/timothypratley
25532 * @author WestLangley / http://github.com/WestLangley
25533 * @author Mugen87 / https://github.com/Mugen87
25534 */
25535
25536 // PolyhedronGeometry
25537
25538 function PolyhedronGeometry( vertices, indices, radius, detail ) {
25539
25540 Geometry.call( this );
25541
25542 this.type = 'PolyhedronGeometry';
25543
25544 this.parameters = {
25545 vertices: vertices,
25546 indices: indices,
25547 radius: radius,
25548 detail: detail
25549 };
25550
25551 this.fromBufferGeometry( new PolyhedronBufferGeometry( vertices, indices, radius, detail ) );
25552 this.mergeVertices();
25553
25554 }
25555
25556 PolyhedronGeometry.prototype = Object.create( Geometry.prototype );
25557 PolyhedronGeometry.prototype.constructor = PolyhedronGeometry;
25558
25559 // PolyhedronBufferGeometry
25560
25561 function PolyhedronBufferGeometry( vertices, indices, radius, detail ) {
25562
25563 BufferGeometry.call( this );
25564
25565 this.type = 'PolyhedronBufferGeometry';
25566
25567 this.parameters = {
25568 vertices: vertices,
25569 indices: indices,
25570 radius: radius,
25571 detail: detail
25572 };
25573
25574 radius = radius || 1;
25575 detail = detail || 0;
25576
25577 // default buffer data
25578
25579 var vertexBuffer = [];
25580 var uvBuffer = [];
25581
25582 // the subdivision creates the vertex buffer data
25583
25584 subdivide( detail );
25585
25586 // all vertices should lie on a conceptual sphere with a given radius
25587
25588 appplyRadius( radius );
25589
25590 // finally, create the uv data
25591
25592 generateUVs();
25593
25594 // build non-indexed geometry
25595
25596 this.addAttribute( 'position', new Float32BufferAttribute( vertexBuffer, 3 ) );
25597 this.addAttribute( 'normal', new Float32BufferAttribute( vertexBuffer.slice(), 3 ) );
25598 this.addAttribute( 'uv', new Float32BufferAttribute( uvBuffer, 2 ) );
25599
25600 if ( detail === 0 ) {
25601
25602 this.computeVertexNormals(); // flat normals
25603
25604 } else {
25605
25606 this.normalizeNormals(); // smooth normals
25607
25608 }
25609
25610 // helper functions
25611
25612 function subdivide( detail ) {
25613
25614 var a = new Vector3();
25615 var b = new Vector3();
25616 var c = new Vector3();
25617
25618 // iterate over all faces and apply a subdivison with the given detail value
25619
25620 for ( var i = 0; i < indices.length; i += 3 ) {
25621
25622 // get the vertices of the face
25623
25624 getVertexByIndex( indices[ i + 0 ], a );
25625 getVertexByIndex( indices[ i + 1 ], b );
25626 getVertexByIndex( indices[ i + 2 ], c );
25627
25628 // perform subdivision
25629
25630 subdivideFace( a, b, c, detail );
25631
25632 }
25633
25634 }
25635
25636 function subdivideFace( a, b, c, detail ) {
25637
25638 var cols = Math.pow( 2, detail );
25639
25640 // we use this multidimensional array as a data structure for creating the subdivision
25641
25642 var v = [];
25643
25644 var i, j;
25645
25646 // construct all of the vertices for this subdivision
25647
25648 for ( i = 0; i <= cols; i ++ ) {
25649
25650 v[ i ] = [];
25651
25652 var aj = a.clone().lerp( c, i / cols );
25653 var bj = b.clone().lerp( c, i / cols );
25654
25655 var rows = cols - i;
25656
25657 for ( j = 0; j <= rows; j ++ ) {
25658
25659 if ( j === 0 && i === cols ) {
25660
25661 v[ i ][ j ] = aj;
25662
25663 } else {
25664
25665 v[ i ][ j ] = aj.clone().lerp( bj, j / rows );
25666
25667 }
25668
25669 }
25670
25671 }
25672
25673 // construct all of the faces
25674
25675 for ( i = 0; i < cols; i ++ ) {
25676
25677 for ( j = 0; j < 2 * ( cols - i ) - 1; j ++ ) {
25678
25679 var k = Math.floor( j / 2 );
25680
25681 if ( j % 2 === 0 ) {
25682
25683 pushVertex( v[ i ][ k + 1 ] );
25684 pushVertex( v[ i + 1 ][ k ] );
25685 pushVertex( v[ i ][ k ] );
25686
25687 } else {
25688
25689 pushVertex( v[ i ][ k + 1 ] );
25690 pushVertex( v[ i + 1 ][ k + 1 ] );
25691 pushVertex( v[ i + 1 ][ k ] );
25692
25693 }
25694
25695 }
25696
25697 }
25698
25699 }
25700
25701 function appplyRadius( radius ) {
25702
25703 var vertex = new Vector3();
25704
25705 // iterate over the entire buffer and apply the radius to each vertex
25706
25707 for ( var i = 0; i < vertexBuffer.length; i += 3 ) {
25708
25709 vertex.x = vertexBuffer[ i + 0 ];
25710 vertex.y = vertexBuffer[ i + 1 ];
25711 vertex.z = vertexBuffer[ i + 2 ];
25712
25713 vertex.normalize().multiplyScalar( radius );
25714
25715 vertexBuffer[ i + 0 ] = vertex.x;
25716 vertexBuffer[ i + 1 ] = vertex.y;
25717 vertexBuffer[ i + 2 ] = vertex.z;
25718
25719 }
25720
25721 }
25722
25723 function generateUVs() {
25724
25725 var vertex = new Vector3();
25726
25727 for ( var i = 0; i < vertexBuffer.length; i += 3 ) {
25728
25729 vertex.x = vertexBuffer[ i + 0 ];
25730 vertex.y = vertexBuffer[ i + 1 ];
25731 vertex.z = vertexBuffer[ i + 2 ];
25732
25733 var u = azimuth( vertex ) / 2 / Math.PI + 0.5;
25734 var v = inclination( vertex ) / Math.PI + 0.5;
25735 uvBuffer.push( u, 1 - v );
25736
25737 }
25738
25739 correctUVs();
25740
25741 correctSeam();
25742
25743 }
25744
25745 function correctSeam() {
25746
25747 // handle case when face straddles the seam, see #3269
25748
25749 for ( var i = 0; i < uvBuffer.length; i += 6 ) {
25750
25751 // uv data of a single face
25752
25753 var x0 = uvBuffer[ i + 0 ];
25754 var x1 = uvBuffer[ i + 2 ];
25755 var x2 = uvBuffer[ i + 4 ];
25756
25757 var max = Math.max( x0, x1, x2 );
25758 var min = Math.min( x0, x1, x2 );
25759
25760 // 0.9 is somewhat arbitrary
25761
25762 if ( max > 0.9 && min < 0.1 ) {
25763
25764 if ( x0 < 0.2 ) uvBuffer[ i + 0 ] += 1;
25765 if ( x1 < 0.2 ) uvBuffer[ i + 2 ] += 1;
25766 if ( x2 < 0.2 ) uvBuffer[ i + 4 ] += 1;
25767
25768 }
25769
25770 }
25771
25772 }
25773
25774 function pushVertex( vertex ) {
25775
25776 vertexBuffer.push( vertex.x, vertex.y, vertex.z );
25777
25778 }
25779
25780 function getVertexByIndex( index, vertex ) {
25781
25782 var stride = index * 3;
25783
25784 vertex.x = vertices[ stride + 0 ];
25785 vertex.y = vertices[ stride + 1 ];
25786 vertex.z = vertices[ stride + 2 ];
25787
25788 }
25789
25790 function correctUVs() {
25791
25792 var a = new Vector3();
25793 var b = new Vector3();
25794 var c = new Vector3();
25795
25796 var centroid = new Vector3();
25797
25798 var uvA = new Vector2();
25799 var uvB = new Vector2();
25800 var uvC = new Vector2();
25801
25802 for ( var i = 0, j = 0; i < vertexBuffer.length; i += 9, j += 6 ) {
25803
25804 a.set( vertexBuffer[ i + 0 ], vertexBuffer[ i + 1 ], vertexBuffer[ i + 2 ] );
25805 b.set( vertexBuffer[ i + 3 ], vertexBuffer[ i + 4 ], vertexBuffer[ i + 5 ] );
25806 c.set( vertexBuffer[ i + 6 ], vertexBuffer[ i + 7 ], vertexBuffer[ i + 8 ] );
25807
25808 uvA.set( uvBuffer[ j + 0 ], uvBuffer[ j + 1 ] );
25809 uvB.set( uvBuffer[ j + 2 ], uvBuffer[ j + 3 ] );
25810 uvC.set( uvBuffer[ j + 4 ], uvBuffer[ j + 5 ] );
25811
25812 centroid.copy( a ).add( b ).add( c ).divideScalar( 3 );
25813
25814 var azi = azimuth( centroid );
25815
25816 correctUV( uvA, j + 0, a, azi );
25817 correctUV( uvB, j + 2, b, azi );
25818 correctUV( uvC, j + 4, c, azi );
25819
25820 }
25821
25822 }
25823
25824 function correctUV( uv, stride, vector, azimuth ) {
25825
25826 if ( ( azimuth < 0 ) && ( uv.x === 1 ) ) {
25827
25828 uvBuffer[ stride ] = uv.x - 1;
25829
25830 }
25831
25832 if ( ( vector.x === 0 ) && ( vector.z === 0 ) ) {
25833
25834 uvBuffer[ stride ] = azimuth / 2 / Math.PI + 0.5;
25835
25836 }
25837
25838 }
25839
25840 // Angle around the Y axis, counter-clockwise when looking from above.
25841
25842 function azimuth( vector ) {
25843
25844 return Math.atan2( vector.z, - vector.x );
25845
25846 }
25847
25848
25849 // Angle above the XZ plane.
25850
25851 function inclination( vector ) {
25852
25853 return Math.atan2( - vector.y, Math.sqrt( ( vector.x * vector.x ) + ( vector.z * vector.z ) ) );
25854
25855 }
25856
25857 }
25858
25859 PolyhedronBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
25860 PolyhedronBufferGeometry.prototype.constructor = PolyhedronBufferGeometry;
25861
25862 /**
25863 * @author timothypratley / https://github.com/timothypratley
25864 * @author Mugen87 / https://github.com/Mugen87
25865 */
25866
25867 // TetrahedronGeometry
25868
25869 function TetrahedronGeometry( radius, detail ) {
25870
25871 Geometry.call( this );
25872
25873 this.type = 'TetrahedronGeometry';
25874
25875 this.parameters = {
25876 radius: radius,
25877 detail: detail
25878 };
25879
25880 this.fromBufferGeometry( new TetrahedronBufferGeometry( radius, detail ) );
25881 this.mergeVertices();
25882
25883 }
25884
25885 TetrahedronGeometry.prototype = Object.create( Geometry.prototype );
25886 TetrahedronGeometry.prototype.constructor = TetrahedronGeometry;
25887
25888 // TetrahedronBufferGeometry
25889
25890 function TetrahedronBufferGeometry( radius, detail ) {
25891
25892 var vertices = [
25893 1, 1, 1, - 1, - 1, 1, - 1, 1, - 1, 1, - 1, - 1
25894 ];
25895
25896 var indices = [
25897 2, 1, 0, 0, 3, 2, 1, 3, 0, 2, 3, 1
25898 ];
25899
25900 PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail );
25901
25902 this.type = 'TetrahedronBufferGeometry';
25903
25904 this.parameters = {
25905 radius: radius,
25906 detail: detail
25907 };
25908
25909 }
25910
25911 TetrahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype );
25912 TetrahedronBufferGeometry.prototype.constructor = TetrahedronBufferGeometry;
25913
25914 /**
25915 * @author timothypratley / https://github.com/timothypratley
25916 * @author Mugen87 / https://github.com/Mugen87
25917 */
25918
25919 // OctahedronGeometry
25920
25921 function OctahedronGeometry( radius, detail ) {
25922
25923 Geometry.call( this );
25924
25925 this.type = 'OctahedronGeometry';
25926
25927 this.parameters = {
25928 radius: radius,
25929 detail: detail
25930 };
25931
25932 this.fromBufferGeometry( new OctahedronBufferGeometry( radius, detail ) );
25933 this.mergeVertices();
25934
25935 }
25936
25937 OctahedronGeometry.prototype = Object.create( Geometry.prototype );
25938 OctahedronGeometry.prototype.constructor = OctahedronGeometry;
25939
25940 // OctahedronBufferGeometry
25941
25942 function OctahedronBufferGeometry( radius, detail ) {
25943
25944 var vertices = [
25945 1, 0, 0, - 1, 0, 0, 0, 1, 0,
25946 0, - 1, 0, 0, 0, 1, 0, 0, - 1
25947 ];
25948
25949 var indices = [
25950 0, 2, 4, 0, 4, 3, 0, 3, 5,
25951 0, 5, 2, 1, 2, 5, 1, 5, 3,
25952 1, 3, 4, 1, 4, 2
25953 ];
25954
25955 PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail );
25956
25957 this.type = 'OctahedronBufferGeometry';
25958
25959 this.parameters = {
25960 radius: radius,
25961 detail: detail
25962 };
25963
25964 }
25965
25966 OctahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype );
25967 OctahedronBufferGeometry.prototype.constructor = OctahedronBufferGeometry;
25968
25969 /**
25970 * @author timothypratley / https://github.com/timothypratley
25971 * @author Mugen87 / https://github.com/Mugen87
25972 */
25973
25974 // IcosahedronGeometry
25975
25976 function IcosahedronGeometry( radius, detail ) {
25977
25978 Geometry.call( this );
25979
25980 this.type = 'IcosahedronGeometry';
25981
25982 this.parameters = {
25983 radius: radius,
25984 detail: detail
25985 };
25986
25987 this.fromBufferGeometry( new IcosahedronBufferGeometry( radius, detail ) );
25988 this.mergeVertices();
25989
25990 }
25991
25992 IcosahedronGeometry.prototype = Object.create( Geometry.prototype );
25993 IcosahedronGeometry.prototype.constructor = IcosahedronGeometry;
25994
25995 // IcosahedronBufferGeometry
25996
25997 function IcosahedronBufferGeometry( radius, detail ) {
25998
25999 var t = ( 1 + Math.sqrt( 5 ) ) / 2;
26000
26001 var vertices = [
26002 - 1, t, 0, 1, t, 0, - 1, - t, 0, 1, - t, 0,
26003 0, - 1, t, 0, 1, t, 0, - 1, - t, 0, 1, - t,
26004 t, 0, - 1, t, 0, 1, - t, 0, - 1, - t, 0, 1
26005 ];
26006
26007 var indices = [
26008 0, 11, 5, 0, 5, 1, 0, 1, 7, 0, 7, 10, 0, 10, 11,
26009 1, 5, 9, 5, 11, 4, 11, 10, 2, 10, 7, 6, 7, 1, 8,
26010 3, 9, 4, 3, 4, 2, 3, 2, 6, 3, 6, 8, 3, 8, 9,
26011 4, 9, 5, 2, 4, 11, 6, 2, 10, 8, 6, 7, 9, 8, 1
26012 ];
26013
26014 PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail );
26015
26016 this.type = 'IcosahedronBufferGeometry';
26017
26018 this.parameters = {
26019 radius: radius,
26020 detail: detail
26021 };
26022
26023 }
26024
26025 IcosahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype );
26026 IcosahedronBufferGeometry.prototype.constructor = IcosahedronBufferGeometry;
26027
26028 /**
26029 * @author Abe Pazos / https://hamoid.com
26030 * @author Mugen87 / https://github.com/Mugen87
26031 */
26032
26033 // DodecahedronGeometry
26034
26035 function DodecahedronGeometry( radius, detail ) {
26036
26037 Geometry.call( this );
26038
26039 this.type = 'DodecahedronGeometry';
26040
26041 this.parameters = {
26042 radius: radius,
26043 detail: detail
26044 };
26045
26046 this.fromBufferGeometry( new DodecahedronBufferGeometry( radius, detail ) );
26047 this.mergeVertices();
26048
26049 }
26050
26051 DodecahedronGeometry.prototype = Object.create( Geometry.prototype );
26052 DodecahedronGeometry.prototype.constructor = DodecahedronGeometry;
26053
26054 // DodecahedronBufferGeometry
26055
26056 function DodecahedronBufferGeometry( radius, detail ) {
26057
26058 var t = ( 1 + Math.sqrt( 5 ) ) / 2;
26059 var r = 1 / t;
26060
26061 var vertices = [
26062
26063 // (±1, ±1, ±1)
26064 - 1, - 1, - 1, - 1, - 1, 1,
26065 - 1, 1, - 1, - 1, 1, 1,
26066 1, - 1, - 1, 1, - 1, 1,
26067 1, 1, - 1, 1, 1, 1,
26068
26069 // (0, ±1/φ, ±φ)
26070 0, - r, - t, 0, - r, t,
26071 0, r, - t, 0, r, t,
26072
26073 // (±1/φ, ±φ, 0)
26074 - r, - t, 0, - r, t, 0,
26075 r, - t, 0, r, t, 0,
26076
26077 // (±φ, 0, ±1/φ)
26078 - t, 0, - r, t, 0, - r,
26079 - t, 0, r, t, 0, r
26080 ];
26081
26082 var indices = [
26083 3, 11, 7, 3, 7, 15, 3, 15, 13,
26084 7, 19, 17, 7, 17, 6, 7, 6, 15,
26085 17, 4, 8, 17, 8, 10, 17, 10, 6,
26086 8, 0, 16, 8, 16, 2, 8, 2, 10,
26087 0, 12, 1, 0, 1, 18, 0, 18, 16,
26088 6, 10, 2, 6, 2, 13, 6, 13, 15,
26089 2, 16, 18, 2, 18, 3, 2, 3, 13,
26090 18, 1, 9, 18, 9, 11, 18, 11, 3,
26091 4, 14, 12, 4, 12, 0, 4, 0, 8,
26092 11, 9, 5, 11, 5, 19, 11, 19, 7,
26093 19, 5, 14, 19, 14, 4, 19, 4, 17,
26094 1, 12, 14, 1, 14, 5, 1, 5, 9
26095 ];
26096
26097 PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail );
26098
26099 this.type = 'DodecahedronBufferGeometry';
26100
26101 this.parameters = {
26102 radius: radius,
26103 detail: detail
26104 };
26105
26106 }
26107
26108 DodecahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype );
26109 DodecahedronBufferGeometry.prototype.constructor = DodecahedronBufferGeometry;
26110
26111 /**
26112 * @author oosmoxiecode / https://github.com/oosmoxiecode
26113 * @author WestLangley / https://github.com/WestLangley
26114 * @author zz85 / https://github.com/zz85
26115 * @author miningold / https://github.com/miningold
26116 * @author jonobr1 / https://github.com/jonobr1
26117 * @author Mugen87 / https://github.com/Mugen87
26118 *
26119 */
26120
26121 // TubeGeometry
26122
26123 function TubeGeometry( path, tubularSegments, radius, radialSegments, closed, taper ) {
26124
26125 Geometry.call( this );
26126
26127 this.type = 'TubeGeometry';
26128
26129 this.parameters = {
26130 path: path,
26131 tubularSegments: tubularSegments,
26132 radius: radius,
26133 radialSegments: radialSegments,
26134 closed: closed
26135 };
26136
26137 if ( taper !== undefined ) console.warn( 'THREE.TubeGeometry: taper has been removed.' );
26138
26139 var bufferGeometry = new TubeBufferGeometry( path, tubularSegments, radius, radialSegments, closed );
26140
26141 // expose internals
26142
26143 this.tangents = bufferGeometry.tangents;
26144 this.normals = bufferGeometry.normals;
26145 this.binormals = bufferGeometry.binormals;
26146
26147 // create geometry
26148
26149 this.fromBufferGeometry( bufferGeometry );
26150 this.mergeVertices();
26151
26152 }
26153
26154 TubeGeometry.prototype = Object.create( Geometry.prototype );
26155 TubeGeometry.prototype.constructor = TubeGeometry;
26156
26157 // TubeBufferGeometry
26158
26159 function TubeBufferGeometry( path, tubularSegments, radius, radialSegments, closed ) {
26160
26161 BufferGeometry.call( this );
26162
26163 this.type = 'TubeBufferGeometry';
26164
26165 this.parameters = {
26166 path: path,
26167 tubularSegments: tubularSegments,
26168 radius: radius,
26169 radialSegments: radialSegments,
26170 closed: closed
26171 };
26172
26173 tubularSegments = tubularSegments || 64;
26174 radius = radius || 1;
26175 radialSegments = radialSegments || 8;
26176 closed = closed || false;
26177
26178 var frames = path.computeFrenetFrames( tubularSegments, closed );
26179
26180 // expose internals
26181
26182 this.tangents = frames.tangents;
26183 this.normals = frames.normals;
26184 this.binormals = frames.binormals;
26185
26186 // helper variables
26187
26188 var vertex = new Vector3();
26189 var normal = new Vector3();
26190 var uv = new Vector2();
26191 var P = new Vector3();
26192
26193 var i, j;
26194
26195 // buffer
26196
26197 var vertices = [];
26198 var normals = [];
26199 var uvs = [];
26200 var indices = [];
26201
26202 // create buffer data
26203
26204 generateBufferData();
26205
26206 // build geometry
26207
26208 this.setIndex( indices );
26209 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
26210 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
26211 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
26212
26213 // functions
26214
26215 function generateBufferData() {
26216
26217 for ( i = 0; i < tubularSegments; i ++ ) {
26218
26219 generateSegment( i );
26220
26221 }
26222
26223 // if the geometry is not closed, generate the last row of vertices and normals
26224 // at the regular position on the given path
26225 //
26226 // if the geometry is closed, duplicate the first row of vertices and normals (uvs will differ)
26227
26228 generateSegment( ( closed === false ) ? tubularSegments : 0 );
26229
26230 // uvs are generated in a separate function.
26231 // this makes it easy compute correct values for closed geometries
26232
26233 generateUVs();
26234
26235 // finally create faces
26236
26237 generateIndices();
26238
26239 }
26240
26241 function generateSegment( i ) {
26242
26243 // we use getPointAt to sample evenly distributed points from the given path
26244
26245 P = path.getPointAt( i / tubularSegments, P );
26246
26247 // retrieve corresponding normal and binormal
26248
26249 var N = frames.normals[ i ];
26250 var B = frames.binormals[ i ];
26251
26252 // generate normals and vertices for the current segment
26253
26254 for ( j = 0; j <= radialSegments; j ++ ) {
26255
26256 var v = j / radialSegments * Math.PI * 2;
26257
26258 var sin = Math.sin( v );
26259 var cos = - Math.cos( v );
26260
26261 // normal
26262
26263 normal.x = ( cos * N.x + sin * B.x );
26264 normal.y = ( cos * N.y + sin * B.y );
26265 normal.z = ( cos * N.z + sin * B.z );
26266 normal.normalize();
26267
26268 normals.push( normal.x, normal.y, normal.z );
26269
26270 // vertex
26271
26272 vertex.x = P.x + radius * normal.x;
26273 vertex.y = P.y + radius * normal.y;
26274 vertex.z = P.z + radius * normal.z;
26275
26276 vertices.push( vertex.x, vertex.y, vertex.z );
26277
26278 }
26279
26280 }
26281
26282 function generateIndices() {
26283
26284 for ( j = 1; j <= tubularSegments; j ++ ) {
26285
26286 for ( i = 1; i <= radialSegments; i ++ ) {
26287
26288 var a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 );
26289 var b = ( radialSegments + 1 ) * j + ( i - 1 );
26290 var c = ( radialSegments + 1 ) * j + i;
26291 var d = ( radialSegments + 1 ) * ( j - 1 ) + i;
26292
26293 // faces
26294
26295 indices.push( a, b, d );
26296 indices.push( b, c, d );
26297
26298 }
26299
26300 }
26301
26302 }
26303
26304 function generateUVs() {
26305
26306 for ( i = 0; i <= tubularSegments; i ++ ) {
26307
26308 for ( j = 0; j <= radialSegments; j ++ ) {
26309
26310 uv.x = i / tubularSegments;
26311 uv.y = j / radialSegments;
26312
26313 uvs.push( uv.x, uv.y );
26314
26315 }
26316
26317 }
26318
26319 }
26320
26321 }
26322
26323 TubeBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
26324 TubeBufferGeometry.prototype.constructor = TubeBufferGeometry;
26325
26326 /**
26327 * @author oosmoxiecode
26328 * @author Mugen87 / https://github.com/Mugen87
26329 *
26330 * based on http://www.blackpawn.com/texts/pqtorus/
26331 */
26332
26333 // TorusKnotGeometry
26334
26335 function TorusKnotGeometry( radius, tube, tubularSegments, radialSegments, p, q, heightScale ) {
26336
26337 Geometry.call( this );
26338
26339 this.type = 'TorusKnotGeometry';
26340
26341 this.parameters = {
26342 radius: radius,
26343 tube: tube,
26344 tubularSegments: tubularSegments,
26345 radialSegments: radialSegments,
26346 p: p,
26347 q: q
26348 };
26349
26350 if ( heightScale !== undefined ) console.warn( 'THREE.TorusKnotGeometry: heightScale has been deprecated. Use .scale( x, y, z ) instead.' );
26351
26352 this.fromBufferGeometry( new TorusKnotBufferGeometry( radius, tube, tubularSegments, radialSegments, p, q ) );
26353 this.mergeVertices();
26354
26355 }
26356
26357 TorusKnotGeometry.prototype = Object.create( Geometry.prototype );
26358 TorusKnotGeometry.prototype.constructor = TorusKnotGeometry;
26359
26360 // TorusKnotBufferGeometry
26361
26362 function TorusKnotBufferGeometry( radius, tube, tubularSegments, radialSegments, p, q ) {
26363
26364 BufferGeometry.call( this );
26365
26366 this.type = 'TorusKnotBufferGeometry';
26367
26368 this.parameters = {
26369 radius: radius,
26370 tube: tube,
26371 tubularSegments: tubularSegments,
26372 radialSegments: radialSegments,
26373 p: p,
26374 q: q
26375 };
26376
26377 radius = radius || 1;
26378 tube = tube || 0.4;
26379 tubularSegments = Math.floor( tubularSegments ) || 64;
26380 radialSegments = Math.floor( radialSegments ) || 8;
26381 p = p || 2;
26382 q = q || 3;
26383
26384 // buffers
26385
26386 var indices = [];
26387 var vertices = [];
26388 var normals = [];
26389 var uvs = [];
26390
26391 // helper variables
26392
26393 var i, j;
26394
26395 var vertex = new Vector3();
26396 var normal = new Vector3();
26397
26398 var P1 = new Vector3();
26399 var P2 = new Vector3();
26400
26401 var B = new Vector3();
26402 var T = new Vector3();
26403 var N = new Vector3();
26404
26405 // generate vertices, normals and uvs
26406
26407 for ( i = 0; i <= tubularSegments; ++ i ) {
26408
26409 // the radian "u" is used to calculate the position on the torus curve of the current tubular segement
26410
26411 var u = i / tubularSegments * p * Math.PI * 2;
26412
26413 // now we calculate two points. P1 is our current position on the curve, P2 is a little farther ahead.
26414 // these points are used to create a special "coordinate space", which is necessary to calculate the correct vertex positions
26415
26416 calculatePositionOnCurve( u, p, q, radius, P1 );
26417 calculatePositionOnCurve( u + 0.01, p, q, radius, P2 );
26418
26419 // calculate orthonormal basis
26420
26421 T.subVectors( P2, P1 );
26422 N.addVectors( P2, P1 );
26423 B.crossVectors( T, N );
26424 N.crossVectors( B, T );
26425
26426 // normalize B, N. T can be ignored, we don't use it
26427
26428 B.normalize();
26429 N.normalize();
26430
26431 for ( j = 0; j <= radialSegments; ++ j ) {
26432
26433 // now calculate the vertices. they are nothing more than an extrusion of the torus curve.
26434 // because we extrude a shape in the xy-plane, there is no need to calculate a z-value.
26435
26436 var v = j / radialSegments * Math.PI * 2;
26437 var cx = - tube * Math.cos( v );
26438 var cy = tube * Math.sin( v );
26439
26440 // now calculate the final vertex position.
26441 // first we orient the extrusion with our basis vectos, then we add it to the current position on the curve
26442
26443 vertex.x = P1.x + ( cx * N.x + cy * B.x );
26444 vertex.y = P1.y + ( cx * N.y + cy * B.y );
26445 vertex.z = P1.z + ( cx * N.z + cy * B.z );
26446
26447 vertices.push( vertex.x, vertex.y, vertex.z );
26448
26449 // normal (P1 is always the center/origin of the extrusion, thus we can use it to calculate the normal)
26450
26451 normal.subVectors( vertex, P1 ).normalize();
26452
26453 normals.push( normal.x, normal.y, normal.z );
26454
26455 // uv
26456
26457 uvs.push( i / tubularSegments );
26458 uvs.push( j / radialSegments );
26459
26460 }
26461
26462 }
26463
26464 // generate indices
26465
26466 for ( j = 1; j <= tubularSegments; j ++ ) {
26467
26468 for ( i = 1; i <= radialSegments; i ++ ) {
26469
26470 // indices
26471
26472 var a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 );
26473 var b = ( radialSegments + 1 ) * j + ( i - 1 );
26474 var c = ( radialSegments + 1 ) * j + i;
26475 var d = ( radialSegments + 1 ) * ( j - 1 ) + i;
26476
26477 // faces
26478
26479 indices.push( a, b, d );
26480 indices.push( b, c, d );
26481
26482 }
26483
26484 }
26485
26486 // build geometry
26487
26488 this.setIndex( indices );
26489 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
26490 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
26491 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
26492
26493 // this function calculates the current position on the torus curve
26494
26495 function calculatePositionOnCurve( u, p, q, radius, position ) {
26496
26497 var cu = Math.cos( u );
26498 var su = Math.sin( u );
26499 var quOverP = q / p * u;
26500 var cs = Math.cos( quOverP );
26501
26502 position.x = radius * ( 2 + cs ) * 0.5 * cu;
26503 position.y = radius * ( 2 + cs ) * su * 0.5;
26504 position.z = radius * Math.sin( quOverP ) * 0.5;
26505
26506 }
26507
26508 }
26509
26510 TorusKnotBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
26511 TorusKnotBufferGeometry.prototype.constructor = TorusKnotBufferGeometry;
26512
26513 /**
26514 * @author oosmoxiecode
26515 * @author mrdoob / http://mrdoob.com/
26516 * @author Mugen87 / https://github.com/Mugen87
26517 */
26518
26519 // TorusGeometry
26520
26521 function TorusGeometry( radius, tube, radialSegments, tubularSegments, arc ) {
26522
26523 Geometry.call( this );
26524
26525 this.type = 'TorusGeometry';
26526
26527 this.parameters = {
26528 radius: radius,
26529 tube: tube,
26530 radialSegments: radialSegments,
26531 tubularSegments: tubularSegments,
26532 arc: arc
26533 };
26534
26535 this.fromBufferGeometry( new TorusBufferGeometry( radius, tube, radialSegments, tubularSegments, arc ) );
26536 this.mergeVertices();
26537
26538 }
26539
26540 TorusGeometry.prototype = Object.create( Geometry.prototype );
26541 TorusGeometry.prototype.constructor = TorusGeometry;
26542
26543 // TorusBufferGeometry
26544
26545 function TorusBufferGeometry( radius, tube, radialSegments, tubularSegments, arc ) {
26546
26547 BufferGeometry.call( this );
26548
26549 this.type = 'TorusBufferGeometry';
26550
26551 this.parameters = {
26552 radius: radius,
26553 tube: tube,
26554 radialSegments: radialSegments,
26555 tubularSegments: tubularSegments,
26556 arc: arc
26557 };
26558
26559 radius = radius || 1;
26560 tube = tube || 0.4;
26561 radialSegments = Math.floor( radialSegments ) || 8;
26562 tubularSegments = Math.floor( tubularSegments ) || 6;
26563 arc = arc || Math.PI * 2;
26564
26565 // buffers
26566
26567 var indices = [];
26568 var vertices = [];
26569 var normals = [];
26570 var uvs = [];
26571
26572 // helper variables
26573
26574 var center = new Vector3();
26575 var vertex = new Vector3();
26576 var normal = new Vector3();
26577
26578 var j, i;
26579
26580 // generate vertices, normals and uvs
26581
26582 for ( j = 0; j <= radialSegments; j ++ ) {
26583
26584 for ( i = 0; i <= tubularSegments; i ++ ) {
26585
26586 var u = i / tubularSegments * arc;
26587 var v = j / radialSegments * Math.PI * 2;
26588
26589 // vertex
26590
26591 vertex.x = ( radius + tube * Math.cos( v ) ) * Math.cos( u );
26592 vertex.y = ( radius + tube * Math.cos( v ) ) * Math.sin( u );
26593 vertex.z = tube * Math.sin( v );
26594
26595 vertices.push( vertex.x, vertex.y, vertex.z );
26596
26597 // normal
26598
26599 center.x = radius * Math.cos( u );
26600 center.y = radius * Math.sin( u );
26601 normal.subVectors( vertex, center ).normalize();
26602
26603 normals.push( normal.x, normal.y, normal.z );
26604
26605 // uv
26606
26607 uvs.push( i / tubularSegments );
26608 uvs.push( j / radialSegments );
26609
26610 }
26611
26612 }
26613
26614 // generate indices
26615
26616 for ( j = 1; j <= radialSegments; j ++ ) {
26617
26618 for ( i = 1; i <= tubularSegments; i ++ ) {
26619
26620 // indices
26621
26622 var a = ( tubularSegments + 1 ) * j + i - 1;
26623 var b = ( tubularSegments + 1 ) * ( j - 1 ) + i - 1;
26624 var c = ( tubularSegments + 1 ) * ( j - 1 ) + i;
26625 var d = ( tubularSegments + 1 ) * j + i;
26626
26627 // faces
26628
26629 indices.push( a, b, d );
26630 indices.push( b, c, d );
26631
26632 }
26633
26634 }
26635
26636 // build geometry
26637
26638 this.setIndex( indices );
26639 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
26640 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
26641 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
26642
26643 }
26644
26645 TorusBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
26646 TorusBufferGeometry.prototype.constructor = TorusBufferGeometry;
26647
26648 /**
26649 * @author Mugen87 / https://github.com/Mugen87
26650 * Port from https://github.com/mapbox/earcut (v2.1.2)
26651 */
26652
26653 var Earcut = {
26654
26655 triangulate: function ( data, holeIndices, dim ) {
26656
26657 dim = dim || 2;
26658
26659 var hasHoles = holeIndices && holeIndices.length,
26660 outerLen = hasHoles ? holeIndices[ 0 ] * dim : data.length,
26661 outerNode = linkedList( data, 0, outerLen, dim, true ),
26662 triangles = [];
26663
26664 if ( ! outerNode ) return triangles;
26665
26666 var minX, minY, maxX, maxY, x, y, invSize;
26667
26668 if ( hasHoles ) outerNode = eliminateHoles( data, holeIndices, outerNode, dim );
26669
26670 // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox
26671
26672 if ( data.length > 80 * dim ) {
26673
26674 minX = maxX = data[ 0 ];
26675 minY = maxY = data[ 1 ];
26676
26677 for ( var i = dim; i < outerLen; i += dim ) {
26678
26679 x = data[ i ];
26680 y = data[ i + 1 ];
26681 if ( x < minX ) minX = x;
26682 if ( y < minY ) minY = y;
26683 if ( x > maxX ) maxX = x;
26684 if ( y > maxY ) maxY = y;
26685
26686 }
26687
26688 // minX, minY and invSize are later used to transform coords into integers for z-order calculation
26689
26690 invSize = Math.max( maxX - minX, maxY - minY );
26691 invSize = invSize !== 0 ? 1 / invSize : 0;
26692
26693 }
26694
26695 earcutLinked( outerNode, triangles, dim, minX, minY, invSize );
26696
26697 return triangles;
26698
26699 }
26700
26701 };
26702
26703 // create a circular doubly linked list from polygon points in the specified winding order
26704
26705 function linkedList( data, start, end, dim, clockwise ) {
26706
26707 var i, last;
26708
26709 if ( clockwise === ( signedArea( data, start, end, dim ) > 0 ) ) {
26710
26711 for ( i = start; i < end; i += dim ) last = insertNode( i, data[ i ], data[ i + 1 ], last );
26712
26713 } else {
26714
26715 for ( i = end - dim; i >= start; i -= dim ) last = insertNode( i, data[ i ], data[ i + 1 ], last );
26716
26717 }
26718
26719 if ( last && equals( last, last.next ) ) {
26720
26721 removeNode( last );
26722 last = last.next;
26723
26724 }
26725
26726 return last;
26727
26728 }
26729
26730 // eliminate colinear or duplicate points
26731
26732 function filterPoints( start, end ) {
26733
26734 if ( ! start ) return start;
26735 if ( ! end ) end = start;
26736
26737 var p = start, again;
26738
26739 do {
26740
26741 again = false;
26742
26743 if ( ! p.steiner && ( equals( p, p.next ) || area( p.prev, p, p.next ) === 0 ) ) {
26744
26745 removeNode( p );
26746 p = end = p.prev;
26747 if ( p === p.next ) break;
26748 again = true;
26749
26750 } else {
26751
26752 p = p.next;
26753
26754 }
26755
26756 } while ( again || p !== end );
26757
26758 return end;
26759
26760 }
26761
26762 // main ear slicing loop which triangulates a polygon (given as a linked list)
26763
26764 function earcutLinked( ear, triangles, dim, minX, minY, invSize, pass ) {
26765
26766 if ( ! ear ) return;
26767
26768 // interlink polygon nodes in z-order
26769
26770 if ( ! pass && invSize ) indexCurve( ear, minX, minY, invSize );
26771
26772 var stop = ear, prev, next;
26773
26774 // iterate through ears, slicing them one by one
26775
26776 while ( ear.prev !== ear.next ) {
26777
26778 prev = ear.prev;
26779 next = ear.next;
26780
26781 if ( invSize ? isEarHashed( ear, minX, minY, invSize ) : isEar( ear ) ) {
26782
26783 // cut off the triangle
26784 triangles.push( prev.i / dim );
26785 triangles.push( ear.i / dim );
26786 triangles.push( next.i / dim );
26787
26788 removeNode( ear );
26789
26790 // skipping the next vertice leads to less sliver triangles
26791 ear = next.next;
26792 stop = next.next;
26793
26794 continue;
26795
26796 }
26797
26798 ear = next;
26799
26800 // if we looped through the whole remaining polygon and can't find any more ears
26801
26802 if ( ear === stop ) {
26803
26804 // try filtering points and slicing again
26805
26806 if ( ! pass ) {
26807
26808 earcutLinked( filterPoints( ear ), triangles, dim, minX, minY, invSize, 1 );
26809
26810 // if this didn't work, try curing all small self-intersections locally
26811
26812 } else if ( pass === 1 ) {
26813
26814 ear = cureLocalIntersections( ear, triangles, dim );
26815 earcutLinked( ear, triangles, dim, minX, minY, invSize, 2 );
26816
26817 // as a last resort, try splitting the remaining polygon into two
26818
26819 } else if ( pass === 2 ) {
26820
26821 splitEarcut( ear, triangles, dim, minX, minY, invSize );
26822
26823 }
26824
26825 break;
26826
26827 }
26828
26829 }
26830
26831 }
26832
26833 // check whether a polygon node forms a valid ear with adjacent nodes
26834
26835 function isEar( ear ) {
26836
26837 var a = ear.prev,
26838 b = ear,
26839 c = ear.next;
26840
26841 if ( area( a, b, c ) >= 0 ) return false; // reflex, can't be an ear
26842
26843 // now make sure we don't have other points inside the potential ear
26844 var p = ear.next.next;
26845
26846 while ( p !== ear.prev ) {
26847
26848 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 ) {
26849
26850 return false;
26851
26852 }
26853
26854 p = p.next;
26855
26856 }
26857
26858 return true;
26859
26860 }
26861
26862 function isEarHashed( ear, minX, minY, invSize ) {
26863
26864 var a = ear.prev,
26865 b = ear,
26866 c = ear.next;
26867
26868 if ( area( a, b, c ) >= 0 ) return false; // reflex, can't be an ear
26869
26870 // triangle bbox; min & max are calculated like this for speed
26871
26872 var minTX = a.x < b.x ? ( a.x < c.x ? a.x : c.x ) : ( b.x < c.x ? b.x : c.x ),
26873 minTY = a.y < b.y ? ( a.y < c.y ? a.y : c.y ) : ( b.y < c.y ? b.y : c.y ),
26874 maxTX = a.x > b.x ? ( a.x > c.x ? a.x : c.x ) : ( b.x > c.x ? b.x : c.x ),
26875 maxTY = a.y > b.y ? ( a.y > c.y ? a.y : c.y ) : ( b.y > c.y ? b.y : c.y );
26876
26877 // z-order range for the current triangle bbox;
26878
26879 var minZ = zOrder( minTX, minTY, minX, minY, invSize ),
26880 maxZ = zOrder( maxTX, maxTY, minX, minY, invSize );
26881
26882 // first look for points inside the triangle in increasing z-order
26883
26884 var p = ear.nextZ;
26885
26886 while ( p && p.z <= maxZ ) {
26887
26888 if ( p !== ear.prev && p !== ear.next &&
26889 pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) &&
26890 area( p.prev, p, p.next ) >= 0 ) return false;
26891 p = p.nextZ;
26892
26893 }
26894
26895 // then look for points in decreasing z-order
26896
26897 p = ear.prevZ;
26898
26899 while ( p && p.z >= minZ ) {
26900
26901 if ( p !== ear.prev && p !== ear.next &&
26902 pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) &&
26903 area( p.prev, p, p.next ) >= 0 ) return false;
26904
26905 p = p.prevZ;
26906
26907 }
26908
26909 return true;
26910
26911 }
26912
26913 // go through all polygon nodes and cure small local self-intersections
26914
26915 function cureLocalIntersections( start, triangles, dim ) {
26916
26917 var p = start;
26918
26919 do {
26920
26921 var a = p.prev, b = p.next.next;
26922
26923 if ( ! equals( a, b ) && intersects( a, p, p.next, b ) && locallyInside( a, b ) && locallyInside( b, a ) ) {
26924
26925 triangles.push( a.i / dim );
26926 triangles.push( p.i / dim );
26927 triangles.push( b.i / dim );
26928
26929 // remove two nodes involved
26930
26931 removeNode( p );
26932 removeNode( p.next );
26933
26934 p = start = b;
26935
26936 }
26937
26938 p = p.next;
26939
26940 } while ( p !== start );
26941
26942 return p;
26943
26944 }
26945
26946 // try splitting polygon into two and triangulate them independently
26947
26948 function splitEarcut( start, triangles, dim, minX, minY, invSize ) {
26949
26950 // look for a valid diagonal that divides the polygon into two
26951
26952 var a = start;
26953
26954 do {
26955
26956 var b = a.next.next;
26957
26958 while ( b !== a.prev ) {
26959
26960 if ( a.i !== b.i && isValidDiagonal( a, b ) ) {
26961
26962 // split the polygon in two by the diagonal
26963
26964 var c = splitPolygon( a, b );
26965
26966 // filter colinear points around the cuts
26967
26968 a = filterPoints( a, a.next );
26969 c = filterPoints( c, c.next );
26970
26971 // run earcut on each half
26972
26973 earcutLinked( a, triangles, dim, minX, minY, invSize );
26974 earcutLinked( c, triangles, dim, minX, minY, invSize );
26975 return;
26976
26977 }
26978
26979 b = b.next;
26980
26981 }
26982
26983 a = a.next;
26984
26985 } while ( a !== start );
26986
26987 }
26988
26989 // link every hole into the outer loop, producing a single-ring polygon without holes
26990
26991 function eliminateHoles( data, holeIndices, outerNode, dim ) {
26992
26993 var queue = [], i, len, start, end, list;
26994
26995 for ( i = 0, len = holeIndices.length; i < len; i ++ ) {
26996
26997 start = holeIndices[ i ] * dim;
26998 end = i < len - 1 ? holeIndices[ i + 1 ] * dim : data.length;
26999 list = linkedList( data, start, end, dim, false );
27000 if ( list === list.next ) list.steiner = true;
27001 queue.push( getLeftmost( list ) );
27002
27003 }
27004
27005 queue.sort( compareX );
27006
27007 // process holes from left to right
27008
27009 for ( i = 0; i < queue.length; i ++ ) {
27010
27011 eliminateHole( queue[ i ], outerNode );
27012 outerNode = filterPoints( outerNode, outerNode.next );
27013
27014 }
27015
27016 return outerNode;
27017
27018 }
27019
27020 function compareX( a, b ) {
27021
27022 return a.x - b.x;
27023
27024 }
27025
27026 // find a bridge between vertices that connects hole with an outer ring and and link it
27027
27028 function eliminateHole( hole, outerNode ) {
27029
27030 outerNode = findHoleBridge( hole, outerNode );
27031
27032 if ( outerNode ) {
27033
27034 var b = splitPolygon( outerNode, hole );
27035
27036 filterPoints( b, b.next );
27037
27038 }
27039
27040 }
27041
27042 // David Eberly's algorithm for finding a bridge between hole and outer polygon
27043
27044 function findHoleBridge( hole, outerNode ) {
27045
27046 var p = outerNode,
27047 hx = hole.x,
27048 hy = hole.y,
27049 qx = - Infinity,
27050 m;
27051
27052 // find a segment intersected by a ray from the hole's leftmost point to the left;
27053 // segment's endpoint with lesser x will be potential connection point
27054
27055 do {
27056
27057 if ( hy <= p.y && hy >= p.next.y && p.next.y !== p.y ) {
27058
27059 var x = p.x + ( hy - p.y ) * ( p.next.x - p.x ) / ( p.next.y - p.y );
27060
27061 if ( x <= hx && x > qx ) {
27062
27063 qx = x;
27064
27065 if ( x === hx ) {
27066
27067 if ( hy === p.y ) return p;
27068 if ( hy === p.next.y ) return p.next;
27069
27070 }
27071
27072 m = p.x < p.next.x ? p : p.next;
27073
27074 }
27075
27076 }
27077
27078 p = p.next;
27079
27080 } while ( p !== outerNode );
27081
27082 if ( ! m ) return null;
27083
27084 if ( hx === qx ) return m.prev; // hole touches outer segment; pick lower endpoint
27085
27086 // look for points inside the triangle of hole point, segment intersection and endpoint;
27087 // if there are no points found, we have a valid connection;
27088 // otherwise choose the point of the minimum angle with the ray as connection point
27089
27090 var stop = m,
27091 mx = m.x,
27092 my = m.y,
27093 tanMin = Infinity,
27094 tan;
27095
27096 p = m.next;
27097
27098 while ( p !== stop ) {
27099
27100 if ( hx >= p.x && p.x >= mx && hx !== p.x &&
27101 pointInTriangle( hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y ) ) {
27102
27103 tan = Math.abs( hy - p.y ) / ( hx - p.x ); // tangential
27104
27105 if ( ( tan < tanMin || ( tan === tanMin && p.x > m.x ) ) && locallyInside( p, hole ) ) {
27106
27107 m = p;
27108 tanMin = tan;
27109
27110 }
27111
27112 }
27113
27114 p = p.next;
27115
27116 }
27117
27118 return m;
27119
27120 }
27121
27122 // interlink polygon nodes in z-order
27123
27124 function indexCurve( start, minX, minY, invSize ) {
27125
27126 var p = start;
27127
27128 do {
27129
27130 if ( p.z === null ) p.z = zOrder( p.x, p.y, minX, minY, invSize );
27131 p.prevZ = p.prev;
27132 p.nextZ = p.next;
27133 p = p.next;
27134
27135 } while ( p !== start );
27136
27137 p.prevZ.nextZ = null;
27138 p.prevZ = null;
27139
27140 sortLinked( p );
27141
27142 }
27143
27144 // Simon Tatham's linked list merge sort algorithm
27145 // http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
27146
27147 function sortLinked( list ) {
27148
27149 var i, p, q, e, tail, numMerges, pSize, qSize, inSize = 1;
27150
27151 do {
27152
27153 p = list;
27154 list = null;
27155 tail = null;
27156 numMerges = 0;
27157
27158 while ( p ) {
27159
27160 numMerges ++;
27161 q = p;
27162 pSize = 0;
27163
27164 for ( i = 0; i < inSize; i ++ ) {
27165
27166 pSize ++;
27167 q = q.nextZ;
27168 if ( ! q ) break;
27169
27170 }
27171
27172 qSize = inSize;
27173
27174 while ( pSize > 0 || ( qSize > 0 && q ) ) {
27175
27176 if ( pSize !== 0 && ( qSize === 0 || ! q || p.z <= q.z ) ) {
27177
27178 e = p;
27179 p = p.nextZ;
27180 pSize --;
27181
27182 } else {
27183
27184 e = q;
27185 q = q.nextZ;
27186 qSize --;
27187
27188 }
27189
27190 if ( tail ) tail.nextZ = e;
27191 else list = e;
27192
27193 e.prevZ = tail;
27194 tail = e;
27195
27196 }
27197
27198 p = q;
27199
27200 }
27201
27202 tail.nextZ = null;
27203 inSize *= 2;
27204
27205 } while ( numMerges > 1 );
27206
27207 return list;
27208
27209 }
27210
27211 // z-order of a point given coords and inverse of the longer side of data bbox
27212
27213 function zOrder( x, y, minX, minY, invSize ) {
27214
27215 // coords are transformed into non-negative 15-bit integer range
27216
27217 x = 32767 * ( x - minX ) * invSize;
27218 y = 32767 * ( y - minY ) * invSize;
27219
27220 x = ( x | ( x << 8 ) ) & 0x00FF00FF;
27221 x = ( x | ( x << 4 ) ) & 0x0F0F0F0F;
27222 x = ( x | ( x << 2 ) ) & 0x33333333;
27223 x = ( x | ( x << 1 ) ) & 0x55555555;
27224
27225 y = ( y | ( y << 8 ) ) & 0x00FF00FF;
27226 y = ( y | ( y << 4 ) ) & 0x0F0F0F0F;
27227 y = ( y | ( y << 2 ) ) & 0x33333333;
27228 y = ( y | ( y << 1 ) ) & 0x55555555;
27229
27230 return x | ( y << 1 );
27231
27232 }
27233
27234 // find the leftmost node of a polygon ring
27235
27236 function getLeftmost( start ) {
27237
27238 var p = start, leftmost = start;
27239
27240 do {
27241
27242 if ( p.x < leftmost.x ) leftmost = p;
27243 p = p.next;
27244
27245 } while ( p !== start );
27246
27247 return leftmost;
27248
27249 }
27250
27251 // check if a point lies within a convex triangle
27252
27253 function pointInTriangle( ax, ay, bx, by, cx, cy, px, py ) {
27254
27255 return ( cx - px ) * ( ay - py ) - ( ax - px ) * ( cy - py ) >= 0 &&
27256 ( ax - px ) * ( by - py ) - ( bx - px ) * ( ay - py ) >= 0 &&
27257 ( bx - px ) * ( cy - py ) - ( cx - px ) * ( by - py ) >= 0;
27258
27259 }
27260
27261 // check if a diagonal between two polygon nodes is valid (lies in polygon interior)
27262
27263 function isValidDiagonal( a, b ) {
27264
27265 return a.next.i !== b.i && a.prev.i !== b.i && ! intersectsPolygon( a, b ) &&
27266 locallyInside( a, b ) && locallyInside( b, a ) && middleInside( a, b );
27267
27268 }
27269
27270 // signed area of a triangle
27271
27272 function area( p, q, r ) {
27273
27274 return ( q.y - p.y ) * ( r.x - q.x ) - ( q.x - p.x ) * ( r.y - q.y );
27275
27276 }
27277
27278 // check if two points are equal
27279
27280 function equals( p1, p2 ) {
27281
27282 return p1.x === p2.x && p1.y === p2.y;
27283
27284 }
27285
27286 // check if two segments intersect
27287
27288 function intersects( p1, q1, p2, q2 ) {
27289
27290 if ( ( equals( p1, q1 ) && equals( p2, q2 ) ) ||
27291 ( equals( p1, q2 ) && equals( p2, q1 ) ) ) return true;
27292
27293 return area( p1, q1, p2 ) > 0 !== area( p1, q1, q2 ) > 0 &&
27294 area( p2, q2, p1 ) > 0 !== area( p2, q2, q1 ) > 0;
27295
27296 }
27297
27298 // check if a polygon diagonal intersects any polygon segments
27299
27300 function intersectsPolygon( a, b ) {
27301
27302 var p = a;
27303
27304 do {
27305
27306 if ( p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i &&
27307 intersects( p, p.next, a, b ) ) {
27308
27309 return true;
27310
27311 }
27312
27313 p = p.next;
27314
27315 } while ( p !== a );
27316
27317 return false;
27318
27319 }
27320
27321 // check if a polygon diagonal is locally inside the polygon
27322
27323 function locallyInside( a, b ) {
27324
27325 return area( a.prev, a, a.next ) < 0 ?
27326 area( a, b, a.next ) >= 0 && area( a, a.prev, b ) >= 0 :
27327 area( a, b, a.prev ) < 0 || area( a, a.next, b ) < 0;
27328
27329 }
27330
27331 // check if the middle point of a polygon diagonal is inside the polygon
27332
27333 function middleInside( a, b ) {
27334
27335 var p = a,
27336 inside = false,
27337 px = ( a.x + b.x ) / 2,
27338 py = ( a.y + b.y ) / 2;
27339
27340 do {
27341
27342 if ( ( ( p.y > py ) !== ( p.next.y > py ) ) && p.next.y !== p.y &&
27343 ( px < ( p.next.x - p.x ) * ( py - p.y ) / ( p.next.y - p.y ) + p.x ) ) {
27344
27345 inside = ! inside;
27346
27347 }
27348
27349 p = p.next;
27350
27351 } while ( p !== a );
27352
27353 return inside;
27354
27355 }
27356
27357 // link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two;
27358 // if one belongs to the outer ring and another to a hole, it merges it into a single ring
27359
27360 function splitPolygon( a, b ) {
27361
27362 var a2 = new Node( a.i, a.x, a.y ),
27363 b2 = new Node( b.i, b.x, b.y ),
27364 an = a.next,
27365 bp = b.prev;
27366
27367 a.next = b;
27368 b.prev = a;
27369
27370 a2.next = an;
27371 an.prev = a2;
27372
27373 b2.next = a2;
27374 a2.prev = b2;
27375
27376 bp.next = b2;
27377 b2.prev = bp;
27378
27379 return b2;
27380
27381 }
27382
27383 // create a node and optionally link it with previous one (in a circular doubly linked list)
27384
27385 function insertNode( i, x, y, last ) {
27386
27387 var p = new Node( i, x, y );
27388
27389 if ( ! last ) {
27390
27391 p.prev = p;
27392 p.next = p;
27393
27394 } else {
27395
27396 p.next = last.next;
27397 p.prev = last;
27398 last.next.prev = p;
27399 last.next = p;
27400
27401 }
27402
27403 return p;
27404
27405 }
27406
27407 function removeNode( p ) {
27408
27409 p.next.prev = p.prev;
27410 p.prev.next = p.next;
27411
27412 if ( p.prevZ ) p.prevZ.nextZ = p.nextZ;
27413 if ( p.nextZ ) p.nextZ.prevZ = p.prevZ;
27414
27415 }
27416
27417 function Node( i, x, y ) {
27418
27419 // vertice index in coordinates array
27420 this.i = i;
27421
27422 // vertex coordinates
27423 this.x = x;
27424 this.y = y;
27425
27426 // previous and next vertice nodes in a polygon ring
27427 this.prev = null;
27428 this.next = null;
27429
27430 // z-order curve value
27431 this.z = null;
27432
27433 // previous and next nodes in z-order
27434 this.prevZ = null;
27435 this.nextZ = null;
27436
27437 // indicates whether this is a steiner point
27438 this.steiner = false;
27439
27440 }
27441
27442 function signedArea( data, start, end, dim ) {
27443
27444 var sum = 0;
27445
27446 for ( var i = start, j = end - dim; i < end; i += dim ) {
27447
27448 sum += ( data[ j ] - data[ i ] ) * ( data[ i + 1 ] + data[ j + 1 ] );
27449 j = i;
27450
27451 }
27452
27453 return sum;
27454
27455 }
27456
27457 /**
27458 * @author zz85 / http://www.lab4games.net/zz85/blog
27459 */
27460
27461 var ShapeUtils = {
27462
27463 // calculate area of the contour polygon
27464
27465 area: function ( contour ) {
27466
27467 var n = contour.length;
27468 var a = 0.0;
27469
27470 for ( var p = n - 1, q = 0; q < n; p = q ++ ) {
27471
27472 a += contour[ p ].x * contour[ q ].y - contour[ q ].x * contour[ p ].y;
27473
27474 }
27475
27476 return a * 0.5;
27477
27478 },
27479
27480 isClockWise: function ( pts ) {
27481
27482 return ShapeUtils.area( pts ) < 0;
27483
27484 },
27485
27486 triangulateShape: function ( contour, holes ) {
27487
27488 var vertices = []; // flat array of vertices like [ x0,y0, x1,y1, x2,y2, ... ]
27489 var holeIndices = []; // array of hole indices
27490 var faces = []; // final array of vertex indices like [ [ a,b,d ], [ b,c,d ] ]
27491
27492 removeDupEndPts( contour );
27493 addContour( vertices, contour );
27494
27495 //
27496
27497 var holeIndex = contour.length;
27498
27499 holes.forEach( removeDupEndPts );
27500
27501 for ( var i = 0; i < holes.length; i ++ ) {
27502
27503 holeIndices.push( holeIndex );
27504 holeIndex += holes[ i ].length;
27505 addContour( vertices, holes[ i ] );
27506
27507 }
27508
27509 //
27510
27511 var triangles = Earcut.triangulate( vertices, holeIndices );
27512
27513 //
27514
27515 for ( var i = 0; i < triangles.length; i += 3 ) {
27516
27517 faces.push( triangles.slice( i, i + 3 ) );
27518
27519 }
27520
27521 return faces;
27522
27523 }
27524
27525 };
27526
27527 function removeDupEndPts( points ) {
27528
27529 var l = points.length;
27530
27531 if ( l > 2 && points[ l - 1 ].equals( points[ 0 ] ) ) {
27532
27533 points.pop();
27534
27535 }
27536
27537 }
27538
27539 function addContour( vertices, contour ) {
27540
27541 for ( var i = 0; i < contour.length; i ++ ) {
27542
27543 vertices.push( contour[ i ].x );
27544 vertices.push( contour[ i ].y );
27545
27546 }
27547
27548 }
27549
27550 /**
27551 * @author zz85 / http://www.lab4games.net/zz85/blog
27552 *
27553 * Creates extruded geometry from a path shape.
27554 *
27555 * parameters = {
27556 *
27557 * curveSegments: <int>, // number of points on the curves
27558 * steps: <int>, // number of points for z-side extrusions / used for subdividing segments of extrude spline too
27559 * amount: <int>, // Depth to extrude the shape
27560 *
27561 * bevelEnabled: <bool>, // turn on bevel
27562 * bevelThickness: <float>, // how deep into the original shape bevel goes
27563 * bevelSize: <float>, // how far from shape outline is bevel
27564 * bevelSegments: <int>, // number of bevel layers
27565 *
27566 * extrudePath: <THREE.Curve> // curve to extrude shape along
27567 *
27568 * UVGenerator: <Object> // object that provides UV generator functions
27569 *
27570 * }
27571 */
27572
27573 // ExtrudeGeometry
27574
27575 function ExtrudeGeometry( shapes, options ) {
27576
27577 Geometry.call( this );
27578
27579 this.type = 'ExtrudeGeometry';
27580
27581 this.parameters = {
27582 shapes: shapes,
27583 options: options
27584 };
27585
27586 this.fromBufferGeometry( new ExtrudeBufferGeometry( shapes, options ) );
27587 this.mergeVertices();
27588
27589 }
27590
27591 ExtrudeGeometry.prototype = Object.create( Geometry.prototype );
27592 ExtrudeGeometry.prototype.constructor = ExtrudeGeometry;
27593
27594 // ExtrudeBufferGeometry
27595
27596 function ExtrudeBufferGeometry( shapes, options ) {
27597
27598 BufferGeometry.call( this );
27599
27600 this.type = 'ExtrudeBufferGeometry';
27601
27602 this.parameters = {
27603 shapes: shapes,
27604 options: options
27605 };
27606
27607 shapes = Array.isArray( shapes ) ? shapes : [ shapes ];
27608
27609 var scope = this;
27610
27611 var verticesArray = [];
27612 var uvArray = [];
27613
27614 for ( var i = 0, l = shapes.length; i < l; i ++ ) {
27615
27616 var shape = shapes[ i ];
27617 addShape( shape, options );
27618
27619 }
27620
27621 // build geometry
27622
27623 this.addAttribute( 'position', new Float32BufferAttribute( verticesArray, 3 ) );
27624 this.addAttribute( 'uv', new Float32BufferAttribute( uvArray, 2 ) );
27625
27626 this.computeVertexNormals();
27627
27628 // functions
27629
27630 function addShape( shape ) {
27631
27632 var placeholder = [];
27633
27634 // options
27635
27636 var curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12;
27637 var steps = options.steps !== undefined ? options.steps : 1;
27638 var amount = options.amount !== undefined ? options.amount : 100;
27639
27640 var bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true;
27641 var bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 6;
27642 var bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 2;
27643 var bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3;
27644
27645 var extrudePath = options.extrudePath;
27646
27647 var uvgen = options.UVGenerator !== undefined ? options.UVGenerator : WorldUVGenerator;
27648
27649 //
27650
27651 var extrudePts, extrudeByPath = false;
27652 var splineTube, binormal, normal, position2;
27653
27654 if ( extrudePath ) {
27655
27656 extrudePts = extrudePath.getSpacedPoints( steps );
27657
27658 extrudeByPath = true;
27659 bevelEnabled = false; // bevels not supported for path extrusion
27660
27661 // SETUP TNB variables
27662
27663 // TODO1 - have a .isClosed in spline?
27664
27665 splineTube = extrudePath.computeFrenetFrames( steps, false );
27666
27667 // console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length);
27668
27669 binormal = new Vector3();
27670 normal = new Vector3();
27671 position2 = new Vector3();
27672
27673 }
27674
27675 // Safeguards if bevels are not enabled
27676
27677 if ( ! bevelEnabled ) {
27678
27679 bevelSegments = 0;
27680 bevelThickness = 0;
27681 bevelSize = 0;
27682
27683 }
27684
27685 // Variables initialization
27686
27687 var ahole, h, hl; // looping of holes
27688
27689 var shapePoints = shape.extractPoints( curveSegments );
27690
27691 var vertices = shapePoints.shape;
27692 var holes = shapePoints.holes;
27693
27694 var reverse = ! ShapeUtils.isClockWise( vertices );
27695
27696 if ( reverse ) {
27697
27698 vertices = vertices.reverse();
27699
27700 // Maybe we should also check if holes are in the opposite direction, just to be safe ...
27701
27702 for ( h = 0, hl = holes.length; h < hl; h ++ ) {
27703
27704 ahole = holes[ h ];
27705
27706 if ( ShapeUtils.isClockWise( ahole ) ) {
27707
27708 holes[ h ] = ahole.reverse();
27709
27710 }
27711
27712 }
27713
27714 }
27715
27716
27717 var faces = ShapeUtils.triangulateShape( vertices, holes );
27718
27719 /* Vertices */
27720
27721 var contour = vertices; // vertices has all points but contour has only points of circumference
27722
27723 for ( h = 0, hl = holes.length; h < hl; h ++ ) {
27724
27725 ahole = holes[ h ];
27726
27727 vertices = vertices.concat( ahole );
27728
27729 }
27730
27731
27732 function scalePt2( pt, vec, size ) {
27733
27734 if ( ! vec ) console.error( "THREE.ExtrudeGeometry: vec does not exist" );
27735
27736 return vec.clone().multiplyScalar( size ).add( pt );
27737
27738 }
27739
27740 var b, bs, t, z,
27741 vert, vlen = vertices.length,
27742 face, flen = faces.length;
27743
27744
27745 // Find directions for point movement
27746
27747
27748 function getBevelVec( inPt, inPrev, inNext ) {
27749
27750 // computes for inPt the corresponding point inPt' on a new contour
27751 // shifted by 1 unit (length of normalized vector) to the left
27752 // if we walk along contour clockwise, this new contour is outside the old one
27753 //
27754 // inPt' is the intersection of the two lines parallel to the two
27755 // adjacent edges of inPt at a distance of 1 unit on the left side.
27756
27757 var v_trans_x, v_trans_y, shrink_by; // resulting translation vector for inPt
27758
27759 // good reading for geometry algorithms (here: line-line intersection)
27760 // http://geomalgorithms.com/a05-_intersect-1.html
27761
27762 var v_prev_x = inPt.x - inPrev.x,
27763 v_prev_y = inPt.y - inPrev.y;
27764 var v_next_x = inNext.x - inPt.x,
27765 v_next_y = inNext.y - inPt.y;
27766
27767 var v_prev_lensq = ( v_prev_x * v_prev_x + v_prev_y * v_prev_y );
27768
27769 // check for collinear edges
27770 var collinear0 = ( v_prev_x * v_next_y - v_prev_y * v_next_x );
27771
27772 if ( Math.abs( collinear0 ) > Number.EPSILON ) {
27773
27774 // not collinear
27775
27776 // length of vectors for normalizing
27777
27778 var v_prev_len = Math.sqrt( v_prev_lensq );
27779 var v_next_len = Math.sqrt( v_next_x * v_next_x + v_next_y * v_next_y );
27780
27781 // shift adjacent points by unit vectors to the left
27782
27783 var ptPrevShift_x = ( inPrev.x - v_prev_y / v_prev_len );
27784 var ptPrevShift_y = ( inPrev.y + v_prev_x / v_prev_len );
27785
27786 var ptNextShift_x = ( inNext.x - v_next_y / v_next_len );
27787 var ptNextShift_y = ( inNext.y + v_next_x / v_next_len );
27788
27789 // scaling factor for v_prev to intersection point
27790
27791 var sf = ( ( ptNextShift_x - ptPrevShift_x ) * v_next_y -
27792 ( ptNextShift_y - ptPrevShift_y ) * v_next_x ) /
27793 ( v_prev_x * v_next_y - v_prev_y * v_next_x );
27794
27795 // vector from inPt to intersection point
27796
27797 v_trans_x = ( ptPrevShift_x + v_prev_x * sf - inPt.x );
27798 v_trans_y = ( ptPrevShift_y + v_prev_y * sf - inPt.y );
27799
27800 // Don't normalize!, otherwise sharp corners become ugly
27801 // but prevent crazy spikes
27802 var v_trans_lensq = ( v_trans_x * v_trans_x + v_trans_y * v_trans_y );
27803 if ( v_trans_lensq <= 2 ) {
27804
27805 return new Vector2( v_trans_x, v_trans_y );
27806
27807 } else {
27808
27809 shrink_by = Math.sqrt( v_trans_lensq / 2 );
27810
27811 }
27812
27813 } else {
27814
27815 // handle special case of collinear edges
27816
27817 var direction_eq = false; // assumes: opposite
27818 if ( v_prev_x > Number.EPSILON ) {
27819
27820 if ( v_next_x > Number.EPSILON ) {
27821
27822 direction_eq = true;
27823
27824 }
27825
27826 } else {
27827
27828 if ( v_prev_x < - Number.EPSILON ) {
27829
27830 if ( v_next_x < - Number.EPSILON ) {
27831
27832 direction_eq = true;
27833
27834 }
27835
27836 } else {
27837
27838 if ( Math.sign( v_prev_y ) === Math.sign( v_next_y ) ) {
27839
27840 direction_eq = true;
27841
27842 }
27843
27844 }
27845
27846 }
27847
27848 if ( direction_eq ) {
27849
27850 // console.log("Warning: lines are a straight sequence");
27851 v_trans_x = - v_prev_y;
27852 v_trans_y = v_prev_x;
27853 shrink_by = Math.sqrt( v_prev_lensq );
27854
27855 } else {
27856
27857 // console.log("Warning: lines are a straight spike");
27858 v_trans_x = v_prev_x;
27859 v_trans_y = v_prev_y;
27860 shrink_by = Math.sqrt( v_prev_lensq / 2 );
27861
27862 }
27863
27864 }
27865
27866 return new Vector2( v_trans_x / shrink_by, v_trans_y / shrink_by );
27867
27868 }
27869
27870
27871 var contourMovements = [];
27872
27873 for ( var i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
27874
27875 if ( j === il ) j = 0;
27876 if ( k === il ) k = 0;
27877
27878 // (j)---(i)---(k)
27879 // console.log('i,j,k', i, j , k)
27880
27881 contourMovements[ i ] = getBevelVec( contour[ i ], contour[ j ], contour[ k ] );
27882
27883 }
27884
27885 var holesMovements = [],
27886 oneHoleMovements, verticesMovements = contourMovements.concat();
27887
27888 for ( h = 0, hl = holes.length; h < hl; h ++ ) {
27889
27890 ahole = holes[ h ];
27891
27892 oneHoleMovements = [];
27893
27894 for ( i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
27895
27896 if ( j === il ) j = 0;
27897 if ( k === il ) k = 0;
27898
27899 // (j)---(i)---(k)
27900 oneHoleMovements[ i ] = getBevelVec( ahole[ i ], ahole[ j ], ahole[ k ] );
27901
27902 }
27903
27904 holesMovements.push( oneHoleMovements );
27905 verticesMovements = verticesMovements.concat( oneHoleMovements );
27906
27907 }
27908
27909
27910 // Loop bevelSegments, 1 for the front, 1 for the back
27911
27912 for ( b = 0; b < bevelSegments; b ++ ) {
27913
27914 //for ( b = bevelSegments; b > 0; b -- ) {
27915
27916 t = b / bevelSegments;
27917 z = bevelThickness * Math.cos( t * Math.PI / 2 );
27918 bs = bevelSize * Math.sin( t * Math.PI / 2 );
27919
27920 // contract shape
27921
27922 for ( i = 0, il = contour.length; i < il; i ++ ) {
27923
27924 vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
27925
27926 v( vert.x, vert.y, - z );
27927
27928 }
27929
27930 // expand holes
27931
27932 for ( h = 0, hl = holes.length; h < hl; h ++ ) {
27933
27934 ahole = holes[ h ];
27935 oneHoleMovements = holesMovements[ h ];
27936
27937 for ( i = 0, il = ahole.length; i < il; i ++ ) {
27938
27939 vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
27940
27941 v( vert.x, vert.y, - z );
27942
27943 }
27944
27945 }
27946
27947 }
27948
27949 bs = bevelSize;
27950
27951 // Back facing vertices
27952
27953 for ( i = 0; i < vlen; i ++ ) {
27954
27955 vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
27956
27957 if ( ! extrudeByPath ) {
27958
27959 v( vert.x, vert.y, 0 );
27960
27961 } else {
27962
27963 // v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x );
27964
27965 normal.copy( splineTube.normals[ 0 ] ).multiplyScalar( vert.x );
27966 binormal.copy( splineTube.binormals[ 0 ] ).multiplyScalar( vert.y );
27967
27968 position2.copy( extrudePts[ 0 ] ).add( normal ).add( binormal );
27969
27970 v( position2.x, position2.y, position2.z );
27971
27972 }
27973
27974 }
27975
27976 // Add stepped vertices...
27977 // Including front facing vertices
27978
27979 var s;
27980
27981 for ( s = 1; s <= steps; s ++ ) {
27982
27983 for ( i = 0; i < vlen; i ++ ) {
27984
27985 vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
27986
27987 if ( ! extrudeByPath ) {
27988
27989 v( vert.x, vert.y, amount / steps * s );
27990
27991 } else {
27992
27993 // v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x );
27994
27995 normal.copy( splineTube.normals[ s ] ).multiplyScalar( vert.x );
27996 binormal.copy( splineTube.binormals[ s ] ).multiplyScalar( vert.y );
27997
27998 position2.copy( extrudePts[ s ] ).add( normal ).add( binormal );
27999
28000 v( position2.x, position2.y, position2.z );
28001
28002 }
28003
28004 }
28005
28006 }
28007
28008
28009 // Add bevel segments planes
28010
28011 //for ( b = 1; b <= bevelSegments; b ++ ) {
28012 for ( b = bevelSegments - 1; b >= 0; b -- ) {
28013
28014 t = b / bevelSegments;
28015 z = bevelThickness * Math.cos( t * Math.PI / 2 );
28016 bs = bevelSize * Math.sin( t * Math.PI / 2 );
28017
28018 // contract shape
28019
28020 for ( i = 0, il = contour.length; i < il; i ++ ) {
28021
28022 vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
28023 v( vert.x, vert.y, amount + z );
28024
28025 }
28026
28027 // expand holes
28028
28029 for ( h = 0, hl = holes.length; h < hl; h ++ ) {
28030
28031 ahole = holes[ h ];
28032 oneHoleMovements = holesMovements[ h ];
28033
28034 for ( i = 0, il = ahole.length; i < il; i ++ ) {
28035
28036 vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
28037
28038 if ( ! extrudeByPath ) {
28039
28040 v( vert.x, vert.y, amount + z );
28041
28042 } else {
28043
28044 v( vert.x, vert.y + extrudePts[ steps - 1 ].y, extrudePts[ steps - 1 ].x + z );
28045
28046 }
28047
28048 }
28049
28050 }
28051
28052 }
28053
28054 /* Faces */
28055
28056 // Top and bottom faces
28057
28058 buildLidFaces();
28059
28060 // Sides faces
28061
28062 buildSideFaces();
28063
28064
28065 ///// Internal functions
28066
28067 function buildLidFaces() {
28068
28069 var start = verticesArray.length / 3;
28070
28071 if ( bevelEnabled ) {
28072
28073 var layer = 0; // steps + 1
28074 var offset = vlen * layer;
28075
28076 // Bottom faces
28077
28078 for ( i = 0; i < flen; i ++ ) {
28079
28080 face = faces[ i ];
28081 f3( face[ 2 ] + offset, face[ 1 ] + offset, face[ 0 ] + offset );
28082
28083 }
28084
28085 layer = steps + bevelSegments * 2;
28086 offset = vlen * layer;
28087
28088 // Top faces
28089
28090 for ( i = 0; i < flen; i ++ ) {
28091
28092 face = faces[ i ];
28093 f3( face[ 0 ] + offset, face[ 1 ] + offset, face[ 2 ] + offset );
28094
28095 }
28096
28097 } else {
28098
28099 // Bottom faces
28100
28101 for ( i = 0; i < flen; i ++ ) {
28102
28103 face = faces[ i ];
28104 f3( face[ 2 ], face[ 1 ], face[ 0 ] );
28105
28106 }
28107
28108 // Top faces
28109
28110 for ( i = 0; i < flen; i ++ ) {
28111
28112 face = faces[ i ];
28113 f3( face[ 0 ] + vlen * steps, face[ 1 ] + vlen * steps, face[ 2 ] + vlen * steps );
28114
28115 }
28116
28117 }
28118
28119 scope.addGroup( start, verticesArray.length / 3 - start, 0 );
28120
28121 }
28122
28123 // Create faces for the z-sides of the shape
28124
28125 function buildSideFaces() {
28126
28127 var start = verticesArray.length / 3;
28128 var layeroffset = 0;
28129 sidewalls( contour, layeroffset );
28130 layeroffset += contour.length;
28131
28132 for ( h = 0, hl = holes.length; h < hl; h ++ ) {
28133
28134 ahole = holes[ h ];
28135 sidewalls( ahole, layeroffset );
28136
28137 //, true
28138 layeroffset += ahole.length;
28139
28140 }
28141
28142
28143 scope.addGroup( start, verticesArray.length / 3 - start, 1 );
28144
28145
28146 }
28147
28148 function sidewalls( contour, layeroffset ) {
28149
28150 var j, k;
28151 i = contour.length;
28152
28153 while ( -- i >= 0 ) {
28154
28155 j = i;
28156 k = i - 1;
28157 if ( k < 0 ) k = contour.length - 1;
28158
28159 //console.log('b', i,j, i-1, k,vertices.length);
28160
28161 var s = 0,
28162 sl = steps + bevelSegments * 2;
28163
28164 for ( s = 0; s < sl; s ++ ) {
28165
28166 var slen1 = vlen * s;
28167 var slen2 = vlen * ( s + 1 );
28168
28169 var a = layeroffset + j + slen1,
28170 b = layeroffset + k + slen1,
28171 c = layeroffset + k + slen2,
28172 d = layeroffset + j + slen2;
28173
28174 f4( a, b, c, d );
28175
28176 }
28177
28178 }
28179
28180 }
28181
28182 function v( x, y, z ) {
28183
28184 placeholder.push( x );
28185 placeholder.push( y );
28186 placeholder.push( z );
28187
28188 }
28189
28190
28191 function f3( a, b, c ) {
28192
28193 addVertex( a );
28194 addVertex( b );
28195 addVertex( c );
28196
28197 var nextIndex = verticesArray.length / 3;
28198 var uvs = uvgen.generateTopUV( scope, verticesArray, nextIndex - 3, nextIndex - 2, nextIndex - 1 );
28199
28200 addUV( uvs[ 0 ] );
28201 addUV( uvs[ 1 ] );
28202 addUV( uvs[ 2 ] );
28203
28204 }
28205
28206 function f4( a, b, c, d ) {
28207
28208 addVertex( a );
28209 addVertex( b );
28210 addVertex( d );
28211
28212 addVertex( b );
28213 addVertex( c );
28214 addVertex( d );
28215
28216
28217 var nextIndex = verticesArray.length / 3;
28218 var uvs = uvgen.generateSideWallUV( scope, verticesArray, nextIndex - 6, nextIndex - 3, nextIndex - 2, nextIndex - 1 );
28219
28220 addUV( uvs[ 0 ] );
28221 addUV( uvs[ 1 ] );
28222 addUV( uvs[ 3 ] );
28223
28224 addUV( uvs[ 1 ] );
28225 addUV( uvs[ 2 ] );
28226 addUV( uvs[ 3 ] );
28227
28228 }
28229
28230 function addVertex( index ) {
28231
28232 verticesArray.push( placeholder[ index * 3 + 0 ] );
28233 verticesArray.push( placeholder[ index * 3 + 1 ] );
28234 verticesArray.push( placeholder[ index * 3 + 2 ] );
28235
28236 }
28237
28238
28239 function addUV( vector2 ) {
28240
28241 uvArray.push( vector2.x );
28242 uvArray.push( vector2.y );
28243
28244 }
28245
28246 }
28247
28248 }
28249
28250 ExtrudeBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
28251 ExtrudeBufferGeometry.prototype.constructor = ExtrudeBufferGeometry;
28252
28253 var WorldUVGenerator = {
28254
28255 generateTopUV: function ( geometry, vertices, indexA, indexB, indexC ) {
28256
28257 var a_x = vertices[ indexA * 3 ];
28258 var a_y = vertices[ indexA * 3 + 1 ];
28259 var b_x = vertices[ indexB * 3 ];
28260 var b_y = vertices[ indexB * 3 + 1 ];
28261 var c_x = vertices[ indexC * 3 ];
28262 var c_y = vertices[ indexC * 3 + 1 ];
28263
28264 return [
28265 new Vector2( a_x, a_y ),
28266 new Vector2( b_x, b_y ),
28267 new Vector2( c_x, c_y )
28268 ];
28269
28270 },
28271
28272 generateSideWallUV: function ( geometry, vertices, indexA, indexB, indexC, indexD ) {
28273
28274 var a_x = vertices[ indexA * 3 ];
28275 var a_y = vertices[ indexA * 3 + 1 ];
28276 var a_z = vertices[ indexA * 3 + 2 ];
28277 var b_x = vertices[ indexB * 3 ];
28278 var b_y = vertices[ indexB * 3 + 1 ];
28279 var b_z = vertices[ indexB * 3 + 2 ];
28280 var c_x = vertices[ indexC * 3 ];
28281 var c_y = vertices[ indexC * 3 + 1 ];
28282 var c_z = vertices[ indexC * 3 + 2 ];
28283 var d_x = vertices[ indexD * 3 ];
28284 var d_y = vertices[ indexD * 3 + 1 ];
28285 var d_z = vertices[ indexD * 3 + 2 ];
28286
28287 if ( Math.abs( a_y - b_y ) < 0.01 ) {
28288
28289 return [
28290 new Vector2( a_x, 1 - a_z ),
28291 new Vector2( b_x, 1 - b_z ),
28292 new Vector2( c_x, 1 - c_z ),
28293 new Vector2( d_x, 1 - d_z )
28294 ];
28295
28296 } else {
28297
28298 return [
28299 new Vector2( a_y, 1 - a_z ),
28300 new Vector2( b_y, 1 - b_z ),
28301 new Vector2( c_y, 1 - c_z ),
28302 new Vector2( d_y, 1 - d_z )
28303 ];
28304
28305 }
28306
28307 }
28308 };
28309
28310 /**
28311 * @author zz85 / http://www.lab4games.net/zz85/blog
28312 * @author alteredq / http://alteredqualia.com/
28313 *
28314 * Text = 3D Text
28315 *
28316 * parameters = {
28317 * font: <THREE.Font>, // font
28318 *
28319 * size: <float>, // size of the text
28320 * height: <float>, // thickness to extrude text
28321 * curveSegments: <int>, // number of points on the curves
28322 *
28323 * bevelEnabled: <bool>, // turn on bevel
28324 * bevelThickness: <float>, // how deep into text bevel goes
28325 * bevelSize: <float> // how far from text outline is bevel
28326 * }
28327 */
28328
28329 // TextGeometry
28330
28331 function TextGeometry( text, parameters ) {
28332
28333 Geometry.call( this );
28334
28335 this.type = 'TextGeometry';
28336
28337 this.parameters = {
28338 text: text,
28339 parameters: parameters
28340 };
28341
28342 this.fromBufferGeometry( new TextBufferGeometry( text, parameters ) );
28343 this.mergeVertices();
28344
28345 }
28346
28347 TextGeometry.prototype = Object.create( Geometry.prototype );
28348 TextGeometry.prototype.constructor = TextGeometry;
28349
28350 // TextBufferGeometry
28351
28352 function TextBufferGeometry( text, parameters ) {
28353
28354 parameters = parameters || {};
28355
28356 var font = parameters.font;
28357
28358 if ( ! ( font && font.isFont ) ) {
28359
28360 console.error( 'THREE.TextGeometry: font parameter is not an instance of THREE.Font.' );
28361 return new Geometry();
28362
28363 }
28364
28365 var shapes = font.generateShapes( text, parameters.size, parameters.curveSegments );
28366
28367 // translate parameters to ExtrudeGeometry API
28368
28369 parameters.amount = parameters.height !== undefined ? parameters.height : 50;
28370
28371 // defaults
28372
28373 if ( parameters.bevelThickness === undefined ) parameters.bevelThickness = 10;
28374 if ( parameters.bevelSize === undefined ) parameters.bevelSize = 8;
28375 if ( parameters.bevelEnabled === undefined ) parameters.bevelEnabled = false;
28376
28377 ExtrudeBufferGeometry.call( this, shapes, parameters );
28378
28379 this.type = 'TextBufferGeometry';
28380
28381 }
28382
28383 TextBufferGeometry.prototype = Object.create( ExtrudeBufferGeometry.prototype );
28384 TextBufferGeometry.prototype.constructor = TextBufferGeometry;
28385
28386 /**
28387 * @author mrdoob / http://mrdoob.com/
28388 * @author benaadams / https://twitter.com/ben_a_adams
28389 * @author Mugen87 / https://github.com/Mugen87
28390 */
28391
28392 // SphereGeometry
28393
28394 function SphereGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) {
28395
28396 Geometry.call( this );
28397
28398 this.type = 'SphereGeometry';
28399
28400 this.parameters = {
28401 radius: radius,
28402 widthSegments: widthSegments,
28403 heightSegments: heightSegments,
28404 phiStart: phiStart,
28405 phiLength: phiLength,
28406 thetaStart: thetaStart,
28407 thetaLength: thetaLength
28408 };
28409
28410 this.fromBufferGeometry( new SphereBufferGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) );
28411 this.mergeVertices();
28412
28413 }
28414
28415 SphereGeometry.prototype = Object.create( Geometry.prototype );
28416 SphereGeometry.prototype.constructor = SphereGeometry;
28417
28418 // SphereBufferGeometry
28419
28420 function SphereBufferGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) {
28421
28422 BufferGeometry.call( this );
28423
28424 this.type = 'SphereBufferGeometry';
28425
28426 this.parameters = {
28427 radius: radius,
28428 widthSegments: widthSegments,
28429 heightSegments: heightSegments,
28430 phiStart: phiStart,
28431 phiLength: phiLength,
28432 thetaStart: thetaStart,
28433 thetaLength: thetaLength
28434 };
28435
28436 radius = radius || 1;
28437
28438 widthSegments = Math.max( 3, Math.floor( widthSegments ) || 8 );
28439 heightSegments = Math.max( 2, Math.floor( heightSegments ) || 6 );
28440
28441 phiStart = phiStart !== undefined ? phiStart : 0;
28442 phiLength = phiLength !== undefined ? phiLength : Math.PI * 2;
28443
28444 thetaStart = thetaStart !== undefined ? thetaStart : 0;
28445 thetaLength = thetaLength !== undefined ? thetaLength : Math.PI;
28446
28447 var thetaEnd = thetaStart + thetaLength;
28448
28449 var ix, iy;
28450
28451 var index = 0;
28452 var grid = [];
28453
28454 var vertex = new Vector3();
28455 var normal = new Vector3();
28456
28457 // buffers
28458
28459 var indices = [];
28460 var vertices = [];
28461 var normals = [];
28462 var uvs = [];
28463
28464 // generate vertices, normals and uvs
28465
28466 for ( iy = 0; iy <= heightSegments; iy ++ ) {
28467
28468 var verticesRow = [];
28469
28470 var v = iy / heightSegments;
28471
28472 for ( ix = 0; ix <= widthSegments; ix ++ ) {
28473
28474 var u = ix / widthSegments;
28475
28476 // vertex
28477
28478 vertex.x = - radius * Math.cos( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
28479 vertex.y = radius * Math.cos( thetaStart + v * thetaLength );
28480 vertex.z = radius * Math.sin( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
28481
28482 vertices.push( vertex.x, vertex.y, vertex.z );
28483
28484 // normal
28485
28486 normal.set( vertex.x, vertex.y, vertex.z ).normalize();
28487 normals.push( normal.x, normal.y, normal.z );
28488
28489 // uv
28490
28491 uvs.push( u, 1 - v );
28492
28493 verticesRow.push( index ++ );
28494
28495 }
28496
28497 grid.push( verticesRow );
28498
28499 }
28500
28501 // indices
28502
28503 for ( iy = 0; iy < heightSegments; iy ++ ) {
28504
28505 for ( ix = 0; ix < widthSegments; ix ++ ) {
28506
28507 var a = grid[ iy ][ ix + 1 ];
28508 var b = grid[ iy ][ ix ];
28509 var c = grid[ iy + 1 ][ ix ];
28510 var d = grid[ iy + 1 ][ ix + 1 ];
28511
28512 if ( iy !== 0 || thetaStart > 0 ) indices.push( a, b, d );
28513 if ( iy !== heightSegments - 1 || thetaEnd < Math.PI ) indices.push( b, c, d );
28514
28515 }
28516
28517 }
28518
28519 // build geometry
28520
28521 this.setIndex( indices );
28522 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
28523 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
28524 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
28525
28526 }
28527
28528 SphereBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
28529 SphereBufferGeometry.prototype.constructor = SphereBufferGeometry;
28530
28531 /**
28532 * @author Kaleb Murphy
28533 * @author Mugen87 / https://github.com/Mugen87
28534 */
28535
28536 // RingGeometry
28537
28538 function RingGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) {
28539
28540 Geometry.call( this );
28541
28542 this.type = 'RingGeometry';
28543
28544 this.parameters = {
28545 innerRadius: innerRadius,
28546 outerRadius: outerRadius,
28547 thetaSegments: thetaSegments,
28548 phiSegments: phiSegments,
28549 thetaStart: thetaStart,
28550 thetaLength: thetaLength
28551 };
28552
28553 this.fromBufferGeometry( new RingBufferGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) );
28554 this.mergeVertices();
28555
28556 }
28557
28558 RingGeometry.prototype = Object.create( Geometry.prototype );
28559 RingGeometry.prototype.constructor = RingGeometry;
28560
28561 // RingBufferGeometry
28562
28563 function RingBufferGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) {
28564
28565 BufferGeometry.call( this );
28566
28567 this.type = 'RingBufferGeometry';
28568
28569 this.parameters = {
28570 innerRadius: innerRadius,
28571 outerRadius: outerRadius,
28572 thetaSegments: thetaSegments,
28573 phiSegments: phiSegments,
28574 thetaStart: thetaStart,
28575 thetaLength: thetaLength
28576 };
28577
28578 innerRadius = innerRadius || 0.5;
28579 outerRadius = outerRadius || 1;
28580
28581 thetaStart = thetaStart !== undefined ? thetaStart : 0;
28582 thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2;
28583
28584 thetaSegments = thetaSegments !== undefined ? Math.max( 3, thetaSegments ) : 8;
28585 phiSegments = phiSegments !== undefined ? Math.max( 1, phiSegments ) : 1;
28586
28587 // buffers
28588
28589 var indices = [];
28590 var vertices = [];
28591 var normals = [];
28592 var uvs = [];
28593
28594 // some helper variables
28595
28596 var segment;
28597 var radius = innerRadius;
28598 var radiusStep = ( ( outerRadius - innerRadius ) / phiSegments );
28599 var vertex = new Vector3();
28600 var uv = new Vector2();
28601 var j, i;
28602
28603 // generate vertices, normals and uvs
28604
28605 for ( j = 0; j <= phiSegments; j ++ ) {
28606
28607 for ( i = 0; i <= thetaSegments; i ++ ) {
28608
28609 // values are generate from the inside of the ring to the outside
28610
28611 segment = thetaStart + i / thetaSegments * thetaLength;
28612
28613 // vertex
28614
28615 vertex.x = radius * Math.cos( segment );
28616 vertex.y = radius * Math.sin( segment );
28617
28618 vertices.push( vertex.x, vertex.y, vertex.z );
28619
28620 // normal
28621
28622 normals.push( 0, 0, 1 );
28623
28624 // uv
28625
28626 uv.x = ( vertex.x / outerRadius + 1 ) / 2;
28627 uv.y = ( vertex.y / outerRadius + 1 ) / 2;
28628
28629 uvs.push( uv.x, uv.y );
28630
28631 }
28632
28633 // increase the radius for next row of vertices
28634
28635 radius += radiusStep;
28636
28637 }
28638
28639 // indices
28640
28641 for ( j = 0; j < phiSegments; j ++ ) {
28642
28643 var thetaSegmentLevel = j * ( thetaSegments + 1 );
28644
28645 for ( i = 0; i < thetaSegments; i ++ ) {
28646
28647 segment = i + thetaSegmentLevel;
28648
28649 var a = segment;
28650 var b = segment + thetaSegments + 1;
28651 var c = segment + thetaSegments + 2;
28652 var d = segment + 1;
28653
28654 // faces
28655
28656 indices.push( a, b, d );
28657 indices.push( b, c, d );
28658
28659 }
28660
28661 }
28662
28663 // build geometry
28664
28665 this.setIndex( indices );
28666 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
28667 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
28668 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
28669
28670 }
28671
28672 RingBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
28673 RingBufferGeometry.prototype.constructor = RingBufferGeometry;
28674
28675 /**
28676 * @author astrodud / http://astrodud.isgreat.org/
28677 * @author zz85 / https://github.com/zz85
28678 * @author bhouston / http://clara.io
28679 * @author Mugen87 / https://github.com/Mugen87
28680 */
28681
28682 // LatheGeometry
28683
28684 function LatheGeometry( points, segments, phiStart, phiLength ) {
28685
28686 Geometry.call( this );
28687
28688 this.type = 'LatheGeometry';
28689
28690 this.parameters = {
28691 points: points,
28692 segments: segments,
28693 phiStart: phiStart,
28694 phiLength: phiLength
28695 };
28696
28697 this.fromBufferGeometry( new LatheBufferGeometry( points, segments, phiStart, phiLength ) );
28698 this.mergeVertices();
28699
28700 }
28701
28702 LatheGeometry.prototype = Object.create( Geometry.prototype );
28703 LatheGeometry.prototype.constructor = LatheGeometry;
28704
28705 // LatheBufferGeometry
28706
28707 function LatheBufferGeometry( points, segments, phiStart, phiLength ) {
28708
28709 BufferGeometry.call( this );
28710
28711 this.type = 'LatheBufferGeometry';
28712
28713 this.parameters = {
28714 points: points,
28715 segments: segments,
28716 phiStart: phiStart,
28717 phiLength: phiLength
28718 };
28719
28720 segments = Math.floor( segments ) || 12;
28721 phiStart = phiStart || 0;
28722 phiLength = phiLength || Math.PI * 2;
28723
28724 // clamp phiLength so it's in range of [ 0, 2PI ]
28725
28726 phiLength = _Math.clamp( phiLength, 0, Math.PI * 2 );
28727
28728
28729 // buffers
28730
28731 var indices = [];
28732 var vertices = [];
28733 var uvs = [];
28734
28735 // helper variables
28736
28737 var base;
28738 var inverseSegments = 1.0 / segments;
28739 var vertex = new Vector3();
28740 var uv = new Vector2();
28741 var i, j;
28742
28743 // generate vertices and uvs
28744
28745 for ( i = 0; i <= segments; i ++ ) {
28746
28747 var phi = phiStart + i * inverseSegments * phiLength;
28748
28749 var sin = Math.sin( phi );
28750 var cos = Math.cos( phi );
28751
28752 for ( j = 0; j <= ( points.length - 1 ); j ++ ) {
28753
28754 // vertex
28755
28756 vertex.x = points[ j ].x * sin;
28757 vertex.y = points[ j ].y;
28758 vertex.z = points[ j ].x * cos;
28759
28760 vertices.push( vertex.x, vertex.y, vertex.z );
28761
28762 // uv
28763
28764 uv.x = i / segments;
28765 uv.y = j / ( points.length - 1 );
28766
28767 uvs.push( uv.x, uv.y );
28768
28769
28770 }
28771
28772 }
28773
28774 // indices
28775
28776 for ( i = 0; i < segments; i ++ ) {
28777
28778 for ( j = 0; j < ( points.length - 1 ); j ++ ) {
28779
28780 base = j + i * points.length;
28781
28782 var a = base;
28783 var b = base + points.length;
28784 var c = base + points.length + 1;
28785 var d = base + 1;
28786
28787 // faces
28788
28789 indices.push( a, b, d );
28790 indices.push( b, c, d );
28791
28792 }
28793
28794 }
28795
28796 // build geometry
28797
28798 this.setIndex( indices );
28799 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
28800 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
28801
28802 // generate normals
28803
28804 this.computeVertexNormals();
28805
28806 // if the geometry is closed, we need to average the normals along the seam.
28807 // because the corresponding vertices are identical (but still have different UVs).
28808
28809 if ( phiLength === Math.PI * 2 ) {
28810
28811 var normals = this.attributes.normal.array;
28812 var n1 = new Vector3();
28813 var n2 = new Vector3();
28814 var n = new Vector3();
28815
28816 // this is the buffer offset for the last line of vertices
28817
28818 base = segments * points.length * 3;
28819
28820 for ( i = 0, j = 0; i < points.length; i ++, j += 3 ) {
28821
28822 // select the normal of the vertex in the first line
28823
28824 n1.x = normals[ j + 0 ];
28825 n1.y = normals[ j + 1 ];
28826 n1.z = normals[ j + 2 ];
28827
28828 // select the normal of the vertex in the last line
28829
28830 n2.x = normals[ base + j + 0 ];
28831 n2.y = normals[ base + j + 1 ];
28832 n2.z = normals[ base + j + 2 ];
28833
28834 // average normals
28835
28836 n.addVectors( n1, n2 ).normalize();
28837
28838 // assign the new values to both normals
28839
28840 normals[ j + 0 ] = normals[ base + j + 0 ] = n.x;
28841 normals[ j + 1 ] = normals[ base + j + 1 ] = n.y;
28842 normals[ j + 2 ] = normals[ base + j + 2 ] = n.z;
28843
28844 }
28845
28846 }
28847
28848 }
28849
28850 LatheBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
28851 LatheBufferGeometry.prototype.constructor = LatheBufferGeometry;
28852
28853 /**
28854 * @author jonobr1 / http://jonobr1.com
28855 * @author Mugen87 / https://github.com/Mugen87
28856 */
28857
28858 // ShapeGeometry
28859
28860 function ShapeGeometry( shapes, curveSegments ) {
28861
28862 Geometry.call( this );
28863
28864 this.type = 'ShapeGeometry';
28865
28866 if ( typeof curveSegments === 'object' ) {
28867
28868 console.warn( 'THREE.ShapeGeometry: Options parameter has been removed.' );
28869
28870 curveSegments = curveSegments.curveSegments;
28871
28872 }
28873
28874 this.parameters = {
28875 shapes: shapes,
28876 curveSegments: curveSegments
28877 };
28878
28879 this.fromBufferGeometry( new ShapeBufferGeometry( shapes, curveSegments ) );
28880 this.mergeVertices();
28881
28882 }
28883
28884 ShapeGeometry.prototype = Object.create( Geometry.prototype );
28885 ShapeGeometry.prototype.constructor = ShapeGeometry;
28886
28887 ShapeGeometry.prototype.toJSON = function () {
28888
28889 var data = Geometry.prototype.toJSON.call( this );
28890
28891 var shapes = this.parameters.shapes;
28892
28893 return toJSON( shapes, data );
28894
28895 };
28896
28897 // ShapeBufferGeometry
28898
28899 function ShapeBufferGeometry( shapes, curveSegments ) {
28900
28901 BufferGeometry.call( this );
28902
28903 this.type = 'ShapeBufferGeometry';
28904
28905 this.parameters = {
28906 shapes: shapes,
28907 curveSegments: curveSegments
28908 };
28909
28910 curveSegments = curveSegments || 12;
28911
28912 // buffers
28913
28914 var indices = [];
28915 var vertices = [];
28916 var normals = [];
28917 var uvs = [];
28918
28919 // helper variables
28920
28921 var groupStart = 0;
28922 var groupCount = 0;
28923
28924 // allow single and array values for "shapes" parameter
28925
28926 if ( Array.isArray( shapes ) === false ) {
28927
28928 addShape( shapes );
28929
28930 } else {
28931
28932 for ( var i = 0; i < shapes.length; i ++ ) {
28933
28934 addShape( shapes[ i ] );
28935
28936 this.addGroup( groupStart, groupCount, i ); // enables MultiMaterial support
28937
28938 groupStart += groupCount;
28939 groupCount = 0;
28940
28941 }
28942
28943 }
28944
28945 // build geometry
28946
28947 this.setIndex( indices );
28948 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
28949 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
28950 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
28951
28952
28953 // helper functions
28954
28955 function addShape( shape ) {
28956
28957 var i, l, shapeHole;
28958
28959 var indexOffset = vertices.length / 3;
28960 var points = shape.extractPoints( curveSegments );
28961
28962 var shapeVertices = points.shape;
28963 var shapeHoles = points.holes;
28964
28965 // check direction of vertices
28966
28967 if ( ShapeUtils.isClockWise( shapeVertices ) === false ) {
28968
28969 shapeVertices = shapeVertices.reverse();
28970
28971 // also check if holes are in the opposite direction
28972
28973 for ( i = 0, l = shapeHoles.length; i < l; i ++ ) {
28974
28975 shapeHole = shapeHoles[ i ];
28976
28977 if ( ShapeUtils.isClockWise( shapeHole ) === true ) {
28978
28979 shapeHoles[ i ] = shapeHole.reverse();
28980
28981 }
28982
28983 }
28984
28985 }
28986
28987 var faces = ShapeUtils.triangulateShape( shapeVertices, shapeHoles );
28988
28989 // join vertices of inner and outer paths to a single array
28990
28991 for ( i = 0, l = shapeHoles.length; i < l; i ++ ) {
28992
28993 shapeHole = shapeHoles[ i ];
28994 shapeVertices = shapeVertices.concat( shapeHole );
28995
28996 }
28997
28998 // vertices, normals, uvs
28999
29000 for ( i = 0, l = shapeVertices.length; i < l; i ++ ) {
29001
29002 var vertex = shapeVertices[ i ];
29003
29004 vertices.push( vertex.x, vertex.y, 0 );
29005 normals.push( 0, 0, 1 );
29006 uvs.push( vertex.x, vertex.y ); // world uvs
29007
29008 }
29009
29010 // incides
29011
29012 for ( i = 0, l = faces.length; i < l; i ++ ) {
29013
29014 var face = faces[ i ];
29015
29016 var a = face[ 0 ] + indexOffset;
29017 var b = face[ 1 ] + indexOffset;
29018 var c = face[ 2 ] + indexOffset;
29019
29020 indices.push( a, b, c );
29021 groupCount += 3;
29022
29023 }
29024
29025 }
29026
29027 }
29028
29029 ShapeBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
29030 ShapeBufferGeometry.prototype.constructor = ShapeBufferGeometry;
29031
29032 ShapeBufferGeometry.prototype.toJSON = function () {
29033
29034 var data = BufferGeometry.prototype.toJSON.call( this );
29035
29036 var shapes = this.parameters.shapes;
29037
29038 return toJSON( shapes, data );
29039
29040 };
29041
29042 //
29043
29044 function toJSON( shapes, data ) {
29045
29046 data.shapes = [];
29047
29048 if ( Array.isArray( shapes ) ) {
29049
29050 for ( var i = 0, l = shapes.length; i < l; i ++ ) {
29051
29052 var shape = shapes[ i ];
29053
29054 data.shapes.push( shape.uuid );
29055
29056 }
29057
29058 } else {
29059
29060 data.shapes.push( shapes.uuid );
29061
29062 }
29063
29064 return data;
29065
29066 }
29067
29068 /**
29069 * @author WestLangley / http://github.com/WestLangley
29070 * @author Mugen87 / https://github.com/Mugen87
29071 */
29072
29073 function EdgesGeometry( geometry, thresholdAngle ) {
29074
29075 BufferGeometry.call( this );
29076
29077 this.type = 'EdgesGeometry';
29078
29079 this.parameters = {
29080 thresholdAngle: thresholdAngle
29081 };
29082
29083 thresholdAngle = ( thresholdAngle !== undefined ) ? thresholdAngle : 1;
29084
29085 // buffer
29086
29087 var vertices = [];
29088
29089 // helper variables
29090
29091 var thresholdDot = Math.cos( _Math.DEG2RAD * thresholdAngle );
29092 var edge = [ 0, 0 ], edges = {}, edge1, edge2;
29093 var key, keys = [ 'a', 'b', 'c' ];
29094
29095 // prepare source geometry
29096
29097 var geometry2;
29098
29099 if ( geometry.isBufferGeometry ) {
29100
29101 geometry2 = new Geometry();
29102 geometry2.fromBufferGeometry( geometry );
29103
29104 } else {
29105
29106 geometry2 = geometry.clone();
29107
29108 }
29109
29110 geometry2.mergeVertices();
29111 geometry2.computeFaceNormals();
29112
29113 var sourceVertices = geometry2.vertices;
29114 var faces = geometry2.faces;
29115
29116 // now create a data structure where each entry represents an edge with its adjoining faces
29117
29118 for ( var i = 0, l = faces.length; i < l; i ++ ) {
29119
29120 var face = faces[ i ];
29121
29122 for ( var j = 0; j < 3; j ++ ) {
29123
29124 edge1 = face[ keys[ j ] ];
29125 edge2 = face[ keys[ ( j + 1 ) % 3 ] ];
29126 edge[ 0 ] = Math.min( edge1, edge2 );
29127 edge[ 1 ] = Math.max( edge1, edge2 );
29128
29129 key = edge[ 0 ] + ',' + edge[ 1 ];
29130
29131 if ( edges[ key ] === undefined ) {
29132
29133 edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ], face1: i, face2: undefined };
29134
29135 } else {
29136
29137 edges[ key ].face2 = i;
29138
29139 }
29140
29141 }
29142
29143 }
29144
29145 // generate vertices
29146
29147 for ( key in edges ) {
29148
29149 var e = edges[ key ];
29150
29151 // an edge is only rendered if the angle (in degrees) between the face normals of the adjoining faces exceeds this value. default = 1 degree.
29152
29153 if ( e.face2 === undefined || faces[ e.face1 ].normal.dot( faces[ e.face2 ].normal ) <= thresholdDot ) {
29154
29155 var vertex = sourceVertices[ e.index1 ];
29156 vertices.push( vertex.x, vertex.y, vertex.z );
29157
29158 vertex = sourceVertices[ e.index2 ];
29159 vertices.push( vertex.x, vertex.y, vertex.z );
29160
29161 }
29162
29163 }
29164
29165 // build geometry
29166
29167 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
29168
29169 }
29170
29171 EdgesGeometry.prototype = Object.create( BufferGeometry.prototype );
29172 EdgesGeometry.prototype.constructor = EdgesGeometry;
29173
29174 /**
29175 * @author mrdoob / http://mrdoob.com/
29176 * @author Mugen87 / https://github.com/Mugen87
29177 */
29178
29179 // CylinderGeometry
29180
29181 function CylinderGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {
29182
29183 Geometry.call( this );
29184
29185 this.type = 'CylinderGeometry';
29186
29187 this.parameters = {
29188 radiusTop: radiusTop,
29189 radiusBottom: radiusBottom,
29190 height: height,
29191 radialSegments: radialSegments,
29192 heightSegments: heightSegments,
29193 openEnded: openEnded,
29194 thetaStart: thetaStart,
29195 thetaLength: thetaLength
29196 };
29197
29198 this.fromBufferGeometry( new CylinderBufferGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) );
29199 this.mergeVertices();
29200
29201 }
29202
29203 CylinderGeometry.prototype = Object.create( Geometry.prototype );
29204 CylinderGeometry.prototype.constructor = CylinderGeometry;
29205
29206 // CylinderBufferGeometry
29207
29208 function CylinderBufferGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {
29209
29210 BufferGeometry.call( this );
29211
29212 this.type = 'CylinderBufferGeometry';
29213
29214 this.parameters = {
29215 radiusTop: radiusTop,
29216 radiusBottom: radiusBottom,
29217 height: height,
29218 radialSegments: radialSegments,
29219 heightSegments: heightSegments,
29220 openEnded: openEnded,
29221 thetaStart: thetaStart,
29222 thetaLength: thetaLength
29223 };
29224
29225 var scope = this;
29226
29227 radiusTop = radiusTop !== undefined ? radiusTop : 1;
29228 radiusBottom = radiusBottom !== undefined ? radiusBottom : 1;
29229 height = height || 1;
29230
29231 radialSegments = Math.floor( radialSegments ) || 8;
29232 heightSegments = Math.floor( heightSegments ) || 1;
29233
29234 openEnded = openEnded !== undefined ? openEnded : false;
29235 thetaStart = thetaStart !== undefined ? thetaStart : 0.0;
29236 thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2;
29237
29238 // buffers
29239
29240 var indices = [];
29241 var vertices = [];
29242 var normals = [];
29243 var uvs = [];
29244
29245 // helper variables
29246
29247 var index = 0;
29248 var indexArray = [];
29249 var halfHeight = height / 2;
29250 var groupStart = 0;
29251
29252 // generate geometry
29253
29254 generateTorso();
29255
29256 if ( openEnded === false ) {
29257
29258 if ( radiusTop > 0 ) generateCap( true );
29259 if ( radiusBottom > 0 ) generateCap( false );
29260
29261 }
29262
29263 // build geometry
29264
29265 this.setIndex( indices );
29266 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
29267 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
29268 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
29269
29270 function generateTorso() {
29271
29272 var x, y;
29273 var normal = new Vector3();
29274 var vertex = new Vector3();
29275
29276 var groupCount = 0;
29277
29278 // this will be used to calculate the normal
29279 var slope = ( radiusBottom - radiusTop ) / height;
29280
29281 // generate vertices, normals and uvs
29282
29283 for ( y = 0; y <= heightSegments; y ++ ) {
29284
29285 var indexRow = [];
29286
29287 var v = y / heightSegments;
29288
29289 // calculate the radius of the current row
29290
29291 var radius = v * ( radiusBottom - radiusTop ) + radiusTop;
29292
29293 for ( x = 0; x <= radialSegments; x ++ ) {
29294
29295 var u = x / radialSegments;
29296
29297 var theta = u * thetaLength + thetaStart;
29298
29299 var sinTheta = Math.sin( theta );
29300 var cosTheta = Math.cos( theta );
29301
29302 // vertex
29303
29304 vertex.x = radius * sinTheta;
29305 vertex.y = - v * height + halfHeight;
29306 vertex.z = radius * cosTheta;
29307 vertices.push( vertex.x, vertex.y, vertex.z );
29308
29309 // normal
29310
29311 normal.set( sinTheta, slope, cosTheta ).normalize();
29312 normals.push( normal.x, normal.y, normal.z );
29313
29314 // uv
29315
29316 uvs.push( u, 1 - v );
29317
29318 // save index of vertex in respective row
29319
29320 indexRow.push( index ++ );
29321
29322 }
29323
29324 // now save vertices of the row in our index array
29325
29326 indexArray.push( indexRow );
29327
29328 }
29329
29330 // generate indices
29331
29332 for ( x = 0; x < radialSegments; x ++ ) {
29333
29334 for ( y = 0; y < heightSegments; y ++ ) {
29335
29336 // we use the index array to access the correct indices
29337
29338 var a = indexArray[ y ][ x ];
29339 var b = indexArray[ y + 1 ][ x ];
29340 var c = indexArray[ y + 1 ][ x + 1 ];
29341 var d = indexArray[ y ][ x + 1 ];
29342
29343 // faces
29344
29345 indices.push( a, b, d );
29346 indices.push( b, c, d );
29347
29348 // update group counter
29349
29350 groupCount += 6;
29351
29352 }
29353
29354 }
29355
29356 // add a group to the geometry. this will ensure multi material support
29357
29358 scope.addGroup( groupStart, groupCount, 0 );
29359
29360 // calculate new start value for groups
29361
29362 groupStart += groupCount;
29363
29364 }
29365
29366 function generateCap( top ) {
29367
29368 var x, centerIndexStart, centerIndexEnd;
29369
29370 var uv = new Vector2();
29371 var vertex = new Vector3();
29372
29373 var groupCount = 0;
29374
29375 var radius = ( top === true ) ? radiusTop : radiusBottom;
29376 var sign = ( top === true ) ? 1 : - 1;
29377
29378 // save the index of the first center vertex
29379 centerIndexStart = index;
29380
29381 // first we generate the center vertex data of the cap.
29382 // because the geometry needs one set of uvs per face,
29383 // we must generate a center vertex per face/segment
29384
29385 for ( x = 1; x <= radialSegments; x ++ ) {
29386
29387 // vertex
29388
29389 vertices.push( 0, halfHeight * sign, 0 );
29390
29391 // normal
29392
29393 normals.push( 0, sign, 0 );
29394
29395 // uv
29396
29397 uvs.push( 0.5, 0.5 );
29398
29399 // increase index
29400
29401 index ++;
29402
29403 }
29404
29405 // save the index of the last center vertex
29406
29407 centerIndexEnd = index;
29408
29409 // now we generate the surrounding vertices, normals and uvs
29410
29411 for ( x = 0; x <= radialSegments; x ++ ) {
29412
29413 var u = x / radialSegments;
29414 var theta = u * thetaLength + thetaStart;
29415
29416 var cosTheta = Math.cos( theta );
29417 var sinTheta = Math.sin( theta );
29418
29419 // vertex
29420
29421 vertex.x = radius * sinTheta;
29422 vertex.y = halfHeight * sign;
29423 vertex.z = radius * cosTheta;
29424 vertices.push( vertex.x, vertex.y, vertex.z );
29425
29426 // normal
29427
29428 normals.push( 0, sign, 0 );
29429
29430 // uv
29431
29432 uv.x = ( cosTheta * 0.5 ) + 0.5;
29433 uv.y = ( sinTheta * 0.5 * sign ) + 0.5;
29434 uvs.push( uv.x, uv.y );
29435
29436 // increase index
29437
29438 index ++;
29439
29440 }
29441
29442 // generate indices
29443
29444 for ( x = 0; x < radialSegments; x ++ ) {
29445
29446 var c = centerIndexStart + x;
29447 var i = centerIndexEnd + x;
29448
29449 if ( top === true ) {
29450
29451 // face top
29452
29453 indices.push( i, i + 1, c );
29454
29455 } else {
29456
29457 // face bottom
29458
29459 indices.push( i + 1, i, c );
29460
29461 }
29462
29463 groupCount += 3;
29464
29465 }
29466
29467 // add a group to the geometry. this will ensure multi material support
29468
29469 scope.addGroup( groupStart, groupCount, top === true ? 1 : 2 );
29470
29471 // calculate new start value for groups
29472
29473 groupStart += groupCount;
29474
29475 }
29476
29477 }
29478
29479 CylinderBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
29480 CylinderBufferGeometry.prototype.constructor = CylinderBufferGeometry;
29481
29482 /**
29483 * @author abelnation / http://github.com/abelnation
29484 */
29485
29486 // ConeGeometry
29487
29488 function ConeGeometry( radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {
29489
29490 CylinderGeometry.call( this, 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength );
29491
29492 this.type = 'ConeGeometry';
29493
29494 this.parameters = {
29495 radius: radius,
29496 height: height,
29497 radialSegments: radialSegments,
29498 heightSegments: heightSegments,
29499 openEnded: openEnded,
29500 thetaStart: thetaStart,
29501 thetaLength: thetaLength
29502 };
29503
29504 }
29505
29506 ConeGeometry.prototype = Object.create( CylinderGeometry.prototype );
29507 ConeGeometry.prototype.constructor = ConeGeometry;
29508
29509 // ConeBufferGeometry
29510
29511 function ConeBufferGeometry( radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {
29512
29513 CylinderBufferGeometry.call( this, 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength );
29514
29515 this.type = 'ConeBufferGeometry';
29516
29517 this.parameters = {
29518 radius: radius,
29519 height: height,
29520 radialSegments: radialSegments,
29521 heightSegments: heightSegments,
29522 openEnded: openEnded,
29523 thetaStart: thetaStart,
29524 thetaLength: thetaLength
29525 };
29526
29527 }
29528
29529 ConeBufferGeometry.prototype = Object.create( CylinderBufferGeometry.prototype );
29530 ConeBufferGeometry.prototype.constructor = ConeBufferGeometry;
29531
29532 /**
29533 * @author benaadams / https://twitter.com/ben_a_adams
29534 * @author Mugen87 / https://github.com/Mugen87
29535 * @author hughes
29536 */
29537
29538 // CircleGeometry
29539
29540 function CircleGeometry( radius, segments, thetaStart, thetaLength ) {
29541
29542 Geometry.call( this );
29543
29544 this.type = 'CircleGeometry';
29545
29546 this.parameters = {
29547 radius: radius,
29548 segments: segments,
29549 thetaStart: thetaStart,
29550 thetaLength: thetaLength
29551 };
29552
29553 this.fromBufferGeometry( new CircleBufferGeometry( radius, segments, thetaStart, thetaLength ) );
29554 this.mergeVertices();
29555
29556 }
29557
29558 CircleGeometry.prototype = Object.create( Geometry.prototype );
29559 CircleGeometry.prototype.constructor = CircleGeometry;
29560
29561 // CircleBufferGeometry
29562
29563 function CircleBufferGeometry( radius, segments, thetaStart, thetaLength ) {
29564
29565 BufferGeometry.call( this );
29566
29567 this.type = 'CircleBufferGeometry';
29568
29569 this.parameters = {
29570 radius: radius,
29571 segments: segments,
29572 thetaStart: thetaStart,
29573 thetaLength: thetaLength
29574 };
29575
29576 radius = radius || 1;
29577 segments = segments !== undefined ? Math.max( 3, segments ) : 8;
29578
29579 thetaStart = thetaStart !== undefined ? thetaStart : 0;
29580 thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2;
29581
29582 // buffers
29583
29584 var indices = [];
29585 var vertices = [];
29586 var normals = [];
29587 var uvs = [];
29588
29589 // helper variables
29590
29591 var i, s;
29592 var vertex = new Vector3();
29593 var uv = new Vector2();
29594
29595 // center point
29596
29597 vertices.push( 0, 0, 0 );
29598 normals.push( 0, 0, 1 );
29599 uvs.push( 0.5, 0.5 );
29600
29601 for ( s = 0, i = 3; s <= segments; s ++, i += 3 ) {
29602
29603 var segment = thetaStart + s / segments * thetaLength;
29604
29605 // vertex
29606
29607 vertex.x = radius * Math.cos( segment );
29608 vertex.y = radius * Math.sin( segment );
29609
29610 vertices.push( vertex.x, vertex.y, vertex.z );
29611
29612 // normal
29613
29614 normals.push( 0, 0, 1 );
29615
29616 // uvs
29617
29618 uv.x = ( vertices[ i ] / radius + 1 ) / 2;
29619 uv.y = ( vertices[ i + 1 ] / radius + 1 ) / 2;
29620
29621 uvs.push( uv.x, uv.y );
29622
29623 }
29624
29625 // indices
29626
29627 for ( i = 1; i <= segments; i ++ ) {
29628
29629 indices.push( i, i + 1, 0 );
29630
29631 }
29632
29633 // build geometry
29634
29635 this.setIndex( indices );
29636 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
29637 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
29638 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
29639
29640 }
29641
29642 CircleBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
29643 CircleBufferGeometry.prototype.constructor = CircleBufferGeometry;
29644
29645
29646
29647 var Geometries = Object.freeze({
29648 WireframeGeometry: WireframeGeometry,
29649 ParametricGeometry: ParametricGeometry,
29650 ParametricBufferGeometry: ParametricBufferGeometry,
29651 TetrahedronGeometry: TetrahedronGeometry,
29652 TetrahedronBufferGeometry: TetrahedronBufferGeometry,
29653 OctahedronGeometry: OctahedronGeometry,
29654 OctahedronBufferGeometry: OctahedronBufferGeometry,
29655 IcosahedronGeometry: IcosahedronGeometry,
29656 IcosahedronBufferGeometry: IcosahedronBufferGeometry,
29657 DodecahedronGeometry: DodecahedronGeometry,
29658 DodecahedronBufferGeometry: DodecahedronBufferGeometry,
29659 PolyhedronGeometry: PolyhedronGeometry,
29660 PolyhedronBufferGeometry: PolyhedronBufferGeometry,
29661 TubeGeometry: TubeGeometry,
29662 TubeBufferGeometry: TubeBufferGeometry,
29663 TorusKnotGeometry: TorusKnotGeometry,
29664 TorusKnotBufferGeometry: TorusKnotBufferGeometry,
29665 TorusGeometry: TorusGeometry,
29666 TorusBufferGeometry: TorusBufferGeometry,
29667 TextGeometry: TextGeometry,
29668 TextBufferGeometry: TextBufferGeometry,
29669 SphereGeometry: SphereGeometry,
29670 SphereBufferGeometry: SphereBufferGeometry,
29671 RingGeometry: RingGeometry,
29672 RingBufferGeometry: RingBufferGeometry,
29673 PlaneGeometry: PlaneGeometry,
29674 PlaneBufferGeometry: PlaneBufferGeometry,
29675 LatheGeometry: LatheGeometry,
29676 LatheBufferGeometry: LatheBufferGeometry,
29677 ShapeGeometry: ShapeGeometry,
29678 ShapeBufferGeometry: ShapeBufferGeometry,
29679 ExtrudeGeometry: ExtrudeGeometry,
29680 ExtrudeBufferGeometry: ExtrudeBufferGeometry,
29681 EdgesGeometry: EdgesGeometry,
29682 ConeGeometry: ConeGeometry,
29683 ConeBufferGeometry: ConeBufferGeometry,
29684 CylinderGeometry: CylinderGeometry,
29685 CylinderBufferGeometry: CylinderBufferGeometry,
29686 CircleGeometry: CircleGeometry,
29687 CircleBufferGeometry: CircleBufferGeometry,
29688 BoxGeometry: BoxGeometry,
29689 BoxBufferGeometry: BoxBufferGeometry
29690 });
29691
29692 /**
29693 * @author mrdoob / http://mrdoob.com/
29694 *
29695 * parameters = {
29696 * color: <THREE.Color>
29697 * }
29698 */
29699
29700 function ShadowMaterial( parameters ) {
29701
29702 Material.call( this );
29703
29704 this.type = 'ShadowMaterial';
29705
29706 this.color = new Color( 0x000000 );
29707 this.transparent = true;
29708
29709 this.setValues( parameters );
29710
29711 }
29712
29713 ShadowMaterial.prototype = Object.create( Material.prototype );
29714 ShadowMaterial.prototype.constructor = ShadowMaterial;
29715
29716 ShadowMaterial.prototype.isShadowMaterial = true;
29717
29718 ShadowMaterial.prototype.copy = function ( source ) {
29719
29720 Material.prototype.copy.call( this, source );
29721
29722 this.color.copy( source.color );
29723
29724 return this;
29725
29726 };
29727
29728 /**
29729 * @author mrdoob / http://mrdoob.com/
29730 */
29731
29732 function RawShaderMaterial( parameters ) {
29733
29734 ShaderMaterial.call( this, parameters );
29735
29736 this.type = 'RawShaderMaterial';
29737
29738 }
29739
29740 RawShaderMaterial.prototype = Object.create( ShaderMaterial.prototype );
29741 RawShaderMaterial.prototype.constructor = RawShaderMaterial;
29742
29743 RawShaderMaterial.prototype.isRawShaderMaterial = true;
29744
29745 /**
29746 * @author WestLangley / http://github.com/WestLangley
29747 *
29748 * parameters = {
29749 * color: <hex>,
29750 * roughness: <float>,
29751 * metalness: <float>,
29752 * opacity: <float>,
29753 *
29754 * map: new THREE.Texture( <Image> ),
29755 *
29756 * lightMap: new THREE.Texture( <Image> ),
29757 * lightMapIntensity: <float>
29758 *
29759 * aoMap: new THREE.Texture( <Image> ),
29760 * aoMapIntensity: <float>
29761 *
29762 * emissive: <hex>,
29763 * emissiveIntensity: <float>
29764 * emissiveMap: new THREE.Texture( <Image> ),
29765 *
29766 * bumpMap: new THREE.Texture( <Image> ),
29767 * bumpScale: <float>,
29768 *
29769 * normalMap: new THREE.Texture( <Image> ),
29770 * normalScale: <Vector2>,
29771 *
29772 * displacementMap: new THREE.Texture( <Image> ),
29773 * displacementScale: <float>,
29774 * displacementBias: <float>,
29775 *
29776 * roughnessMap: new THREE.Texture( <Image> ),
29777 *
29778 * metalnessMap: new THREE.Texture( <Image> ),
29779 *
29780 * alphaMap: new THREE.Texture( <Image> ),
29781 *
29782 * envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
29783 * envMapIntensity: <float>
29784 *
29785 * refractionRatio: <float>,
29786 *
29787 * wireframe: <boolean>,
29788 * wireframeLinewidth: <float>,
29789 *
29790 * skinning: <bool>,
29791 * morphTargets: <bool>,
29792 * morphNormals: <bool>
29793 * }
29794 */
29795
29796 function MeshStandardMaterial( parameters ) {
29797
29798 Material.call( this );
29799
29800 this.defines = { 'STANDARD': '' };
29801
29802 this.type = 'MeshStandardMaterial';
29803
29804 this.color = new Color( 0xffffff ); // diffuse
29805 this.roughness = 0.5;
29806 this.metalness = 0.5;
29807
29808 this.map = null;
29809
29810 this.lightMap = null;
29811 this.lightMapIntensity = 1.0;
29812
29813 this.aoMap = null;
29814 this.aoMapIntensity = 1.0;
29815
29816 this.emissive = new Color( 0x000000 );
29817 this.emissiveIntensity = 1.0;
29818 this.emissiveMap = null;
29819
29820 this.bumpMap = null;
29821 this.bumpScale = 1;
29822
29823 this.normalMap = null;
29824 this.normalScale = new Vector2( 1, 1 );
29825
29826 this.displacementMap = null;
29827 this.displacementScale = 1;
29828 this.displacementBias = 0;
29829
29830 this.roughnessMap = null;
29831
29832 this.metalnessMap = null;
29833
29834 this.alphaMap = null;
29835
29836 this.envMap = null;
29837 this.envMapIntensity = 1.0;
29838
29839 this.refractionRatio = 0.98;
29840
29841 this.wireframe = false;
29842 this.wireframeLinewidth = 1;
29843 this.wireframeLinecap = 'round';
29844 this.wireframeLinejoin = 'round';
29845
29846 this.skinning = false;
29847 this.morphTargets = false;
29848 this.morphNormals = false;
29849
29850 this.setValues( parameters );
29851
29852 }
29853
29854 MeshStandardMaterial.prototype = Object.create( Material.prototype );
29855 MeshStandardMaterial.prototype.constructor = MeshStandardMaterial;
29856
29857 MeshStandardMaterial.prototype.isMeshStandardMaterial = true;
29858
29859 MeshStandardMaterial.prototype.copy = function ( source ) {
29860
29861 Material.prototype.copy.call( this, source );
29862
29863 this.defines = { 'STANDARD': '' };
29864
29865 this.color.copy( source.color );
29866 this.roughness = source.roughness;
29867 this.metalness = source.metalness;
29868
29869 this.map = source.map;
29870
29871 this.lightMap = source.lightMap;
29872 this.lightMapIntensity = source.lightMapIntensity;
29873
29874 this.aoMap = source.aoMap;
29875 this.aoMapIntensity = source.aoMapIntensity;
29876
29877 this.emissive.copy( source.emissive );
29878 this.emissiveMap = source.emissiveMap;
29879 this.emissiveIntensity = source.emissiveIntensity;
29880
29881 this.bumpMap = source.bumpMap;
29882 this.bumpScale = source.bumpScale;
29883
29884 this.normalMap = source.normalMap;
29885 this.normalScale.copy( source.normalScale );
29886
29887 this.displacementMap = source.displacementMap;
29888 this.displacementScale = source.displacementScale;
29889 this.displacementBias = source.displacementBias;
29890
29891 this.roughnessMap = source.roughnessMap;
29892
29893 this.metalnessMap = source.metalnessMap;
29894
29895 this.alphaMap = source.alphaMap;
29896
29897 this.envMap = source.envMap;
29898 this.envMapIntensity = source.envMapIntensity;
29899
29900 this.refractionRatio = source.refractionRatio;
29901
29902 this.wireframe = source.wireframe;
29903 this.wireframeLinewidth = source.wireframeLinewidth;
29904 this.wireframeLinecap = source.wireframeLinecap;
29905 this.wireframeLinejoin = source.wireframeLinejoin;
29906
29907 this.skinning = source.skinning;
29908 this.morphTargets = source.morphTargets;
29909 this.morphNormals = source.morphNormals;
29910
29911 return this;
29912
29913 };
29914
29915 /**
29916 * @author WestLangley / http://github.com/WestLangley
29917 *
29918 * parameters = {
29919 * reflectivity: <float>
29920 * }
29921 */
29922
29923 function MeshPhysicalMaterial( parameters ) {
29924
29925 MeshStandardMaterial.call( this );
29926
29927 this.defines = { 'PHYSICAL': '' };
29928
29929 this.type = 'MeshPhysicalMaterial';
29930
29931 this.reflectivity = 0.5; // maps to F0 = 0.04
29932
29933 this.clearCoat = 0.0;
29934 this.clearCoatRoughness = 0.0;
29935
29936 this.setValues( parameters );
29937
29938 }
29939
29940 MeshPhysicalMaterial.prototype = Object.create( MeshStandardMaterial.prototype );
29941 MeshPhysicalMaterial.prototype.constructor = MeshPhysicalMaterial;
29942
29943 MeshPhysicalMaterial.prototype.isMeshPhysicalMaterial = true;
29944
29945 MeshPhysicalMaterial.prototype.copy = function ( source ) {
29946
29947 MeshStandardMaterial.prototype.copy.call( this, source );
29948
29949 this.defines = { 'PHYSICAL': '' };
29950
29951 this.reflectivity = source.reflectivity;
29952
29953 this.clearCoat = source.clearCoat;
29954 this.clearCoatRoughness = source.clearCoatRoughness;
29955
29956 return this;
29957
29958 };
29959
29960 /**
29961 * @author mrdoob / http://mrdoob.com/
29962 * @author alteredq / http://alteredqualia.com/
29963 *
29964 * parameters = {
29965 * color: <hex>,
29966 * specular: <hex>,
29967 * shininess: <float>,
29968 * opacity: <float>,
29969 *
29970 * map: new THREE.Texture( <Image> ),
29971 *
29972 * lightMap: new THREE.Texture( <Image> ),
29973 * lightMapIntensity: <float>
29974 *
29975 * aoMap: new THREE.Texture( <Image> ),
29976 * aoMapIntensity: <float>
29977 *
29978 * emissive: <hex>,
29979 * emissiveIntensity: <float>
29980 * emissiveMap: new THREE.Texture( <Image> ),
29981 *
29982 * bumpMap: new THREE.Texture( <Image> ),
29983 * bumpScale: <float>,
29984 *
29985 * normalMap: new THREE.Texture( <Image> ),
29986 * normalScale: <Vector2>,
29987 *
29988 * displacementMap: new THREE.Texture( <Image> ),
29989 * displacementScale: <float>,
29990 * displacementBias: <float>,
29991 *
29992 * specularMap: new THREE.Texture( <Image> ),
29993 *
29994 * alphaMap: new THREE.Texture( <Image> ),
29995 *
29996 * envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
29997 * combine: THREE.Multiply,
29998 * reflectivity: <float>,
29999 * refractionRatio: <float>,
30000 *
30001 * wireframe: <boolean>,
30002 * wireframeLinewidth: <float>,
30003 *
30004 * skinning: <bool>,
30005 * morphTargets: <bool>,
30006 * morphNormals: <bool>
30007 * }
30008 */
30009
30010 function MeshPhongMaterial( parameters ) {
30011
30012 Material.call( this );
30013
30014 this.type = 'MeshPhongMaterial';
30015
30016 this.color = new Color( 0xffffff ); // diffuse
30017 this.specular = new Color( 0x111111 );
30018 this.shininess = 30;
30019
30020 this.map = null;
30021
30022 this.lightMap = null;
30023 this.lightMapIntensity = 1.0;
30024
30025 this.aoMap = null;
30026 this.aoMapIntensity = 1.0;
30027
30028 this.emissive = new Color( 0x000000 );
30029 this.emissiveIntensity = 1.0;
30030 this.emissiveMap = null;
30031
30032 this.bumpMap = null;
30033 this.bumpScale = 1;
30034
30035 this.normalMap = null;
30036 this.normalScale = new Vector2( 1, 1 );
30037
30038 this.displacementMap = null;
30039 this.displacementScale = 1;
30040 this.displacementBias = 0;
30041
30042 this.specularMap = null;
30043
30044 this.alphaMap = null;
30045
30046 this.envMap = null;
30047 this.combine = MultiplyOperation;
30048 this.reflectivity = 1;
30049 this.refractionRatio = 0.98;
30050
30051 this.wireframe = false;
30052 this.wireframeLinewidth = 1;
30053 this.wireframeLinecap = 'round';
30054 this.wireframeLinejoin = 'round';
30055
30056 this.skinning = false;
30057 this.morphTargets = false;
30058 this.morphNormals = false;
30059
30060 this.setValues( parameters );
30061
30062 }
30063
30064 MeshPhongMaterial.prototype = Object.create( Material.prototype );
30065 MeshPhongMaterial.prototype.constructor = MeshPhongMaterial;
30066
30067 MeshPhongMaterial.prototype.isMeshPhongMaterial = true;
30068
30069 MeshPhongMaterial.prototype.copy = function ( source ) {
30070
30071 Material.prototype.copy.call( this, source );
30072
30073 this.color.copy( source.color );
30074 this.specular.copy( source.specular );
30075 this.shininess = source.shininess;
30076
30077 this.map = source.map;
30078
30079 this.lightMap = source.lightMap;
30080 this.lightMapIntensity = source.lightMapIntensity;
30081
30082 this.aoMap = source.aoMap;
30083 this.aoMapIntensity = source.aoMapIntensity;
30084
30085 this.emissive.copy( source.emissive );
30086 this.emissiveMap = source.emissiveMap;
30087 this.emissiveIntensity = source.emissiveIntensity;
30088
30089 this.bumpMap = source.bumpMap;
30090 this.bumpScale = source.bumpScale;
30091
30092 this.normalMap = source.normalMap;
30093 this.normalScale.copy( source.normalScale );
30094
30095 this.displacementMap = source.displacementMap;
30096 this.displacementScale = source.displacementScale;
30097 this.displacementBias = source.displacementBias;
30098
30099 this.specularMap = source.specularMap;
30100
30101 this.alphaMap = source.alphaMap;
30102
30103 this.envMap = source.envMap;
30104 this.combine = source.combine;
30105 this.reflectivity = source.reflectivity;
30106 this.refractionRatio = source.refractionRatio;
30107
30108 this.wireframe = source.wireframe;
30109 this.wireframeLinewidth = source.wireframeLinewidth;
30110 this.wireframeLinecap = source.wireframeLinecap;
30111 this.wireframeLinejoin = source.wireframeLinejoin;
30112
30113 this.skinning = source.skinning;
30114 this.morphTargets = source.morphTargets;
30115 this.morphNormals = source.morphNormals;
30116
30117 return this;
30118
30119 };
30120
30121 /**
30122 * @author takahirox / http://github.com/takahirox
30123 *
30124 * parameters = {
30125 * gradientMap: new THREE.Texture( <Image> )
30126 * }
30127 */
30128
30129 function MeshToonMaterial( parameters ) {
30130
30131 MeshPhongMaterial.call( this );
30132
30133 this.defines = { 'TOON': '' };
30134
30135 this.type = 'MeshToonMaterial';
30136
30137 this.gradientMap = null;
30138
30139 this.setValues( parameters );
30140
30141 }
30142
30143 MeshToonMaterial.prototype = Object.create( MeshPhongMaterial.prototype );
30144 MeshToonMaterial.prototype.constructor = MeshToonMaterial;
30145
30146 MeshToonMaterial.prototype.isMeshToonMaterial = true;
30147
30148 MeshToonMaterial.prototype.copy = function ( source ) {
30149
30150 MeshPhongMaterial.prototype.copy.call( this, source );
30151
30152 this.gradientMap = source.gradientMap;
30153
30154 return this;
30155
30156 };
30157
30158 /**
30159 * @author mrdoob / http://mrdoob.com/
30160 * @author WestLangley / http://github.com/WestLangley
30161 *
30162 * parameters = {
30163 * opacity: <float>,
30164 *
30165 * bumpMap: new THREE.Texture( <Image> ),
30166 * bumpScale: <float>,
30167 *
30168 * normalMap: new THREE.Texture( <Image> ),
30169 * normalScale: <Vector2>,
30170 *
30171 * displacementMap: new THREE.Texture( <Image> ),
30172 * displacementScale: <float>,
30173 * displacementBias: <float>,
30174 *
30175 * wireframe: <boolean>,
30176 * wireframeLinewidth: <float>
30177 *
30178 * skinning: <bool>,
30179 * morphTargets: <bool>,
30180 * morphNormals: <bool>
30181 * }
30182 */
30183
30184 function MeshNormalMaterial( parameters ) {
30185
30186 Material.call( this );
30187
30188 this.type = 'MeshNormalMaterial';
30189
30190 this.bumpMap = null;
30191 this.bumpScale = 1;
30192
30193 this.normalMap = null;
30194 this.normalScale = new Vector2( 1, 1 );
30195
30196 this.displacementMap = null;
30197 this.displacementScale = 1;
30198 this.displacementBias = 0;
30199
30200 this.wireframe = false;
30201 this.wireframeLinewidth = 1;
30202
30203 this.fog = false;
30204 this.lights = false;
30205
30206 this.skinning = false;
30207 this.morphTargets = false;
30208 this.morphNormals = false;
30209
30210 this.setValues( parameters );
30211
30212 }
30213
30214 MeshNormalMaterial.prototype = Object.create( Material.prototype );
30215 MeshNormalMaterial.prototype.constructor = MeshNormalMaterial;
30216
30217 MeshNormalMaterial.prototype.isMeshNormalMaterial = true;
30218
30219 MeshNormalMaterial.prototype.copy = function ( source ) {
30220
30221 Material.prototype.copy.call( this, source );
30222
30223 this.bumpMap = source.bumpMap;
30224 this.bumpScale = source.bumpScale;
30225
30226 this.normalMap = source.normalMap;
30227 this.normalScale.copy( source.normalScale );
30228
30229 this.displacementMap = source.displacementMap;
30230 this.displacementScale = source.displacementScale;
30231 this.displacementBias = source.displacementBias;
30232
30233 this.wireframe = source.wireframe;
30234 this.wireframeLinewidth = source.wireframeLinewidth;
30235
30236 this.skinning = source.skinning;
30237 this.morphTargets = source.morphTargets;
30238 this.morphNormals = source.morphNormals;
30239
30240 return this;
30241
30242 };
30243
30244 /**
30245 * @author mrdoob / http://mrdoob.com/
30246 * @author alteredq / http://alteredqualia.com/
30247 *
30248 * parameters = {
30249 * color: <hex>,
30250 * opacity: <float>,
30251 *
30252 * map: new THREE.Texture( <Image> ),
30253 *
30254 * lightMap: new THREE.Texture( <Image> ),
30255 * lightMapIntensity: <float>
30256 *
30257 * aoMap: new THREE.Texture( <Image> ),
30258 * aoMapIntensity: <float>
30259 *
30260 * emissive: <hex>,
30261 * emissiveIntensity: <float>
30262 * emissiveMap: new THREE.Texture( <Image> ),
30263 *
30264 * specularMap: new THREE.Texture( <Image> ),
30265 *
30266 * alphaMap: new THREE.Texture( <Image> ),
30267 *
30268 * envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
30269 * combine: THREE.Multiply,
30270 * reflectivity: <float>,
30271 * refractionRatio: <float>,
30272 *
30273 * wireframe: <boolean>,
30274 * wireframeLinewidth: <float>,
30275 *
30276 * skinning: <bool>,
30277 * morphTargets: <bool>,
30278 * morphNormals: <bool>
30279 * }
30280 */
30281
30282 function MeshLambertMaterial( parameters ) {
30283
30284 Material.call( this );
30285
30286 this.type = 'MeshLambertMaterial';
30287
30288 this.color = new Color( 0xffffff ); // diffuse
30289
30290 this.map = null;
30291
30292 this.lightMap = null;
30293 this.lightMapIntensity = 1.0;
30294
30295 this.aoMap = null;
30296 this.aoMapIntensity = 1.0;
30297
30298 this.emissive = new Color( 0x000000 );
30299 this.emissiveIntensity = 1.0;
30300 this.emissiveMap = null;
30301
30302 this.specularMap = null;
30303
30304 this.alphaMap = null;
30305
30306 this.envMap = null;
30307 this.combine = MultiplyOperation;
30308 this.reflectivity = 1;
30309 this.refractionRatio = 0.98;
30310
30311 this.wireframe = false;
30312 this.wireframeLinewidth = 1;
30313 this.wireframeLinecap = 'round';
30314 this.wireframeLinejoin = 'round';
30315
30316 this.skinning = false;
30317 this.morphTargets = false;
30318 this.morphNormals = false;
30319
30320 this.setValues( parameters );
30321
30322 }
30323
30324 MeshLambertMaterial.prototype = Object.create( Material.prototype );
30325 MeshLambertMaterial.prototype.constructor = MeshLambertMaterial;
30326
30327 MeshLambertMaterial.prototype.isMeshLambertMaterial = true;
30328
30329 MeshLambertMaterial.prototype.copy = function ( source ) {
30330
30331 Material.prototype.copy.call( this, source );
30332
30333 this.color.copy( source.color );
30334
30335 this.map = source.map;
30336
30337 this.lightMap = source.lightMap;
30338 this.lightMapIntensity = source.lightMapIntensity;
30339
30340 this.aoMap = source.aoMap;
30341 this.aoMapIntensity = source.aoMapIntensity;
30342
30343 this.emissive.copy( source.emissive );
30344 this.emissiveMap = source.emissiveMap;
30345 this.emissiveIntensity = source.emissiveIntensity;
30346
30347 this.specularMap = source.specularMap;
30348
30349 this.alphaMap = source.alphaMap;
30350
30351 this.envMap = source.envMap;
30352 this.combine = source.combine;
30353 this.reflectivity = source.reflectivity;
30354 this.refractionRatio = source.refractionRatio;
30355
30356 this.wireframe = source.wireframe;
30357 this.wireframeLinewidth = source.wireframeLinewidth;
30358 this.wireframeLinecap = source.wireframeLinecap;
30359 this.wireframeLinejoin = source.wireframeLinejoin;
30360
30361 this.skinning = source.skinning;
30362 this.morphTargets = source.morphTargets;
30363 this.morphNormals = source.morphNormals;
30364
30365 return this;
30366
30367 };
30368
30369 /**
30370 * @author alteredq / http://alteredqualia.com/
30371 *
30372 * parameters = {
30373 * color: <hex>,
30374 * opacity: <float>,
30375 *
30376 * linewidth: <float>,
30377 *
30378 * scale: <float>,
30379 * dashSize: <float>,
30380 * gapSize: <float>
30381 * }
30382 */
30383
30384 function LineDashedMaterial( parameters ) {
30385
30386 LineBasicMaterial.call( this );
30387
30388 this.type = 'LineDashedMaterial';
30389
30390 this.scale = 1;
30391 this.dashSize = 3;
30392 this.gapSize = 1;
30393
30394 this.setValues( parameters );
30395
30396 }
30397
30398 LineDashedMaterial.prototype = Object.create( LineBasicMaterial.prototype );
30399 LineDashedMaterial.prototype.constructor = LineDashedMaterial;
30400
30401 LineDashedMaterial.prototype.isLineDashedMaterial = true;
30402
30403 LineDashedMaterial.prototype.copy = function ( source ) {
30404
30405 LineBasicMaterial.prototype.copy.call( this, source );
30406
30407 this.scale = source.scale;
30408 this.dashSize = source.dashSize;
30409 this.gapSize = source.gapSize;
30410
30411 return this;
30412
30413 };
30414
30415
30416
30417 var Materials = Object.freeze({
30418 ShadowMaterial: ShadowMaterial,
30419 SpriteMaterial: SpriteMaterial,
30420 RawShaderMaterial: RawShaderMaterial,
30421 ShaderMaterial: ShaderMaterial,
30422 PointsMaterial: PointsMaterial,
30423 MeshPhysicalMaterial: MeshPhysicalMaterial,
30424 MeshStandardMaterial: MeshStandardMaterial,
30425 MeshPhongMaterial: MeshPhongMaterial,
30426 MeshToonMaterial: MeshToonMaterial,
30427 MeshNormalMaterial: MeshNormalMaterial,
30428 MeshLambertMaterial: MeshLambertMaterial,
30429 MeshDepthMaterial: MeshDepthMaterial,
30430 MeshDistanceMaterial: MeshDistanceMaterial,
30431 MeshBasicMaterial: MeshBasicMaterial,
30432 LineDashedMaterial: LineDashedMaterial,
30433 LineBasicMaterial: LineBasicMaterial,
30434 Material: Material
30435 });
30436
30437 /**
30438 * @author mrdoob / http://mrdoob.com/
30439 */
30440
30441 var Cache = {
30442
30443 enabled: false,
30444
30445 files: {},
30446
30447 add: function ( key, file ) {
30448
30449 if ( this.enabled === false ) return;
30450
30451 // console.log( 'THREE.Cache', 'Adding key:', key );
30452
30453 this.files[ key ] = file;
30454
30455 },
30456
30457 get: function ( key ) {
30458
30459 if ( this.enabled === false ) return;
30460
30461 // console.log( 'THREE.Cache', 'Checking key:', key );
30462
30463 return this.files[ key ];
30464
30465 },
30466
30467 remove: function ( key ) {
30468
30469 delete this.files[ key ];
30470
30471 },
30472
30473 clear: function () {
30474
30475 this.files = {};
30476
30477 }
30478
30479 };
30480
30481 /**
30482 * @author mrdoob / http://mrdoob.com/
30483 */
30484
30485 function LoadingManager( onLoad, onProgress, onError ) {
30486
30487 var scope = this;
30488
30489 var isLoading = false;
30490 var itemsLoaded = 0;
30491 var itemsTotal = 0;
30492 var urlModifier = undefined;
30493
30494 this.onStart = undefined;
30495 this.onLoad = onLoad;
30496 this.onProgress = onProgress;
30497 this.onError = onError;
30498
30499 this.itemStart = function ( url ) {
30500
30501 itemsTotal ++;
30502
30503 if ( isLoading === false ) {
30504
30505 if ( scope.onStart !== undefined ) {
30506
30507 scope.onStart( url, itemsLoaded, itemsTotal );
30508
30509 }
30510
30511 }
30512
30513 isLoading = true;
30514
30515 };
30516
30517 this.itemEnd = function ( url ) {
30518
30519 itemsLoaded ++;
30520
30521 if ( scope.onProgress !== undefined ) {
30522
30523 scope.onProgress( url, itemsLoaded, itemsTotal );
30524
30525 }
30526
30527 if ( itemsLoaded === itemsTotal ) {
30528
30529 isLoading = false;
30530
30531 if ( scope.onLoad !== undefined ) {
30532
30533 scope.onLoad();
30534
30535 }
30536
30537 }
30538
30539 };
30540
30541 this.itemError = function ( url ) {
30542
30543 if ( scope.onError !== undefined ) {
30544
30545 scope.onError( url );
30546
30547 }
30548
30549 };
30550
30551 this.resolveURL = function ( url ) {
30552
30553 if ( urlModifier ) {
30554
30555 return urlModifier( url );
30556
30557 }
30558
30559 return url;
30560
30561 };
30562
30563 this.setURLModifier = function ( transform ) {
30564
30565 urlModifier = transform;
30566 return this;
30567
30568 };
30569
30570 }
30571
30572 var DefaultLoadingManager = new LoadingManager();
30573
30574 /**
30575 * @author mrdoob / http://mrdoob.com/
30576 */
30577
30578 var loading = {};
30579
30580 function FileLoader( manager ) {
30581
30582 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
30583
30584 }
30585
30586 Object.assign( FileLoader.prototype, {
30587
30588 load: function ( url, onLoad, onProgress, onError ) {
30589
30590 if ( url === undefined ) url = '';
30591
30592 if ( this.path !== undefined ) url = this.path + url;
30593
30594 url = this.manager.resolveURL( url );
30595
30596 var scope = this;
30597
30598 var cached = Cache.get( url );
30599
30600 if ( cached !== undefined ) {
30601
30602 scope.manager.itemStart( url );
30603
30604 setTimeout( function () {
30605
30606 if ( onLoad ) onLoad( cached );
30607
30608 scope.manager.itemEnd( url );
30609
30610 }, 0 );
30611
30612 return cached;
30613
30614 }
30615
30616 // Check if request is duplicate
30617
30618 if ( loading[ url ] !== undefined ) {
30619
30620 loading[ url ].push( {
30621
30622 onLoad: onLoad,
30623 onProgress: onProgress,
30624 onError: onError
30625
30626 } );
30627
30628 return;
30629
30630 }
30631
30632 // Check for data: URI
30633 var dataUriRegex = /^data:(.*?)(;base64)?,(.*)$/;
30634 var dataUriRegexResult = url.match( dataUriRegex );
30635
30636 // Safari can not handle Data URIs through XMLHttpRequest so process manually
30637 if ( dataUriRegexResult ) {
30638
30639 var mimeType = dataUriRegexResult[ 1 ];
30640 var isBase64 = !! dataUriRegexResult[ 2 ];
30641 var data = dataUriRegexResult[ 3 ];
30642
30643 data = window.decodeURIComponent( data );
30644
30645 if ( isBase64 ) data = window.atob( data );
30646
30647 try {
30648
30649 var response;
30650 var responseType = ( this.responseType || '' ).toLowerCase();
30651
30652 switch ( responseType ) {
30653
30654 case 'arraybuffer':
30655 case 'blob':
30656
30657 var view = new Uint8Array( data.length );
30658
30659 for ( var i = 0; i < data.length; i ++ ) {
30660
30661 view[ i ] = data.charCodeAt( i );
30662
30663 }
30664
30665 if ( responseType === 'blob' ) {
30666
30667 response = new Blob( [ view.buffer ], { type: mimeType } );
30668
30669 } else {
30670
30671 response = view.buffer;
30672
30673 }
30674
30675 break;
30676
30677 case 'document':
30678
30679 var parser = new DOMParser();
30680 response = parser.parseFromString( data, mimeType );
30681
30682 break;
30683
30684 case 'json':
30685
30686 response = JSON.parse( data );
30687
30688 break;
30689
30690 default: // 'text' or other
30691
30692 response = data;
30693
30694 break;
30695
30696 }
30697
30698 // Wait for next browser tick like standard XMLHttpRequest event dispatching does
30699 window.setTimeout( function () {
30700
30701 if ( onLoad ) onLoad( response );
30702
30703 scope.manager.itemEnd( url );
30704
30705 }, 0 );
30706
30707 } catch ( error ) {
30708
30709 // Wait for next browser tick like standard XMLHttpRequest event dispatching does
30710 window.setTimeout( function () {
30711
30712 if ( onError ) onError( error );
30713
30714 scope.manager.itemEnd( url );
30715 scope.manager.itemError( url );
30716
30717 }, 0 );
30718
30719 }
30720
30721 } else {
30722
30723 // Initialise array for duplicate requests
30724
30725 loading[ url ] = [];
30726
30727 loading[ url ].push( {
30728
30729 onLoad: onLoad,
30730 onProgress: onProgress,
30731 onError: onError
30732
30733 } );
30734
30735 var request = new XMLHttpRequest();
30736
30737 request.open( 'GET', url, true );
30738
30739 request.addEventListener( 'load', function ( event ) {
30740
30741 var response = this.response;
30742
30743 Cache.add( url, response );
30744
30745 var callbacks = loading[ url ];
30746
30747 delete loading[ url ];
30748
30749 if ( this.status === 200 ) {
30750
30751 for ( var i = 0, il = callbacks.length; i < il; i ++ ) {
30752
30753 var callback = callbacks[ i ];
30754 if ( callback.onLoad ) callback.onLoad( response );
30755
30756 }
30757
30758 scope.manager.itemEnd( url );
30759
30760 } else if ( this.status === 0 ) {
30761
30762 // Some browsers return HTTP Status 0 when using non-http protocol
30763 // e.g. 'file://' or 'data://'. Handle as success.
30764
30765 console.warn( 'THREE.FileLoader: HTTP Status 0 received.' );
30766
30767 for ( var i = 0, il = callbacks.length; i < il; i ++ ) {
30768
30769 var callback = callbacks[ i ];
30770 if ( callback.onLoad ) callback.onLoad( response );
30771
30772 }
30773
30774 scope.manager.itemEnd( url );
30775
30776 } else {
30777
30778 for ( var i = 0, il = callbacks.length; i < il; i ++ ) {
30779
30780 var callback = callbacks[ i ];
30781 if ( callback.onError ) callback.onError( event );
30782
30783 }
30784
30785 scope.manager.itemEnd( url );
30786 scope.manager.itemError( url );
30787
30788 }
30789
30790 }, false );
30791
30792 request.addEventListener( 'progress', function ( event ) {
30793
30794 var callbacks = loading[ url ];
30795
30796 for ( var i = 0, il = callbacks.length; i < il; i ++ ) {
30797
30798 var callback = callbacks[ i ];
30799 if ( callback.onProgress ) callback.onProgress( event );
30800
30801 }
30802
30803 }, false );
30804
30805 request.addEventListener( 'error', function ( event ) {
30806
30807 var callbacks = loading[ url ];
30808
30809 delete loading[ url ];
30810
30811 for ( var i = 0, il = callbacks.length; i < il; i ++ ) {
30812
30813 var callback = callbacks[ i ];
30814 if ( callback.onError ) callback.onError( event );
30815
30816 }
30817
30818 scope.manager.itemEnd( url );
30819 scope.manager.itemError( url );
30820
30821 }, false );
30822
30823 if ( this.responseType !== undefined ) request.responseType = this.responseType;
30824 if ( this.withCredentials !== undefined ) request.withCredentials = this.withCredentials;
30825
30826 if ( request.overrideMimeType ) request.overrideMimeType( this.mimeType !== undefined ? this.mimeType : 'text/plain' );
30827
30828 for ( var header in this.requestHeader ) {
30829
30830 request.setRequestHeader( header, this.requestHeader[ header ] );
30831
30832 }
30833
30834 request.send( null );
30835
30836 }
30837
30838 scope.manager.itemStart( url );
30839
30840 return request;
30841
30842 },
30843
30844 setPath: function ( value ) {
30845
30846 this.path = value;
30847 return this;
30848
30849 },
30850
30851 setResponseType: function ( value ) {
30852
30853 this.responseType = value;
30854 return this;
30855
30856 },
30857
30858 setWithCredentials: function ( value ) {
30859
30860 this.withCredentials = value;
30861 return this;
30862
30863 },
30864
30865 setMimeType: function ( value ) {
30866
30867 this.mimeType = value;
30868 return this;
30869
30870 },
30871
30872 setRequestHeader: function ( value ) {
30873
30874 this.requestHeader = value;
30875 return this;
30876
30877 }
30878
30879 } );
30880
30881 /**
30882 * @author mrdoob / http://mrdoob.com/
30883 *
30884 * Abstract Base class to block based textures loader (dds, pvr, ...)
30885 */
30886
30887 function CompressedTextureLoader( manager ) {
30888
30889 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
30890
30891 // override in sub classes
30892 this._parser = null;
30893
30894 }
30895
30896 Object.assign( CompressedTextureLoader.prototype, {
30897
30898 load: function ( url, onLoad, onProgress, onError ) {
30899
30900 var scope = this;
30901
30902 var images = [];
30903
30904 var texture = new CompressedTexture();
30905 texture.image = images;
30906
30907 var loader = new FileLoader( this.manager );
30908 loader.setPath( this.path );
30909 loader.setResponseType( 'arraybuffer' );
30910
30911 function loadTexture( i ) {
30912
30913 loader.load( url[ i ], function ( buffer ) {
30914
30915 var texDatas = scope._parser( buffer, true );
30916
30917 images[ i ] = {
30918 width: texDatas.width,
30919 height: texDatas.height,
30920 format: texDatas.format,
30921 mipmaps: texDatas.mipmaps
30922 };
30923
30924 loaded += 1;
30925
30926 if ( loaded === 6 ) {
30927
30928 if ( texDatas.mipmapCount === 1 )
30929 texture.minFilter = LinearFilter;
30930
30931 texture.format = texDatas.format;
30932 texture.needsUpdate = true;
30933
30934 if ( onLoad ) onLoad( texture );
30935
30936 }
30937
30938 }, onProgress, onError );
30939
30940 }
30941
30942 if ( Array.isArray( url ) ) {
30943
30944 var loaded = 0;
30945
30946 for ( var i = 0, il = url.length; i < il; ++ i ) {
30947
30948 loadTexture( i );
30949
30950 }
30951
30952 } else {
30953
30954 // compressed cubemap texture stored in a single DDS file
30955
30956 loader.load( url, function ( buffer ) {
30957
30958 var texDatas = scope._parser( buffer, true );
30959
30960 if ( texDatas.isCubemap ) {
30961
30962 var faces = texDatas.mipmaps.length / texDatas.mipmapCount;
30963
30964 for ( var f = 0; f < faces; f ++ ) {
30965
30966 images[ f ] = { mipmaps: [] };
30967
30968 for ( var i = 0; i < texDatas.mipmapCount; i ++ ) {
30969
30970 images[ f ].mipmaps.push( texDatas.mipmaps[ f * texDatas.mipmapCount + i ] );
30971 images[ f ].format = texDatas.format;
30972 images[ f ].width = texDatas.width;
30973 images[ f ].height = texDatas.height;
30974
30975 }
30976
30977 }
30978
30979 } else {
30980
30981 texture.image.width = texDatas.width;
30982 texture.image.height = texDatas.height;
30983 texture.mipmaps = texDatas.mipmaps;
30984
30985 }
30986
30987 if ( texDatas.mipmapCount === 1 ) {
30988
30989 texture.minFilter = LinearFilter;
30990
30991 }
30992
30993 texture.format = texDatas.format;
30994 texture.needsUpdate = true;
30995
30996 if ( onLoad ) onLoad( texture );
30997
30998 }, onProgress, onError );
30999
31000 }
31001
31002 return texture;
31003
31004 },
31005
31006 setPath: function ( value ) {
31007
31008 this.path = value;
31009 return this;
31010
31011 }
31012
31013 } );
31014
31015 /**
31016 * @author Nikos M. / https://github.com/foo123/
31017 *
31018 * Abstract Base class to load generic binary textures formats (rgbe, hdr, ...)
31019 */
31020
31021 function DataTextureLoader( manager ) {
31022
31023 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
31024
31025 // override in sub classes
31026 this._parser = null;
31027
31028 }
31029
31030 Object.assign( DataTextureLoader.prototype, {
31031
31032 load: function ( url, onLoad, onProgress, onError ) {
31033
31034 var scope = this;
31035
31036 var texture = new DataTexture();
31037
31038 var loader = new FileLoader( this.manager );
31039 loader.setResponseType( 'arraybuffer' );
31040
31041 loader.load( url, function ( buffer ) {
31042
31043 var texData = scope._parser( buffer );
31044
31045 if ( ! texData ) return;
31046
31047 if ( undefined !== texData.image ) {
31048
31049 texture.image = texData.image;
31050
31051 } else if ( undefined !== texData.data ) {
31052
31053 texture.image.width = texData.width;
31054 texture.image.height = texData.height;
31055 texture.image.data = texData.data;
31056
31057 }
31058
31059 texture.wrapS = undefined !== texData.wrapS ? texData.wrapS : ClampToEdgeWrapping;
31060 texture.wrapT = undefined !== texData.wrapT ? texData.wrapT : ClampToEdgeWrapping;
31061
31062 texture.magFilter = undefined !== texData.magFilter ? texData.magFilter : LinearFilter;
31063 texture.minFilter = undefined !== texData.minFilter ? texData.minFilter : LinearMipMapLinearFilter;
31064
31065 texture.anisotropy = undefined !== texData.anisotropy ? texData.anisotropy : 1;
31066
31067 if ( undefined !== texData.format ) {
31068
31069 texture.format = texData.format;
31070
31071 }
31072 if ( undefined !== texData.type ) {
31073
31074 texture.type = texData.type;
31075
31076 }
31077
31078 if ( undefined !== texData.mipmaps ) {
31079
31080 texture.mipmaps = texData.mipmaps;
31081
31082 }
31083
31084 if ( 1 === texData.mipmapCount ) {
31085
31086 texture.minFilter = LinearFilter;
31087
31088 }
31089
31090 texture.needsUpdate = true;
31091
31092 if ( onLoad ) onLoad( texture, texData );
31093
31094 }, onProgress, onError );
31095
31096
31097 return texture;
31098
31099 }
31100
31101 } );
31102
31103 /**
31104 * @author mrdoob / http://mrdoob.com/
31105 */
31106
31107 function ImageLoader( manager ) {
31108
31109 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
31110
31111 }
31112
31113 Object.assign( ImageLoader.prototype, {
31114
31115 crossOrigin: 'Anonymous',
31116
31117 load: function ( url, onLoad, onProgress, onError ) {
31118
31119 if ( url === undefined ) url = '';
31120
31121 if ( this.path !== undefined ) url = this.path + url;
31122
31123 url = this.manager.resolveURL( url );
31124
31125 var scope = this;
31126
31127 var cached = Cache.get( url );
31128
31129 if ( cached !== undefined ) {
31130
31131 scope.manager.itemStart( url );
31132
31133 setTimeout( function () {
31134
31135 if ( onLoad ) onLoad( cached );
31136
31137 scope.manager.itemEnd( url );
31138
31139 }, 0 );
31140
31141 return cached;
31142
31143 }
31144
31145 var image = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'img' );
31146
31147 image.addEventListener( 'load', function () {
31148
31149 Cache.add( url, this );
31150
31151 if ( onLoad ) onLoad( this );
31152
31153 scope.manager.itemEnd( url );
31154
31155 }, false );
31156
31157 /*
31158 image.addEventListener( 'progress', function ( event ) {
31159
31160 if ( onProgress ) onProgress( event );
31161
31162 }, false );
31163 */
31164
31165 image.addEventListener( 'error', function ( event ) {
31166
31167 if ( onError ) onError( event );
31168
31169 scope.manager.itemEnd( url );
31170 scope.manager.itemError( url );
31171
31172 }, false );
31173
31174 if ( url.substr( 0, 5 ) !== 'data:' ) {
31175
31176 if ( this.crossOrigin !== undefined ) image.crossOrigin = this.crossOrigin;
31177
31178 }
31179
31180 scope.manager.itemStart( url );
31181
31182 image.src = url;
31183
31184 return image;
31185
31186 },
31187
31188 setCrossOrigin: function ( value ) {
31189
31190 this.crossOrigin = value;
31191 return this;
31192
31193 },
31194
31195 setPath: function ( value ) {
31196
31197 this.path = value;
31198 return this;
31199
31200 }
31201
31202 } );
31203
31204 /**
31205 * @author mrdoob / http://mrdoob.com/
31206 */
31207
31208 function CubeTextureLoader( manager ) {
31209
31210 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
31211
31212 }
31213
31214 Object.assign( CubeTextureLoader.prototype, {
31215
31216 crossOrigin: 'Anonymous',
31217
31218 load: function ( urls, onLoad, onProgress, onError ) {
31219
31220 var texture = new CubeTexture();
31221
31222 var loader = new ImageLoader( this.manager );
31223 loader.setCrossOrigin( this.crossOrigin );
31224 loader.setPath( this.path );
31225
31226 var loaded = 0;
31227
31228 function loadTexture( i ) {
31229
31230 loader.load( urls[ i ], function ( image ) {
31231
31232 texture.images[ i ] = image;
31233
31234 loaded ++;
31235
31236 if ( loaded === 6 ) {
31237
31238 texture.needsUpdate = true;
31239
31240 if ( onLoad ) onLoad( texture );
31241
31242 }
31243
31244 }, undefined, onError );
31245
31246 }
31247
31248 for ( var i = 0; i < urls.length; ++ i ) {
31249
31250 loadTexture( i );
31251
31252 }
31253
31254 return texture;
31255
31256 },
31257
31258 setCrossOrigin: function ( value ) {
31259
31260 this.crossOrigin = value;
31261 return this;
31262
31263 },
31264
31265 setPath: function ( value ) {
31266
31267 this.path = value;
31268 return this;
31269
31270 }
31271
31272 } );
31273
31274 /**
31275 * @author mrdoob / http://mrdoob.com/
31276 */
31277
31278 function TextureLoader( manager ) {
31279
31280 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
31281
31282 }
31283
31284 Object.assign( TextureLoader.prototype, {
31285
31286 crossOrigin: 'Anonymous',
31287
31288 load: function ( url, onLoad, onProgress, onError ) {
31289
31290 var texture = new Texture();
31291
31292 var loader = new ImageLoader( this.manager );
31293 loader.setCrossOrigin( this.crossOrigin );
31294 loader.setPath( this.path );
31295
31296 loader.load( url, function ( image ) {
31297
31298 texture.image = image;
31299
31300 // JPEGs can't have an alpha channel, so memory can be saved by storing them as RGB.
31301 var isJPEG = url.search( /\.(jpg|jpeg)$/ ) > 0 || url.search( /^data\:image\/jpeg/ ) === 0;
31302
31303 texture.format = isJPEG ? RGBFormat : RGBAFormat;
31304 texture.needsUpdate = true;
31305
31306 if ( onLoad !== undefined ) {
31307
31308 onLoad( texture );
31309
31310 }
31311
31312 }, onProgress, onError );
31313
31314 return texture;
31315
31316 },
31317
31318 setCrossOrigin: function ( value ) {
31319
31320 this.crossOrigin = value;
31321 return this;
31322
31323 },
31324
31325 setPath: function ( value ) {
31326
31327 this.path = value;
31328 return this;
31329
31330 }
31331
31332 } );
31333
31334 /**
31335 * @author zz85 / http://www.lab4games.net/zz85/blog
31336 * Extensible curve object
31337 *
31338 * Some common of curve methods:
31339 * .getPoint( t, optionalTarget ), .getTangent( t )
31340 * .getPointAt( u, optionalTarget ), .getTangentAt( u )
31341 * .getPoints(), .getSpacedPoints()
31342 * .getLength()
31343 * .updateArcLengths()
31344 *
31345 * This following curves inherit from THREE.Curve:
31346 *
31347 * -- 2D curves --
31348 * THREE.ArcCurve
31349 * THREE.CubicBezierCurve
31350 * THREE.EllipseCurve
31351 * THREE.LineCurve
31352 * THREE.QuadraticBezierCurve
31353 * THREE.SplineCurve
31354 *
31355 * -- 3D curves --
31356 * THREE.CatmullRomCurve3
31357 * THREE.CubicBezierCurve3
31358 * THREE.LineCurve3
31359 * THREE.QuadraticBezierCurve3
31360 *
31361 * A series of curves can be represented as a THREE.CurvePath.
31362 *
31363 **/
31364
31365 /**************************************************************
31366 * Abstract Curve base class
31367 **************************************************************/
31368
31369 function Curve() {
31370
31371 this.type = 'Curve';
31372
31373 this.arcLengthDivisions = 200;
31374
31375 }
31376
31377 Object.assign( Curve.prototype, {
31378
31379 // Virtual base class method to overwrite and implement in subclasses
31380 // - t [0 .. 1]
31381
31382 getPoint: function ( /* t, optionalTarget */ ) {
31383
31384 console.warn( 'THREE.Curve: .getPoint() not implemented.' );
31385 return null;
31386
31387 },
31388
31389 // Get point at relative position in curve according to arc length
31390 // - u [0 .. 1]
31391
31392 getPointAt: function ( u, optionalTarget ) {
31393
31394 var t = this.getUtoTmapping( u );
31395 return this.getPoint( t, optionalTarget );
31396
31397 },
31398
31399 // Get sequence of points using getPoint( t )
31400
31401 getPoints: function ( divisions ) {
31402
31403 if ( divisions === undefined ) divisions = 5;
31404
31405 var points = [];
31406
31407 for ( var d = 0; d <= divisions; d ++ ) {
31408
31409 points.push( this.getPoint( d / divisions ) );
31410
31411 }
31412
31413 return points;
31414
31415 },
31416
31417 // Get sequence of points using getPointAt( u )
31418
31419 getSpacedPoints: function ( divisions ) {
31420
31421 if ( divisions === undefined ) divisions = 5;
31422
31423 var points = [];
31424
31425 for ( var d = 0; d <= divisions; d ++ ) {
31426
31427 points.push( this.getPointAt( d / divisions ) );
31428
31429 }
31430
31431 return points;
31432
31433 },
31434
31435 // Get total curve arc length
31436
31437 getLength: function () {
31438
31439 var lengths = this.getLengths();
31440 return lengths[ lengths.length - 1 ];
31441
31442 },
31443
31444 // Get list of cumulative segment lengths
31445
31446 getLengths: function ( divisions ) {
31447
31448 if ( divisions === undefined ) divisions = this.arcLengthDivisions;
31449
31450 if ( this.cacheArcLengths &&
31451 ( this.cacheArcLengths.length === divisions + 1 ) &&
31452 ! this.needsUpdate ) {
31453
31454 return this.cacheArcLengths;
31455
31456 }
31457
31458 this.needsUpdate = false;
31459
31460 var cache = [];
31461 var current, last = this.getPoint( 0 );
31462 var p, sum = 0;
31463
31464 cache.push( 0 );
31465
31466 for ( p = 1; p <= divisions; p ++ ) {
31467
31468 current = this.getPoint( p / divisions );
31469 sum += current.distanceTo( last );
31470 cache.push( sum );
31471 last = current;
31472
31473 }
31474
31475 this.cacheArcLengths = cache;
31476
31477 return cache; // { sums: cache, sum: sum }; Sum is in the last element.
31478
31479 },
31480
31481 updateArcLengths: function () {
31482
31483 this.needsUpdate = true;
31484 this.getLengths();
31485
31486 },
31487
31488 // Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equidistant
31489
31490 getUtoTmapping: function ( u, distance ) {
31491
31492 var arcLengths = this.getLengths();
31493
31494 var i = 0, il = arcLengths.length;
31495
31496 var targetArcLength; // The targeted u distance value to get
31497
31498 if ( distance ) {
31499
31500 targetArcLength = distance;
31501
31502 } else {
31503
31504 targetArcLength = u * arcLengths[ il - 1 ];
31505
31506 }
31507
31508 // binary search for the index with largest value smaller than target u distance
31509
31510 var low = 0, high = il - 1, comparison;
31511
31512 while ( low <= high ) {
31513
31514 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
31515
31516 comparison = arcLengths[ i ] - targetArcLength;
31517
31518 if ( comparison < 0 ) {
31519
31520 low = i + 1;
31521
31522 } else if ( comparison > 0 ) {
31523
31524 high = i - 1;
31525
31526 } else {
31527
31528 high = i;
31529 break;
31530
31531 // DONE
31532
31533 }
31534
31535 }
31536
31537 i = high;
31538
31539 if ( arcLengths[ i ] === targetArcLength ) {
31540
31541 return i / ( il - 1 );
31542
31543 }
31544
31545 // we could get finer grain at lengths, or use simple interpolation between two points
31546
31547 var lengthBefore = arcLengths[ i ];
31548 var lengthAfter = arcLengths[ i + 1 ];
31549
31550 var segmentLength = lengthAfter - lengthBefore;
31551
31552 // determine where we are between the 'before' and 'after' points
31553
31554 var segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength;
31555
31556 // add that fractional amount to t
31557
31558 var t = ( i + segmentFraction ) / ( il - 1 );
31559
31560 return t;
31561
31562 },
31563
31564 // Returns a unit vector tangent at t
31565 // In case any sub curve does not implement its tangent derivation,
31566 // 2 points a small delta apart will be used to find its gradient
31567 // which seems to give a reasonable approximation
31568
31569 getTangent: function ( t ) {
31570
31571 var delta = 0.0001;
31572 var t1 = t - delta;
31573 var t2 = t + delta;
31574
31575 // Capping in case of danger
31576
31577 if ( t1 < 0 ) t1 = 0;
31578 if ( t2 > 1 ) t2 = 1;
31579
31580 var pt1 = this.getPoint( t1 );
31581 var pt2 = this.getPoint( t2 );
31582
31583 var vec = pt2.clone().sub( pt1 );
31584 return vec.normalize();
31585
31586 },
31587
31588 getTangentAt: function ( u ) {
31589
31590 var t = this.getUtoTmapping( u );
31591 return this.getTangent( t );
31592
31593 },
31594
31595 computeFrenetFrames: function ( segments, closed ) {
31596
31597 // see http://www.cs.indiana.edu/pub/techreports/TR425.pdf
31598
31599 var normal = new Vector3();
31600
31601 var tangents = [];
31602 var normals = [];
31603 var binormals = [];
31604
31605 var vec = new Vector3();
31606 var mat = new Matrix4();
31607
31608 var i, u, theta;
31609
31610 // compute the tangent vectors for each segment on the curve
31611
31612 for ( i = 0; i <= segments; i ++ ) {
31613
31614 u = i / segments;
31615
31616 tangents[ i ] = this.getTangentAt( u );
31617 tangents[ i ].normalize();
31618
31619 }
31620
31621 // select an initial normal vector perpendicular to the first tangent vector,
31622 // and in the direction of the minimum tangent xyz component
31623
31624 normals[ 0 ] = new Vector3();
31625 binormals[ 0 ] = new Vector3();
31626 var min = Number.MAX_VALUE;
31627 var tx = Math.abs( tangents[ 0 ].x );
31628 var ty = Math.abs( tangents[ 0 ].y );
31629 var tz = Math.abs( tangents[ 0 ].z );
31630
31631 if ( tx <= min ) {
31632
31633 min = tx;
31634 normal.set( 1, 0, 0 );
31635
31636 }
31637
31638 if ( ty <= min ) {
31639
31640 min = ty;
31641 normal.set( 0, 1, 0 );
31642
31643 }
31644
31645 if ( tz <= min ) {
31646
31647 normal.set( 0, 0, 1 );
31648
31649 }
31650
31651 vec.crossVectors( tangents[ 0 ], normal ).normalize();
31652
31653 normals[ 0 ].crossVectors( tangents[ 0 ], vec );
31654 binormals[ 0 ].crossVectors( tangents[ 0 ], normals[ 0 ] );
31655
31656
31657 // compute the slowly-varying normal and binormal vectors for each segment on the curve
31658
31659 for ( i = 1; i <= segments; i ++ ) {
31660
31661 normals[ i ] = normals[ i - 1 ].clone();
31662
31663 binormals[ i ] = binormals[ i - 1 ].clone();
31664
31665 vec.crossVectors( tangents[ i - 1 ], tangents[ i ] );
31666
31667 if ( vec.length() > Number.EPSILON ) {
31668
31669 vec.normalize();
31670
31671 theta = Math.acos( _Math.clamp( tangents[ i - 1 ].dot( tangents[ i ] ), - 1, 1 ) ); // clamp for floating pt errors
31672
31673 normals[ i ].applyMatrix4( mat.makeRotationAxis( vec, theta ) );
31674
31675 }
31676
31677 binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
31678
31679 }
31680
31681 // if the curve is closed, postprocess the vectors so the first and last normal vectors are the same
31682
31683 if ( closed === true ) {
31684
31685 theta = Math.acos( _Math.clamp( normals[ 0 ].dot( normals[ segments ] ), - 1, 1 ) );
31686 theta /= segments;
31687
31688 if ( tangents[ 0 ].dot( vec.crossVectors( normals[ 0 ], normals[ segments ] ) ) > 0 ) {
31689
31690 theta = - theta;
31691
31692 }
31693
31694 for ( i = 1; i <= segments; i ++ ) {
31695
31696 // twist a little...
31697 normals[ i ].applyMatrix4( mat.makeRotationAxis( tangents[ i ], theta * i ) );
31698 binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
31699
31700 }
31701
31702 }
31703
31704 return {
31705 tangents: tangents,
31706 normals: normals,
31707 binormals: binormals
31708 };
31709
31710 },
31711
31712 clone: function () {
31713
31714 return new this.constructor().copy( this );
31715
31716 },
31717
31718 copy: function ( source ) {
31719
31720 this.arcLengthDivisions = source.arcLengthDivisions;
31721
31722 return this;
31723
31724 },
31725
31726 toJSON: function () {
31727
31728 var data = {
31729 metadata: {
31730 version: 4.5,
31731 type: 'Curve',
31732 generator: 'Curve.toJSON'
31733 }
31734 };
31735
31736 data.arcLengthDivisions = this.arcLengthDivisions;
31737 data.type = this.type;
31738
31739 return data;
31740
31741 },
31742
31743 fromJSON: function ( json ) {
31744
31745 this.arcLengthDivisions = json.arcLengthDivisions;
31746
31747 return this;
31748
31749 }
31750
31751 } );
31752
31753 function EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
31754
31755 Curve.call( this );
31756
31757 this.type = 'EllipseCurve';
31758
31759 this.aX = aX || 0;
31760 this.aY = aY || 0;
31761
31762 this.xRadius = xRadius || 1;
31763 this.yRadius = yRadius || 1;
31764
31765 this.aStartAngle = aStartAngle || 0;
31766 this.aEndAngle = aEndAngle || 2 * Math.PI;
31767
31768 this.aClockwise = aClockwise || false;
31769
31770 this.aRotation = aRotation || 0;
31771
31772 }
31773
31774 EllipseCurve.prototype = Object.create( Curve.prototype );
31775 EllipseCurve.prototype.constructor = EllipseCurve;
31776
31777 EllipseCurve.prototype.isEllipseCurve = true;
31778
31779 EllipseCurve.prototype.getPoint = function ( t, optionalTarget ) {
31780
31781 var point = optionalTarget || new Vector2();
31782
31783 var twoPi = Math.PI * 2;
31784 var deltaAngle = this.aEndAngle - this.aStartAngle;
31785 var samePoints = Math.abs( deltaAngle ) < Number.EPSILON;
31786
31787 // ensures that deltaAngle is 0 .. 2 PI
31788 while ( deltaAngle < 0 ) deltaAngle += twoPi;
31789 while ( deltaAngle > twoPi ) deltaAngle -= twoPi;
31790
31791 if ( deltaAngle < Number.EPSILON ) {
31792
31793 if ( samePoints ) {
31794
31795 deltaAngle = 0;
31796
31797 } else {
31798
31799 deltaAngle = twoPi;
31800
31801 }
31802
31803 }
31804
31805 if ( this.aClockwise === true && ! samePoints ) {
31806
31807 if ( deltaAngle === twoPi ) {
31808
31809 deltaAngle = - twoPi;
31810
31811 } else {
31812
31813 deltaAngle = deltaAngle - twoPi;
31814
31815 }
31816
31817 }
31818
31819 var angle = this.aStartAngle + t * deltaAngle;
31820 var x = this.aX + this.xRadius * Math.cos( angle );
31821 var y = this.aY + this.yRadius * Math.sin( angle );
31822
31823 if ( this.aRotation !== 0 ) {
31824
31825 var cos = Math.cos( this.aRotation );
31826 var sin = Math.sin( this.aRotation );
31827
31828 var tx = x - this.aX;
31829 var ty = y - this.aY;
31830
31831 // Rotate the point about the center of the ellipse.
31832 x = tx * cos - ty * sin + this.aX;
31833 y = tx * sin + ty * cos + this.aY;
31834
31835 }
31836
31837 return point.set( x, y );
31838
31839 };
31840
31841 EllipseCurve.prototype.copy = function ( source ) {
31842
31843 Curve.prototype.copy.call( this, source );
31844
31845 this.aX = source.aX;
31846 this.aY = source.aY;
31847
31848 this.xRadius = source.xRadius;
31849 this.yRadius = source.yRadius;
31850
31851 this.aStartAngle = source.aStartAngle;
31852 this.aEndAngle = source.aEndAngle;
31853
31854 this.aClockwise = source.aClockwise;
31855
31856 this.aRotation = source.aRotation;
31857
31858 return this;
31859
31860 };
31861
31862
31863 EllipseCurve.prototype.toJSON = function () {
31864
31865 var data = Curve.prototype.toJSON.call( this );
31866
31867 data.aX = this.aX;
31868 data.aY = this.aY;
31869
31870 data.xRadius = this.xRadius;
31871 data.yRadius = this.yRadius;
31872
31873 data.aStartAngle = this.aStartAngle;
31874 data.aEndAngle = this.aEndAngle;
31875
31876 data.aClockwise = this.aClockwise;
31877
31878 data.aRotation = this.aRotation;
31879
31880 return data;
31881
31882 };
31883
31884 EllipseCurve.prototype.fromJSON = function ( json ) {
31885
31886 Curve.prototype.fromJSON.call( this, json );
31887
31888 this.aX = json.aX;
31889 this.aY = json.aY;
31890
31891 this.xRadius = json.xRadius;
31892 this.yRadius = json.yRadius;
31893
31894 this.aStartAngle = json.aStartAngle;
31895 this.aEndAngle = json.aEndAngle;
31896
31897 this.aClockwise = json.aClockwise;
31898
31899 this.aRotation = json.aRotation;
31900
31901 return this;
31902
31903 };
31904
31905 function ArcCurve( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
31906
31907 EllipseCurve.call( this, aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
31908
31909 this.type = 'ArcCurve';
31910
31911 }
31912
31913 ArcCurve.prototype = Object.create( EllipseCurve.prototype );
31914 ArcCurve.prototype.constructor = ArcCurve;
31915
31916 ArcCurve.prototype.isArcCurve = true;
31917
31918 /**
31919 * @author zz85 https://github.com/zz85
31920 *
31921 * Centripetal CatmullRom Curve - which is useful for avoiding
31922 * cusps and self-intersections in non-uniform catmull rom curves.
31923 * http://www.cemyuksel.com/research/catmullrom_param/catmullrom.pdf
31924 *
31925 * curve.type accepts centripetal(default), chordal and catmullrom
31926 * curve.tension is used for catmullrom which defaults to 0.5
31927 */
31928
31929
31930 /*
31931 Based on an optimized c++ solution in
31932 - http://stackoverflow.com/questions/9489736/catmull-rom-curve-with-no-cusps-and-no-self-intersections/
31933 - http://ideone.com/NoEbVM
31934
31935 This CubicPoly class could be used for reusing some variables and calculations,
31936 but for three.js curve use, it could be possible inlined and flatten into a single function call
31937 which can be placed in CurveUtils.
31938 */
31939
31940 function CubicPoly() {
31941
31942 var c0 = 0, c1 = 0, c2 = 0, c3 = 0;
31943
31944 /*
31945 * Compute coefficients for a cubic polynomial
31946 * p(s) = c0 + c1*s + c2*s^2 + c3*s^3
31947 * such that
31948 * p(0) = x0, p(1) = x1
31949 * and
31950 * p'(0) = t0, p'(1) = t1.
31951 */
31952 function init( x0, x1, t0, t1 ) {
31953
31954 c0 = x0;
31955 c1 = t0;
31956 c2 = - 3 * x0 + 3 * x1 - 2 * t0 - t1;
31957 c3 = 2 * x0 - 2 * x1 + t0 + t1;
31958
31959 }
31960
31961 return {
31962
31963 initCatmullRom: function ( x0, x1, x2, x3, tension ) {
31964
31965 init( x1, x2, tension * ( x2 - x0 ), tension * ( x3 - x1 ) );
31966
31967 },
31968
31969 initNonuniformCatmullRom: function ( x0, x1, x2, x3, dt0, dt1, dt2 ) {
31970
31971 // compute tangents when parameterized in [t1,t2]
31972 var t1 = ( x1 - x0 ) / dt0 - ( x2 - x0 ) / ( dt0 + dt1 ) + ( x2 - x1 ) / dt1;
31973 var t2 = ( x2 - x1 ) / dt1 - ( x3 - x1 ) / ( dt1 + dt2 ) + ( x3 - x2 ) / dt2;
31974
31975 // rescale tangents for parametrization in [0,1]
31976 t1 *= dt1;
31977 t2 *= dt1;
31978
31979 init( x1, x2, t1, t2 );
31980
31981 },
31982
31983 calc: function ( t ) {
31984
31985 var t2 = t * t;
31986 var t3 = t2 * t;
31987 return c0 + c1 * t + c2 * t2 + c3 * t3;
31988
31989 }
31990
31991 };
31992
31993 }
31994
31995 //
31996
31997 var tmp = new Vector3();
31998 var px = new CubicPoly();
31999 var py = new CubicPoly();
32000 var pz = new CubicPoly();
32001
32002 function CatmullRomCurve3( points, closed, curveType, tension ) {
32003
32004 Curve.call( this );
32005
32006 this.type = 'CatmullRomCurve3';
32007
32008 this.points = points || [];
32009 this.closed = closed || false;
32010 this.curveType = curveType || 'centripetal';
32011 this.tension = tension || 0.5;
32012
32013 }
32014
32015 CatmullRomCurve3.prototype = Object.create( Curve.prototype );
32016 CatmullRomCurve3.prototype.constructor = CatmullRomCurve3;
32017
32018 CatmullRomCurve3.prototype.isCatmullRomCurve3 = true;
32019
32020 CatmullRomCurve3.prototype.getPoint = function ( t, optionalTarget ) {
32021
32022 var point = optionalTarget || new Vector3();
32023
32024 var points = this.points;
32025 var l = points.length;
32026
32027 var p = ( l - ( this.closed ? 0 : 1 ) ) * t;
32028 var intPoint = Math.floor( p );
32029 var weight = p - intPoint;
32030
32031 if ( this.closed ) {
32032
32033 intPoint += intPoint > 0 ? 0 : ( Math.floor( Math.abs( intPoint ) / l ) + 1 ) * l;
32034
32035 } else if ( weight === 0 && intPoint === l - 1 ) {
32036
32037 intPoint = l - 2;
32038 weight = 1;
32039
32040 }
32041
32042 var p0, p1, p2, p3; // 4 points
32043
32044 if ( this.closed || intPoint > 0 ) {
32045
32046 p0 = points[ ( intPoint - 1 ) % l ];
32047
32048 } else {
32049
32050 // extrapolate first point
32051 tmp.subVectors( points[ 0 ], points[ 1 ] ).add( points[ 0 ] );
32052 p0 = tmp;
32053
32054 }
32055
32056 p1 = points[ intPoint % l ];
32057 p2 = points[ ( intPoint + 1 ) % l ];
32058
32059 if ( this.closed || intPoint + 2 < l ) {
32060
32061 p3 = points[ ( intPoint + 2 ) % l ];
32062
32063 } else {
32064
32065 // extrapolate last point
32066 tmp.subVectors( points[ l - 1 ], points[ l - 2 ] ).add( points[ l - 1 ] );
32067 p3 = tmp;
32068
32069 }
32070
32071 if ( this.curveType === 'centripetal' || this.curveType === 'chordal' ) {
32072
32073 // init Centripetal / Chordal Catmull-Rom
32074 var pow = this.curveType === 'chordal' ? 0.5 : 0.25;
32075 var dt0 = Math.pow( p0.distanceToSquared( p1 ), pow );
32076 var dt1 = Math.pow( p1.distanceToSquared( p2 ), pow );
32077 var dt2 = Math.pow( p2.distanceToSquared( p3 ), pow );
32078
32079 // safety check for repeated points
32080 if ( dt1 < 1e-4 ) dt1 = 1.0;
32081 if ( dt0 < 1e-4 ) dt0 = dt1;
32082 if ( dt2 < 1e-4 ) dt2 = dt1;
32083
32084 px.initNonuniformCatmullRom( p0.x, p1.x, p2.x, p3.x, dt0, dt1, dt2 );
32085 py.initNonuniformCatmullRom( p0.y, p1.y, p2.y, p3.y, dt0, dt1, dt2 );
32086 pz.initNonuniformCatmullRom( p0.z, p1.z, p2.z, p3.z, dt0, dt1, dt2 );
32087
32088 } else if ( this.curveType === 'catmullrom' ) {
32089
32090 px.initCatmullRom( p0.x, p1.x, p2.x, p3.x, this.tension );
32091 py.initCatmullRom( p0.y, p1.y, p2.y, p3.y, this.tension );
32092 pz.initCatmullRom( p0.z, p1.z, p2.z, p3.z, this.tension );
32093
32094 }
32095
32096 point.set(
32097 px.calc( weight ),
32098 py.calc( weight ),
32099 pz.calc( weight )
32100 );
32101
32102 return point;
32103
32104 };
32105
32106 CatmullRomCurve3.prototype.copy = function ( source ) {
32107
32108 Curve.prototype.copy.call( this, source );
32109
32110 this.points = [];
32111
32112 for ( var i = 0, l = source.points.length; i < l; i ++ ) {
32113
32114 var point = source.points[ i ];
32115
32116 this.points.push( point.clone() );
32117
32118 }
32119
32120 this.closed = source.closed;
32121 this.curveType = source.curveType;
32122 this.tension = source.tension;
32123
32124 return this;
32125
32126 };
32127
32128 CatmullRomCurve3.prototype.toJSON = function () {
32129
32130 var data = Curve.prototype.toJSON.call( this );
32131
32132 data.points = [];
32133
32134 for ( var i = 0, l = this.points.length; i < l; i ++ ) {
32135
32136 var point = this.points[ i ];
32137 data.points.push( point.toArray() );
32138
32139 }
32140
32141 data.closed = this.closed;
32142 data.curveType = this.curveType;
32143 data.tension = this.tension;
32144
32145 return data;
32146
32147 };
32148
32149 CatmullRomCurve3.prototype.fromJSON = function ( json ) {
32150
32151 Curve.prototype.fromJSON.call( this, json );
32152
32153 this.points = [];
32154
32155 for ( var i = 0, l = json.points.length; i < l; i ++ ) {
32156
32157 var point = json.points[ i ];
32158 this.points.push( new Vector3().fromArray( point ) );
32159
32160 }
32161
32162 this.closed = json.closed;
32163 this.curveType = json.curveType;
32164 this.tension = json.tension;
32165
32166 return this;
32167
32168 };
32169
32170 /**
32171 * @author zz85 / http://www.lab4games.net/zz85/blog
32172 *
32173 * Bezier Curves formulas obtained from
32174 * http://en.wikipedia.org/wiki/Bézier_curve
32175 */
32176
32177 function CatmullRom( t, p0, p1, p2, p3 ) {
32178
32179 var v0 = ( p2 - p0 ) * 0.5;
32180 var v1 = ( p3 - p1 ) * 0.5;
32181 var t2 = t * t;
32182 var t3 = t * t2;
32183 return ( 2 * p1 - 2 * p2 + v0 + v1 ) * t3 + ( - 3 * p1 + 3 * p2 - 2 * v0 - v1 ) * t2 + v0 * t + p1;
32184
32185 }
32186
32187 //
32188
32189 function QuadraticBezierP0( t, p ) {
32190
32191 var k = 1 - t;
32192 return k * k * p;
32193
32194 }
32195
32196 function QuadraticBezierP1( t, p ) {
32197
32198 return 2 * ( 1 - t ) * t * p;
32199
32200 }
32201
32202 function QuadraticBezierP2( t, p ) {
32203
32204 return t * t * p;
32205
32206 }
32207
32208 function QuadraticBezier( t, p0, p1, p2 ) {
32209
32210 return QuadraticBezierP0( t, p0 ) + QuadraticBezierP1( t, p1 ) +
32211 QuadraticBezierP2( t, p2 );
32212
32213 }
32214
32215 //
32216
32217 function CubicBezierP0( t, p ) {
32218
32219 var k = 1 - t;
32220 return k * k * k * p;
32221
32222 }
32223
32224 function CubicBezierP1( t, p ) {
32225
32226 var k = 1 - t;
32227 return 3 * k * k * t * p;
32228
32229 }
32230
32231 function CubicBezierP2( t, p ) {
32232
32233 return 3 * ( 1 - t ) * t * t * p;
32234
32235 }
32236
32237 function CubicBezierP3( t, p ) {
32238
32239 return t * t * t * p;
32240
32241 }
32242
32243 function CubicBezier( t, p0, p1, p2, p3 ) {
32244
32245 return CubicBezierP0( t, p0 ) + CubicBezierP1( t, p1 ) + CubicBezierP2( t, p2 ) +
32246 CubicBezierP3( t, p3 );
32247
32248 }
32249
32250 function CubicBezierCurve( v0, v1, v2, v3 ) {
32251
32252 Curve.call( this );
32253
32254 this.type = 'CubicBezierCurve';
32255
32256 this.v0 = v0 || new Vector2();
32257 this.v1 = v1 || new Vector2();
32258 this.v2 = v2 || new Vector2();
32259 this.v3 = v3 || new Vector2();
32260
32261 }
32262
32263 CubicBezierCurve.prototype = Object.create( Curve.prototype );
32264 CubicBezierCurve.prototype.constructor = CubicBezierCurve;
32265
32266 CubicBezierCurve.prototype.isCubicBezierCurve = true;
32267
32268 CubicBezierCurve.prototype.getPoint = function ( t, optionalTarget ) {
32269
32270 var point = optionalTarget || new Vector2();
32271
32272 var v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3;
32273
32274 point.set(
32275 CubicBezier( t, v0.x, v1.x, v2.x, v3.x ),
32276 CubicBezier( t, v0.y, v1.y, v2.y, v3.y )
32277 );
32278
32279 return point;
32280
32281 };
32282
32283 CubicBezierCurve.prototype.copy = function ( source ) {
32284
32285 Curve.prototype.copy.call( this, source );
32286
32287 this.v0.copy( source.v0 );
32288 this.v1.copy( source.v1 );
32289 this.v2.copy( source.v2 );
32290 this.v3.copy( source.v3 );
32291
32292 return this;
32293
32294 };
32295
32296 CubicBezierCurve.prototype.toJSON = function () {
32297
32298 var data = Curve.prototype.toJSON.call( this );
32299
32300 data.v0 = this.v0.toArray();
32301 data.v1 = this.v1.toArray();
32302 data.v2 = this.v2.toArray();
32303 data.v3 = this.v3.toArray();
32304
32305 return data;
32306
32307 };
32308
32309 CubicBezierCurve.prototype.fromJSON = function ( json ) {
32310
32311 Curve.prototype.fromJSON.call( this, json );
32312
32313 this.v0.fromArray( json.v0 );
32314 this.v1.fromArray( json.v1 );
32315 this.v2.fromArray( json.v2 );
32316 this.v3.fromArray( json.v3 );
32317
32318 return this;
32319
32320 };
32321
32322 function CubicBezierCurve3( v0, v1, v2, v3 ) {
32323
32324 Curve.call( this );
32325
32326 this.type = 'CubicBezierCurve3';
32327
32328 this.v0 = v0 || new Vector3();
32329 this.v1 = v1 || new Vector3();
32330 this.v2 = v2 || new Vector3();
32331 this.v3 = v3 || new Vector3();
32332
32333 }
32334
32335 CubicBezierCurve3.prototype = Object.create( Curve.prototype );
32336 CubicBezierCurve3.prototype.constructor = CubicBezierCurve3;
32337
32338 CubicBezierCurve3.prototype.isCubicBezierCurve3 = true;
32339
32340 CubicBezierCurve3.prototype.getPoint = function ( t, optionalTarget ) {
32341
32342 var point = optionalTarget || new Vector3();
32343
32344 var v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3;
32345
32346 point.set(
32347 CubicBezier( t, v0.x, v1.x, v2.x, v3.x ),
32348 CubicBezier( t, v0.y, v1.y, v2.y, v3.y ),
32349 CubicBezier( t, v0.z, v1.z, v2.z, v3.z )
32350 );
32351
32352 return point;
32353
32354 };
32355
32356 CubicBezierCurve3.prototype.copy = function ( source ) {
32357
32358 Curve.prototype.copy.call( this, source );
32359
32360 this.v0.copy( source.v0 );
32361 this.v1.copy( source.v1 );
32362 this.v2.copy( source.v2 );
32363 this.v3.copy( source.v3 );
32364
32365 return this;
32366
32367 };
32368
32369 CubicBezierCurve3.prototype.toJSON = function () {
32370
32371 var data = Curve.prototype.toJSON.call( this );
32372
32373 data.v0 = this.v0.toArray();
32374 data.v1 = this.v1.toArray();
32375 data.v2 = this.v2.toArray();
32376 data.v3 = this.v3.toArray();
32377
32378 return data;
32379
32380 };
32381
32382 CubicBezierCurve3.prototype.fromJSON = function ( json ) {
32383
32384 Curve.prototype.fromJSON.call( this, json );
32385
32386 this.v0.fromArray( json.v0 );
32387 this.v1.fromArray( json.v1 );
32388 this.v2.fromArray( json.v2 );
32389 this.v3.fromArray( json.v3 );
32390
32391 return this;
32392
32393 };
32394
32395 function LineCurve( v1, v2 ) {
32396
32397 Curve.call( this );
32398
32399 this.type = 'LineCurve';
32400
32401 this.v1 = v1 || new Vector2();
32402 this.v2 = v2 || new Vector2();
32403
32404 }
32405
32406 LineCurve.prototype = Object.create( Curve.prototype );
32407 LineCurve.prototype.constructor = LineCurve;
32408
32409 LineCurve.prototype.isLineCurve = true;
32410
32411 LineCurve.prototype.getPoint = function ( t, optionalTarget ) {
32412
32413 var point = optionalTarget || new Vector2();
32414
32415 if ( t === 1 ) {
32416
32417 point.copy( this.v2 );
32418
32419 } else {
32420
32421 point.copy( this.v2 ).sub( this.v1 );
32422 point.multiplyScalar( t ).add( this.v1 );
32423
32424 }
32425
32426 return point;
32427
32428 };
32429
32430 // Line curve is linear, so we can overwrite default getPointAt
32431
32432 LineCurve.prototype.getPointAt = function ( u, optionalTarget ) {
32433
32434 return this.getPoint( u, optionalTarget );
32435
32436 };
32437
32438 LineCurve.prototype.getTangent = function ( /* t */ ) {
32439
32440 var tangent = this.v2.clone().sub( this.v1 );
32441
32442 return tangent.normalize();
32443
32444 };
32445
32446 LineCurve.prototype.copy = function ( source ) {
32447
32448 Curve.prototype.copy.call( this, source );
32449
32450 this.v1.copy( source.v1 );
32451 this.v2.copy( source.v2 );
32452
32453 return this;
32454
32455 };
32456
32457 LineCurve.prototype.toJSON = function () {
32458
32459 var data = Curve.prototype.toJSON.call( this );
32460
32461 data.v1 = this.v1.toArray();
32462 data.v2 = this.v2.toArray();
32463
32464 return data;
32465
32466 };
32467
32468 LineCurve.prototype.fromJSON = function ( json ) {
32469
32470 Curve.prototype.fromJSON.call( this, json );
32471
32472 this.v1.fromArray( json.v1 );
32473 this.v2.fromArray( json.v2 );
32474
32475 return this;
32476
32477 };
32478
32479 function LineCurve3( v1, v2 ) {
32480
32481 Curve.call( this );
32482
32483 this.type = 'LineCurve3';
32484
32485 this.v1 = v1 || new Vector3();
32486 this.v2 = v2 || new Vector3();
32487
32488 }
32489
32490 LineCurve3.prototype = Object.create( Curve.prototype );
32491 LineCurve3.prototype.constructor = LineCurve3;
32492
32493 LineCurve3.prototype.isLineCurve3 = true;
32494
32495 LineCurve3.prototype.getPoint = function ( t, optionalTarget ) {
32496
32497 var point = optionalTarget || new Vector3();
32498
32499 if ( t === 1 ) {
32500
32501 point.copy( this.v2 );
32502
32503 } else {
32504
32505 point.copy( this.v2 ).sub( this.v1 );
32506 point.multiplyScalar( t ).add( this.v1 );
32507
32508 }
32509
32510 return point;
32511
32512 };
32513
32514 // Line curve is linear, so we can overwrite default getPointAt
32515
32516 LineCurve3.prototype.getPointAt = function ( u, optionalTarget ) {
32517
32518 return this.getPoint( u, optionalTarget );
32519
32520 };
32521
32522 LineCurve3.prototype.copy = function ( source ) {
32523
32524 Curve.prototype.copy.call( this, source );
32525
32526 this.v1.copy( source.v1 );
32527 this.v2.copy( source.v2 );
32528
32529 return this;
32530
32531 };
32532
32533 LineCurve3.prototype.toJSON = function () {
32534
32535 var data = Curve.prototype.toJSON.call( this );
32536
32537 data.v1 = this.v1.toArray();
32538 data.v2 = this.v2.toArray();
32539
32540 return data;
32541
32542 };
32543
32544 LineCurve3.prototype.fromJSON = function ( json ) {
32545
32546 Curve.prototype.fromJSON.call( this, json );
32547
32548 this.v1.fromArray( json.v1 );
32549 this.v2.fromArray( json.v2 );
32550
32551 return this;
32552
32553 };
32554
32555 function QuadraticBezierCurve( v0, v1, v2 ) {
32556
32557 Curve.call( this );
32558
32559 this.type = 'QuadraticBezierCurve';
32560
32561 this.v0 = v0 || new Vector2();
32562 this.v1 = v1 || new Vector2();
32563 this.v2 = v2 || new Vector2();
32564
32565 }
32566
32567 QuadraticBezierCurve.prototype = Object.create( Curve.prototype );
32568 QuadraticBezierCurve.prototype.constructor = QuadraticBezierCurve;
32569
32570 QuadraticBezierCurve.prototype.isQuadraticBezierCurve = true;
32571
32572 QuadraticBezierCurve.prototype.getPoint = function ( t, optionalTarget ) {
32573
32574 var point = optionalTarget || new Vector2();
32575
32576 var v0 = this.v0, v1 = this.v1, v2 = this.v2;
32577
32578 point.set(
32579 QuadraticBezier( t, v0.x, v1.x, v2.x ),
32580 QuadraticBezier( t, v0.y, v1.y, v2.y )
32581 );
32582
32583 return point;
32584
32585 };
32586
32587 QuadraticBezierCurve.prototype.copy = function ( source ) {
32588
32589 Curve.prototype.copy.call( this, source );
32590
32591 this.v0.copy( source.v0 );
32592 this.v1.copy( source.v1 );
32593 this.v2.copy( source.v2 );
32594
32595 return this;
32596
32597 };
32598
32599 QuadraticBezierCurve.prototype.toJSON = function () {
32600
32601 var data = Curve.prototype.toJSON.call( this );
32602
32603 data.v0 = this.v0.toArray();
32604 data.v1 = this.v1.toArray();
32605 data.v2 = this.v2.toArray();
32606
32607 return data;
32608
32609 };
32610
32611 QuadraticBezierCurve.prototype.fromJSON = function ( json ) {
32612
32613 Curve.prototype.fromJSON.call( this, json );
32614
32615 this.v0.fromArray( json.v0 );
32616 this.v1.fromArray( json.v1 );
32617 this.v2.fromArray( json.v2 );
32618
32619 return this;
32620
32621 };
32622
32623 function QuadraticBezierCurve3( v0, v1, v2 ) {
32624
32625 Curve.call( this );
32626
32627 this.type = 'QuadraticBezierCurve3';
32628
32629 this.v0 = v0 || new Vector3();
32630 this.v1 = v1 || new Vector3();
32631 this.v2 = v2 || new Vector3();
32632
32633 }
32634
32635 QuadraticBezierCurve3.prototype = Object.create( Curve.prototype );
32636 QuadraticBezierCurve3.prototype.constructor = QuadraticBezierCurve3;
32637
32638 QuadraticBezierCurve3.prototype.isQuadraticBezierCurve3 = true;
32639
32640 QuadraticBezierCurve3.prototype.getPoint = function ( t, optionalTarget ) {
32641
32642 var point = optionalTarget || new Vector3();
32643
32644 var v0 = this.v0, v1 = this.v1, v2 = this.v2;
32645
32646 point.set(
32647 QuadraticBezier( t, v0.x, v1.x, v2.x ),
32648 QuadraticBezier( t, v0.y, v1.y, v2.y ),
32649 QuadraticBezier( t, v0.z, v1.z, v2.z )
32650 );
32651
32652 return point;
32653
32654 };
32655
32656 QuadraticBezierCurve3.prototype.copy = function ( source ) {
32657
32658 Curve.prototype.copy.call( this, source );
32659
32660 this.v0.copy( source.v0 );
32661 this.v1.copy( source.v1 );
32662 this.v2.copy( source.v2 );
32663
32664 return this;
32665
32666 };
32667
32668 QuadraticBezierCurve3.prototype.toJSON = function () {
32669
32670 var data = Curve.prototype.toJSON.call( this );
32671
32672 data.v0 = this.v0.toArray();
32673 data.v1 = this.v1.toArray();
32674 data.v2 = this.v2.toArray();
32675
32676 return data;
32677
32678 };
32679
32680 QuadraticBezierCurve3.prototype.fromJSON = function ( json ) {
32681
32682 Curve.prototype.fromJSON.call( this, json );
32683
32684 this.v0.fromArray( json.v0 );
32685 this.v1.fromArray( json.v1 );
32686 this.v2.fromArray( json.v2 );
32687
32688 return this;
32689
32690 };
32691
32692 function SplineCurve( points /* array of Vector2 */ ) {
32693
32694 Curve.call( this );
32695
32696 this.type = 'SplineCurve';
32697
32698 this.points = points || [];
32699
32700 }
32701
32702 SplineCurve.prototype = Object.create( Curve.prototype );
32703 SplineCurve.prototype.constructor = SplineCurve;
32704
32705 SplineCurve.prototype.isSplineCurve = true;
32706
32707 SplineCurve.prototype.getPoint = function ( t, optionalTarget ) {
32708
32709 var point = optionalTarget || new Vector2();
32710
32711 var points = this.points;
32712 var p = ( points.length - 1 ) * t;
32713
32714 var intPoint = Math.floor( p );
32715 var weight = p - intPoint;
32716
32717 var p0 = points[ intPoint === 0 ? intPoint : intPoint - 1 ];
32718 var p1 = points[ intPoint ];
32719 var p2 = points[ intPoint > points.length - 2 ? points.length - 1 : intPoint + 1 ];
32720 var p3 = points[ intPoint > points.length - 3 ? points.length - 1 : intPoint + 2 ];
32721
32722 point.set(
32723 CatmullRom( weight, p0.x, p1.x, p2.x, p3.x ),
32724 CatmullRom( weight, p0.y, p1.y, p2.y, p3.y )
32725 );
32726
32727 return point;
32728
32729 };
32730
32731 SplineCurve.prototype.copy = function ( source ) {
32732
32733 Curve.prototype.copy.call( this, source );
32734
32735 this.points = [];
32736
32737 for ( var i = 0, l = source.points.length; i < l; i ++ ) {
32738
32739 var point = source.points[ i ];
32740
32741 this.points.push( point.clone() );
32742
32743 }
32744
32745 return this;
32746
32747 };
32748
32749 SplineCurve.prototype.toJSON = function () {
32750
32751 var data = Curve.prototype.toJSON.call( this );
32752
32753 data.points = [];
32754
32755 for ( var i = 0, l = this.points.length; i < l; i ++ ) {
32756
32757 var point = this.points[ i ];
32758 data.points.push( point.toArray() );
32759
32760 }
32761
32762 return data;
32763
32764 };
32765
32766 SplineCurve.prototype.fromJSON = function ( json ) {
32767
32768 Curve.prototype.fromJSON.call( this, json );
32769
32770 this.points = [];
32771
32772 for ( var i = 0, l = json.points.length; i < l; i ++ ) {
32773
32774 var point = json.points[ i ];
32775 this.points.push( new Vector2().fromArray( point ) );
32776
32777 }
32778
32779 return this;
32780
32781 };
32782
32783
32784
32785 var Curves = Object.freeze({
32786 ArcCurve: ArcCurve,
32787 CatmullRomCurve3: CatmullRomCurve3,
32788 CubicBezierCurve: CubicBezierCurve,
32789 CubicBezierCurve3: CubicBezierCurve3,
32790 EllipseCurve: EllipseCurve,
32791 LineCurve: LineCurve,
32792 LineCurve3: LineCurve3,
32793 QuadraticBezierCurve: QuadraticBezierCurve,
32794 QuadraticBezierCurve3: QuadraticBezierCurve3,
32795 SplineCurve: SplineCurve
32796 });
32797
32798 /**
32799 * @author zz85 / http://www.lab4games.net/zz85/blog
32800 *
32801 **/
32802
32803 /**************************************************************
32804 * Curved Path - a curve path is simply a array of connected
32805 * curves, but retains the api of a curve
32806 **************************************************************/
32807
32808 function CurvePath() {
32809
32810 Curve.call( this );
32811
32812 this.type = 'CurvePath';
32813
32814 this.curves = [];
32815 this.autoClose = false; // Automatically closes the path
32816
32817 }
32818
32819 CurvePath.prototype = Object.assign( Object.create( Curve.prototype ), {
32820
32821 constructor: CurvePath,
32822
32823 add: function ( curve ) {
32824
32825 this.curves.push( curve );
32826
32827 },
32828
32829 closePath: function () {
32830
32831 // Add a line curve if start and end of lines are not connected
32832 var startPoint = this.curves[ 0 ].getPoint( 0 );
32833 var endPoint = this.curves[ this.curves.length - 1 ].getPoint( 1 );
32834
32835 if ( ! startPoint.equals( endPoint ) ) {
32836
32837 this.curves.push( new LineCurve( endPoint, startPoint ) );
32838
32839 }
32840
32841 },
32842
32843 // To get accurate point with reference to
32844 // entire path distance at time t,
32845 // following has to be done:
32846
32847 // 1. Length of each sub path have to be known
32848 // 2. Locate and identify type of curve
32849 // 3. Get t for the curve
32850 // 4. Return curve.getPointAt(t')
32851
32852 getPoint: function ( t ) {
32853
32854 var d = t * this.getLength();
32855 var curveLengths = this.getCurveLengths();
32856 var i = 0;
32857
32858 // To think about boundaries points.
32859
32860 while ( i < curveLengths.length ) {
32861
32862 if ( curveLengths[ i ] >= d ) {
32863
32864 var diff = curveLengths[ i ] - d;
32865 var curve = this.curves[ i ];
32866
32867 var segmentLength = curve.getLength();
32868 var u = segmentLength === 0 ? 0 : 1 - diff / segmentLength;
32869
32870 return curve.getPointAt( u );
32871
32872 }
32873
32874 i ++;
32875
32876 }
32877
32878 return null;
32879
32880 // loop where sum != 0, sum > d , sum+1 <d
32881
32882 },
32883
32884 // We cannot use the default THREE.Curve getPoint() with getLength() because in
32885 // THREE.Curve, getLength() depends on getPoint() but in THREE.CurvePath
32886 // getPoint() depends on getLength
32887
32888 getLength: function () {
32889
32890 var lens = this.getCurveLengths();
32891 return lens[ lens.length - 1 ];
32892
32893 },
32894
32895 // cacheLengths must be recalculated.
32896 updateArcLengths: function () {
32897
32898 this.needsUpdate = true;
32899 this.cacheLengths = null;
32900 this.getCurveLengths();
32901
32902 },
32903
32904 // Compute lengths and cache them
32905 // We cannot overwrite getLengths() because UtoT mapping uses it.
32906
32907 getCurveLengths: function () {
32908
32909 // We use cache values if curves and cache array are same length
32910
32911 if ( this.cacheLengths && this.cacheLengths.length === this.curves.length ) {
32912
32913 return this.cacheLengths;
32914
32915 }
32916
32917 // Get length of sub-curve
32918 // Push sums into cached array
32919
32920 var lengths = [], sums = 0;
32921
32922 for ( var i = 0, l = this.curves.length; i < l; i ++ ) {
32923
32924 sums += this.curves[ i ].getLength();
32925 lengths.push( sums );
32926
32927 }
32928
32929 this.cacheLengths = lengths;
32930
32931 return lengths;
32932
32933 },
32934
32935 getSpacedPoints: function ( divisions ) {
32936
32937 if ( divisions === undefined ) divisions = 40;
32938
32939 var points = [];
32940
32941 for ( var i = 0; i <= divisions; i ++ ) {
32942
32943 points.push( this.getPoint( i / divisions ) );
32944
32945 }
32946
32947 if ( this.autoClose ) {
32948
32949 points.push( points[ 0 ] );
32950
32951 }
32952
32953 return points;
32954
32955 },
32956
32957 getPoints: function ( divisions ) {
32958
32959 divisions = divisions || 12;
32960
32961 var points = [], last;
32962
32963 for ( var i = 0, curves = this.curves; i < curves.length; i ++ ) {
32964
32965 var curve = curves[ i ];
32966 var resolution = ( curve && curve.isEllipseCurve ) ? divisions * 2
32967 : ( curve && curve.isLineCurve ) ? 1
32968 : ( curve && curve.isSplineCurve ) ? divisions * curve.points.length
32969 : divisions;
32970
32971 var pts = curve.getPoints( resolution );
32972
32973 for ( var j = 0; j < pts.length; j ++ ) {
32974
32975 var point = pts[ j ];
32976
32977 if ( last && last.equals( point ) ) continue; // ensures no consecutive points are duplicates
32978
32979 points.push( point );
32980 last = point;
32981
32982 }
32983
32984 }
32985
32986 if ( this.autoClose && points.length > 1 && ! points[ points.length - 1 ].equals( points[ 0 ] ) ) {
32987
32988 points.push( points[ 0 ] );
32989
32990 }
32991
32992 return points;
32993
32994 },
32995
32996 copy: function ( source ) {
32997
32998 Curve.prototype.copy.call( this, source );
32999
33000 this.curves = [];
33001
33002 for ( var i = 0, l = source.curves.length; i < l; i ++ ) {
33003
33004 var curve = source.curves[ i ];
33005
33006 this.curves.push( curve.clone() );
33007
33008 }
33009
33010 this.autoClose = source.autoClose;
33011
33012 return this;
33013
33014 },
33015
33016 toJSON: function () {
33017
33018 var data = Curve.prototype.toJSON.call( this );
33019
33020 data.autoClose = this.autoClose;
33021 data.curves = [];
33022
33023 for ( var i = 0, l = this.curves.length; i < l; i ++ ) {
33024
33025 var curve = this.curves[ i ];
33026 data.curves.push( curve.toJSON() );
33027
33028 }
33029
33030 return data;
33031
33032 },
33033
33034 fromJSON: function ( json ) {
33035
33036 Curve.prototype.fromJSON.call( this, json );
33037
33038 this.autoClose = json.autoClose;
33039 this.curves = [];
33040
33041 for ( var i = 0, l = json.curves.length; i < l; i ++ ) {
33042
33043 var curve = json.curves[ i ];
33044 this.curves.push( new Curves[ curve.type ]().fromJSON( curve ) );
33045
33046 }
33047
33048 return this;
33049
33050 }
33051
33052 } );
33053
33054 /**
33055 * @author zz85 / http://www.lab4games.net/zz85/blog
33056 * Creates free form 2d path using series of points, lines or curves.
33057 **/
33058
33059 function Path( points ) {
33060
33061 CurvePath.call( this );
33062
33063 this.type = 'Path';
33064
33065 this.currentPoint = new Vector2();
33066
33067 if ( points ) {
33068
33069 this.setFromPoints( points );
33070
33071 }
33072
33073 }
33074
33075 Path.prototype = Object.assign( Object.create( CurvePath.prototype ), {
33076
33077 constructor: Path,
33078
33079 setFromPoints: function ( points ) {
33080
33081 this.moveTo( points[ 0 ].x, points[ 0 ].y );
33082
33083 for ( var i = 1, l = points.length; i < l; i ++ ) {
33084
33085 this.lineTo( points[ i ].x, points[ i ].y );
33086
33087 }
33088
33089 },
33090
33091 moveTo: function ( x, y ) {
33092
33093 this.currentPoint.set( x, y ); // TODO consider referencing vectors instead of copying?
33094
33095 },
33096
33097 lineTo: function ( x, y ) {
33098
33099 var curve = new LineCurve( this.currentPoint.clone(), new Vector2( x, y ) );
33100 this.curves.push( curve );
33101
33102 this.currentPoint.set( x, y );
33103
33104 },
33105
33106 quadraticCurveTo: function ( aCPx, aCPy, aX, aY ) {
33107
33108 var curve = new QuadraticBezierCurve(
33109 this.currentPoint.clone(),
33110 new Vector2( aCPx, aCPy ),
33111 new Vector2( aX, aY )
33112 );
33113
33114 this.curves.push( curve );
33115
33116 this.currentPoint.set( aX, aY );
33117
33118 },
33119
33120 bezierCurveTo: function ( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) {
33121
33122 var curve = new CubicBezierCurve(
33123 this.currentPoint.clone(),
33124 new Vector2( aCP1x, aCP1y ),
33125 new Vector2( aCP2x, aCP2y ),
33126 new Vector2( aX, aY )
33127 );
33128
33129 this.curves.push( curve );
33130
33131 this.currentPoint.set( aX, aY );
33132
33133 },
33134
33135 splineThru: function ( pts /*Array of Vector*/ ) {
33136
33137 var npts = [ this.currentPoint.clone() ].concat( pts );
33138
33139 var curve = new SplineCurve( npts );
33140 this.curves.push( curve );
33141
33142 this.currentPoint.copy( pts[ pts.length - 1 ] );
33143
33144 },
33145
33146 arc: function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
33147
33148 var x0 = this.currentPoint.x;
33149 var y0 = this.currentPoint.y;
33150
33151 this.absarc( aX + x0, aY + y0, aRadius,
33152 aStartAngle, aEndAngle, aClockwise );
33153
33154 },
33155
33156 absarc: function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
33157
33158 this.absellipse( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
33159
33160 },
33161
33162 ellipse: function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
33163
33164 var x0 = this.currentPoint.x;
33165 var y0 = this.currentPoint.y;
33166
33167 this.absellipse( aX + x0, aY + y0, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
33168
33169 },
33170
33171 absellipse: function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
33172
33173 var curve = new EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
33174
33175 if ( this.curves.length > 0 ) {
33176
33177 // if a previous curve is present, attempt to join
33178 var firstPoint = curve.getPoint( 0 );
33179
33180 if ( ! firstPoint.equals( this.currentPoint ) ) {
33181
33182 this.lineTo( firstPoint.x, firstPoint.y );
33183
33184 }
33185
33186 }
33187
33188 this.curves.push( curve );
33189
33190 var lastPoint = curve.getPoint( 1 );
33191 this.currentPoint.copy( lastPoint );
33192
33193 },
33194
33195 copy: function ( source ) {
33196
33197 CurvePath.prototype.copy.call( this, source );
33198
33199 this.currentPoint.copy( source.currentPoint );
33200
33201 return this;
33202
33203 },
33204
33205 toJSON: function () {
33206
33207 var data = CurvePath.prototype.toJSON.call( this );
33208
33209 data.currentPoint = this.currentPoint.toArray();
33210
33211 return data;
33212
33213 },
33214
33215 fromJSON: function ( json ) {
33216
33217 CurvePath.prototype.fromJSON.call( this, json );
33218
33219 this.currentPoint.fromArray( json.currentPoint );
33220
33221 return this;
33222
33223 }
33224
33225 } );
33226
33227 /**
33228 * @author zz85 / http://www.lab4games.net/zz85/blog
33229 * Defines a 2d shape plane using paths.
33230 **/
33231
33232 // STEP 1 Create a path.
33233 // STEP 2 Turn path into shape.
33234 // STEP 3 ExtrudeGeometry takes in Shape/Shapes
33235 // STEP 3a - Extract points from each shape, turn to vertices
33236 // STEP 3b - Triangulate each shape, add faces.
33237
33238 function Shape( points ) {
33239
33240 Path.call( this, points );
33241
33242 this.uuid = _Math.generateUUID();
33243
33244 this.type = 'Shape';
33245
33246 this.holes = [];
33247
33248 }
33249
33250 Shape.prototype = Object.assign( Object.create( Path.prototype ), {
33251
33252 constructor: Shape,
33253
33254 getPointsHoles: function ( divisions ) {
33255
33256 var holesPts = [];
33257
33258 for ( var i = 0, l = this.holes.length; i < l; i ++ ) {
33259
33260 holesPts[ i ] = this.holes[ i ].getPoints( divisions );
33261
33262 }
33263
33264 return holesPts;
33265
33266 },
33267
33268 // get points of shape and holes (keypoints based on segments parameter)
33269
33270 extractPoints: function ( divisions ) {
33271
33272 return {
33273
33274 shape: this.getPoints( divisions ),
33275 holes: this.getPointsHoles( divisions )
33276
33277 };
33278
33279 },
33280
33281 copy: function ( source ) {
33282
33283 Path.prototype.copy.call( this, source );
33284
33285 this.holes = [];
33286
33287 for ( var i = 0, l = source.holes.length; i < l; i ++ ) {
33288
33289 var hole = source.holes[ i ];
33290
33291 this.holes.push( hole.clone() );
33292
33293 }
33294
33295 return this;
33296
33297 },
33298
33299 toJSON: function () {
33300
33301 var data = Path.prototype.toJSON.call( this );
33302
33303 data.uuid = this.uuid;
33304 data.holes = [];
33305
33306 for ( var i = 0, l = this.holes.length; i < l; i ++ ) {
33307
33308 var hole = this.holes[ i ];
33309 data.holes.push( hole.toJSON() );
33310
33311 }
33312
33313 return data;
33314
33315 },
33316
33317 fromJSON: function ( json ) {
33318
33319 Path.prototype.fromJSON.call( this, json );
33320
33321 this.uuid = json.uuid;
33322 this.holes = [];
33323
33324 for ( var i = 0, l = json.holes.length; i < l; i ++ ) {
33325
33326 var hole = json.holes[ i ];
33327 this.holes.push( new Path().fromJSON( hole ) );
33328
33329 }
33330
33331 return this;
33332
33333 }
33334
33335 } );
33336
33337 /**
33338 * @author mrdoob / http://mrdoob.com/
33339 * @author alteredq / http://alteredqualia.com/
33340 */
33341
33342 function Light( color, intensity ) {
33343
33344 Object3D.call( this );
33345
33346 this.type = 'Light';
33347
33348 this.color = new Color( color );
33349 this.intensity = intensity !== undefined ? intensity : 1;
33350
33351 this.receiveShadow = undefined;
33352
33353 }
33354
33355 Light.prototype = Object.assign( Object.create( Object3D.prototype ), {
33356
33357 constructor: Light,
33358
33359 isLight: true,
33360
33361 copy: function ( source ) {
33362
33363 Object3D.prototype.copy.call( this, source );
33364
33365 this.color.copy( source.color );
33366 this.intensity = source.intensity;
33367
33368 return this;
33369
33370 },
33371
33372 toJSON: function ( meta ) {
33373
33374 var data = Object3D.prototype.toJSON.call( this, meta );
33375
33376 data.object.color = this.color.getHex();
33377 data.object.intensity = this.intensity;
33378
33379 if ( this.groundColor !== undefined ) data.object.groundColor = this.groundColor.getHex();
33380
33381 if ( this.distance !== undefined ) data.object.distance = this.distance;
33382 if ( this.angle !== undefined ) data.object.angle = this.angle;
33383 if ( this.decay !== undefined ) data.object.decay = this.decay;
33384 if ( this.penumbra !== undefined ) data.object.penumbra = this.penumbra;
33385
33386 if ( this.shadow !== undefined ) data.object.shadow = this.shadow.toJSON();
33387
33388 return data;
33389
33390 }
33391
33392 } );
33393
33394 /**
33395 * @author alteredq / http://alteredqualia.com/
33396 */
33397
33398 function HemisphereLight( skyColor, groundColor, intensity ) {
33399
33400 Light.call( this, skyColor, intensity );
33401
33402 this.type = 'HemisphereLight';
33403
33404 this.castShadow = undefined;
33405
33406 this.position.copy( Object3D.DefaultUp );
33407 this.updateMatrix();
33408
33409 this.groundColor = new Color( groundColor );
33410
33411 }
33412
33413 HemisphereLight.prototype = Object.assign( Object.create( Light.prototype ), {
33414
33415 constructor: HemisphereLight,
33416
33417 isHemisphereLight: true,
33418
33419 copy: function ( source ) {
33420
33421 Light.prototype.copy.call( this, source );
33422
33423 this.groundColor.copy( source.groundColor );
33424
33425 return this;
33426
33427 }
33428
33429 } );
33430
33431 /**
33432 * @author mrdoob / http://mrdoob.com/
33433 */
33434
33435 function LightShadow( camera ) {
33436
33437 this.camera = camera;
33438
33439 this.bias = 0;
33440 this.radius = 1;
33441
33442 this.mapSize = new Vector2( 512, 512 );
33443
33444 this.map = null;
33445 this.matrix = new Matrix4();
33446
33447 }
33448
33449 Object.assign( LightShadow.prototype, {
33450
33451 copy: function ( source ) {
33452
33453 this.camera = source.camera.clone();
33454
33455 this.bias = source.bias;
33456 this.radius = source.radius;
33457
33458 this.mapSize.copy( source.mapSize );
33459
33460 return this;
33461
33462 },
33463
33464 clone: function () {
33465
33466 return new this.constructor().copy( this );
33467
33468 },
33469
33470 toJSON: function () {
33471
33472 var object = {};
33473
33474 if ( this.bias !== 0 ) object.bias = this.bias;
33475 if ( this.radius !== 1 ) object.radius = this.radius;
33476 if ( this.mapSize.x !== 512 || this.mapSize.y !== 512 ) object.mapSize = this.mapSize.toArray();
33477
33478 object.camera = this.camera.toJSON( false ).object;
33479 delete object.camera.matrix;
33480
33481 return object;
33482
33483 }
33484
33485 } );
33486
33487 /**
33488 * @author mrdoob / http://mrdoob.com/
33489 */
33490
33491 function SpotLightShadow() {
33492
33493 LightShadow.call( this, new PerspectiveCamera( 50, 1, 0.5, 500 ) );
33494
33495 }
33496
33497 SpotLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype ), {
33498
33499 constructor: SpotLightShadow,
33500
33501 isSpotLightShadow: true,
33502
33503 update: function ( light ) {
33504
33505 var camera = this.camera;
33506
33507 var fov = _Math.RAD2DEG * 2 * light.angle;
33508 var aspect = this.mapSize.width / this.mapSize.height;
33509 var far = light.distance || camera.far;
33510
33511 if ( fov !== camera.fov || aspect !== camera.aspect || far !== camera.far ) {
33512
33513 camera.fov = fov;
33514 camera.aspect = aspect;
33515 camera.far = far;
33516 camera.updateProjectionMatrix();
33517
33518 }
33519
33520 }
33521
33522 } );
33523
33524 /**
33525 * @author alteredq / http://alteredqualia.com/
33526 */
33527
33528 function SpotLight( color, intensity, distance, angle, penumbra, decay ) {
33529
33530 Light.call( this, color, intensity );
33531
33532 this.type = 'SpotLight';
33533
33534 this.position.copy( Object3D.DefaultUp );
33535 this.updateMatrix();
33536
33537 this.target = new Object3D();
33538
33539 Object.defineProperty( this, 'power', {
33540 get: function () {
33541
33542 // intensity = power per solid angle.
33543 // ref: equation (17) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
33544 return this.intensity * Math.PI;
33545
33546 },
33547 set: function ( power ) {
33548
33549 // intensity = power per solid angle.
33550 // ref: equation (17) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
33551 this.intensity = power / Math.PI;
33552
33553 }
33554 } );
33555
33556 this.distance = ( distance !== undefined ) ? distance : 0;
33557 this.angle = ( angle !== undefined ) ? angle : Math.PI / 3;
33558 this.penumbra = ( penumbra !== undefined ) ? penumbra : 0;
33559 this.decay = ( decay !== undefined ) ? decay : 1; // for physically correct lights, should be 2.
33560
33561 this.shadow = new SpotLightShadow();
33562
33563 }
33564
33565 SpotLight.prototype = Object.assign( Object.create( Light.prototype ), {
33566
33567 constructor: SpotLight,
33568
33569 isSpotLight: true,
33570
33571 copy: function ( source ) {
33572
33573 Light.prototype.copy.call( this, source );
33574
33575 this.distance = source.distance;
33576 this.angle = source.angle;
33577 this.penumbra = source.penumbra;
33578 this.decay = source.decay;
33579
33580 this.target = source.target.clone();
33581
33582 this.shadow = source.shadow.clone();
33583
33584 return this;
33585
33586 }
33587
33588 } );
33589
33590 /**
33591 * @author mrdoob / http://mrdoob.com/
33592 */
33593
33594
33595 function PointLight( color, intensity, distance, decay ) {
33596
33597 Light.call( this, color, intensity );
33598
33599 this.type = 'PointLight';
33600
33601 Object.defineProperty( this, 'power', {
33602 get: function () {
33603
33604 // intensity = power per solid angle.
33605 // ref: equation (15) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
33606 return this.intensity * 4 * Math.PI;
33607
33608 },
33609 set: function ( power ) {
33610
33611 // intensity = power per solid angle.
33612 // ref: equation (15) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
33613 this.intensity = power / ( 4 * Math.PI );
33614
33615 }
33616 } );
33617
33618 this.distance = ( distance !== undefined ) ? distance : 0;
33619 this.decay = ( decay !== undefined ) ? decay : 1; // for physically correct lights, should be 2.
33620
33621 this.shadow = new LightShadow( new PerspectiveCamera( 90, 1, 0.5, 500 ) );
33622
33623 }
33624
33625 PointLight.prototype = Object.assign( Object.create( Light.prototype ), {
33626
33627 constructor: PointLight,
33628
33629 isPointLight: true,
33630
33631 copy: function ( source ) {
33632
33633 Light.prototype.copy.call( this, source );
33634
33635 this.distance = source.distance;
33636 this.decay = source.decay;
33637
33638 this.shadow = source.shadow.clone();
33639
33640 return this;
33641
33642 }
33643
33644 } );
33645
33646 /**
33647 * @author mrdoob / http://mrdoob.com/
33648 */
33649
33650 function DirectionalLightShadow( ) {
33651
33652 LightShadow.call( this, new OrthographicCamera( - 5, 5, 5, - 5, 0.5, 500 ) );
33653
33654 }
33655
33656 DirectionalLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype ), {
33657
33658 constructor: DirectionalLightShadow
33659
33660 } );
33661
33662 /**
33663 * @author mrdoob / http://mrdoob.com/
33664 * @author alteredq / http://alteredqualia.com/
33665 */
33666
33667 function DirectionalLight( color, intensity ) {
33668
33669 Light.call( this, color, intensity );
33670
33671 this.type = 'DirectionalLight';
33672
33673 this.position.copy( Object3D.DefaultUp );
33674 this.updateMatrix();
33675
33676 this.target = new Object3D();
33677
33678 this.shadow = new DirectionalLightShadow();
33679
33680 }
33681
33682 DirectionalLight.prototype = Object.assign( Object.create( Light.prototype ), {
33683
33684 constructor: DirectionalLight,
33685
33686 isDirectionalLight: true,
33687
33688 copy: function ( source ) {
33689
33690 Light.prototype.copy.call( this, source );
33691
33692 this.target = source.target.clone();
33693
33694 this.shadow = source.shadow.clone();
33695
33696 return this;
33697
33698 }
33699
33700 } );
33701
33702 /**
33703 * @author mrdoob / http://mrdoob.com/
33704 */
33705
33706 function AmbientLight( color, intensity ) {
33707
33708 Light.call( this, color, intensity );
33709
33710 this.type = 'AmbientLight';
33711
33712 this.castShadow = undefined;
33713
33714 }
33715
33716 AmbientLight.prototype = Object.assign( Object.create( Light.prototype ), {
33717
33718 constructor: AmbientLight,
33719
33720 isAmbientLight: true
33721
33722 } );
33723
33724 /**
33725 * @author abelnation / http://github.com/abelnation
33726 */
33727
33728 function RectAreaLight( color, intensity, width, height ) {
33729
33730 Light.call( this, color, intensity );
33731
33732 this.type = 'RectAreaLight';
33733
33734 this.width = ( width !== undefined ) ? width : 10;
33735 this.height = ( height !== undefined ) ? height : 10;
33736
33737 }
33738
33739 RectAreaLight.prototype = Object.assign( Object.create( Light.prototype ), {
33740
33741 constructor: RectAreaLight,
33742
33743 isRectAreaLight: true,
33744
33745 copy: function ( source ) {
33746
33747 Light.prototype.copy.call( this, source );
33748
33749 this.width = source.width;
33750 this.height = source.height;
33751
33752 return this;
33753
33754 },
33755
33756 toJSON: function ( meta ) {
33757
33758 var data = Light.prototype.toJSON.call( this, meta );
33759
33760 data.object.width = this.width;
33761 data.object.height = this.height;
33762
33763 return data;
33764
33765 }
33766
33767 } );
33768
33769 /**
33770 *
33771 * A Track that interpolates Strings
33772 *
33773 *
33774 * @author Ben Houston / http://clara.io/
33775 * @author David Sarno / http://lighthaus.us/
33776 * @author tschw
33777 */
33778
33779 function StringKeyframeTrack( name, times, values, interpolation ) {
33780
33781 KeyframeTrack.call( this, name, times, values, interpolation );
33782
33783 }
33784
33785 StringKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
33786
33787 constructor: StringKeyframeTrack,
33788
33789 ValueTypeName: 'string',
33790 ValueBufferType: Array,
33791
33792 DefaultInterpolation: InterpolateDiscrete,
33793
33794 InterpolantFactoryMethodLinear: undefined,
33795
33796 InterpolantFactoryMethodSmooth: undefined
33797
33798 } );
33799
33800 /**
33801 *
33802 * A Track of Boolean keyframe values.
33803 *
33804 *
33805 * @author Ben Houston / http://clara.io/
33806 * @author David Sarno / http://lighthaus.us/
33807 * @author tschw
33808 */
33809
33810 function BooleanKeyframeTrack( name, times, values ) {
33811
33812 KeyframeTrack.call( this, name, times, values );
33813
33814 }
33815
33816 BooleanKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
33817
33818 constructor: BooleanKeyframeTrack,
33819
33820 ValueTypeName: 'bool',
33821 ValueBufferType: Array,
33822
33823 DefaultInterpolation: InterpolateDiscrete,
33824
33825 InterpolantFactoryMethodLinear: undefined,
33826 InterpolantFactoryMethodSmooth: undefined
33827
33828 // Note: Actually this track could have a optimized / compressed
33829 // representation of a single value and a custom interpolant that
33830 // computes "firstValue ^ isOdd( index )".
33831
33832 } );
33833
33834 /**
33835 * Abstract base class of interpolants over parametric samples.
33836 *
33837 * The parameter domain is one dimensional, typically the time or a path
33838 * along a curve defined by the data.
33839 *
33840 * The sample values can have any dimensionality and derived classes may
33841 * apply special interpretations to the data.
33842 *
33843 * This class provides the interval seek in a Template Method, deferring
33844 * the actual interpolation to derived classes.
33845 *
33846 * Time complexity is O(1) for linear access crossing at most two points
33847 * and O(log N) for random access, where N is the number of positions.
33848 *
33849 * References:
33850 *
33851 * http://www.oodesign.com/template-method-pattern.html
33852 *
33853 * @author tschw
33854 */
33855
33856 function Interpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
33857
33858 this.parameterPositions = parameterPositions;
33859 this._cachedIndex = 0;
33860
33861 this.resultBuffer = resultBuffer !== undefined ?
33862 resultBuffer : new sampleValues.constructor( sampleSize );
33863 this.sampleValues = sampleValues;
33864 this.valueSize = sampleSize;
33865
33866 }
33867
33868 Object.assign( Interpolant.prototype, {
33869
33870 evaluate: function ( t ) {
33871
33872 var pp = this.parameterPositions,
33873 i1 = this._cachedIndex,
33874
33875 t1 = pp[ i1 ],
33876 t0 = pp[ i1 - 1 ];
33877
33878 validate_interval: {
33879
33880 seek: {
33881
33882 var right;
33883
33884 linear_scan: {
33885
33886 //- See http://jsperf.com/comparison-to-undefined/3
33887 //- slower code:
33888 //-
33889 //- if ( t >= t1 || t1 === undefined ) {
33890 forward_scan: if ( ! ( t < t1 ) ) {
33891
33892 for ( var giveUpAt = i1 + 2; ; ) {
33893
33894 if ( t1 === undefined ) {
33895
33896 if ( t < t0 ) break forward_scan;
33897
33898 // after end
33899
33900 i1 = pp.length;
33901 this._cachedIndex = i1;
33902 return this.afterEnd_( i1 - 1, t, t0 );
33903
33904 }
33905
33906 if ( i1 === giveUpAt ) break; // this loop
33907
33908 t0 = t1;
33909 t1 = pp[ ++ i1 ];
33910
33911 if ( t < t1 ) {
33912
33913 // we have arrived at the sought interval
33914 break seek;
33915
33916 }
33917
33918 }
33919
33920 // prepare binary search on the right side of the index
33921 right = pp.length;
33922 break linear_scan;
33923
33924 }
33925
33926 //- slower code:
33927 //- if ( t < t0 || t0 === undefined ) {
33928 if ( ! ( t >= t0 ) ) {
33929
33930 // looping?
33931
33932 var t1global = pp[ 1 ];
33933
33934 if ( t < t1global ) {
33935
33936 i1 = 2; // + 1, using the scan for the details
33937 t0 = t1global;
33938
33939 }
33940
33941 // linear reverse scan
33942
33943 for ( var giveUpAt = i1 - 2; ; ) {
33944
33945 if ( t0 === undefined ) {
33946
33947 // before start
33948
33949 this._cachedIndex = 0;
33950 return this.beforeStart_( 0, t, t1 );
33951
33952 }
33953
33954 if ( i1 === giveUpAt ) break; // this loop
33955
33956 t1 = t0;
33957 t0 = pp[ -- i1 - 1 ];
33958
33959 if ( t >= t0 ) {
33960
33961 // we have arrived at the sought interval
33962 break seek;
33963
33964 }
33965
33966 }
33967
33968 // prepare binary search on the left side of the index
33969 right = i1;
33970 i1 = 0;
33971 break linear_scan;
33972
33973 }
33974
33975 // the interval is valid
33976
33977 break validate_interval;
33978
33979 } // linear scan
33980
33981 // binary search
33982
33983 while ( i1 < right ) {
33984
33985 var mid = ( i1 + right ) >>> 1;
33986
33987 if ( t < pp[ mid ] ) {
33988
33989 right = mid;
33990
33991 } else {
33992
33993 i1 = mid + 1;
33994
33995 }
33996
33997 }
33998
33999 t1 = pp[ i1 ];
34000 t0 = pp[ i1 - 1 ];
34001
34002 // check boundary cases, again
34003
34004 if ( t0 === undefined ) {
34005
34006 this._cachedIndex = 0;
34007 return this.beforeStart_( 0, t, t1 );
34008
34009 }
34010
34011 if ( t1 === undefined ) {
34012
34013 i1 = pp.length;
34014 this._cachedIndex = i1;
34015 return this.afterEnd_( i1 - 1, t0, t );
34016
34017 }
34018
34019 } // seek
34020
34021 this._cachedIndex = i1;
34022
34023 this.intervalChanged_( i1, t0, t1 );
34024
34025 } // validate_interval
34026
34027 return this.interpolate_( i1, t0, t, t1 );
34028
34029 },
34030
34031 settings: null, // optional, subclass-specific settings structure
34032 // Note: The indirection allows central control of many interpolants.
34033
34034 // --- Protected interface
34035
34036 DefaultSettings_: {},
34037
34038 getSettings_: function () {
34039
34040 return this.settings || this.DefaultSettings_;
34041
34042 },
34043
34044 copySampleValue_: function ( index ) {
34045
34046 // copies a sample value to the result buffer
34047
34048 var result = this.resultBuffer,
34049 values = this.sampleValues,
34050 stride = this.valueSize,
34051 offset = index * stride;
34052
34053 for ( var i = 0; i !== stride; ++ i ) {
34054
34055 result[ i ] = values[ offset + i ];
34056
34057 }
34058
34059 return result;
34060
34061 },
34062
34063 // Template methods for derived classes:
34064
34065 interpolate_: function ( /* i1, t0, t, t1 */ ) {
34066
34067 throw new Error( 'call to abstract method' );
34068 // implementations shall return this.resultBuffer
34069
34070 },
34071
34072 intervalChanged_: function ( /* i1, t0, t1 */ ) {
34073
34074 // empty
34075
34076 }
34077
34078 } );
34079
34080 //!\ DECLARE ALIAS AFTER assign prototype !
34081 Object.assign( Interpolant.prototype, {
34082
34083 //( 0, t, t0 ), returns this.resultBuffer
34084 beforeStart_: Interpolant.prototype.copySampleValue_,
34085
34086 //( N-1, tN-1, t ), returns this.resultBuffer
34087 afterEnd_: Interpolant.prototype.copySampleValue_,
34088
34089 } );
34090
34091 /**
34092 * Spherical linear unit quaternion interpolant.
34093 *
34094 * @author tschw
34095 */
34096
34097 function QuaternionLinearInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
34098
34099 Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );
34100
34101 }
34102
34103 QuaternionLinearInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {
34104
34105 constructor: QuaternionLinearInterpolant,
34106
34107 interpolate_: function ( i1, t0, t, t1 ) {
34108
34109 var result = this.resultBuffer,
34110 values = this.sampleValues,
34111 stride = this.valueSize,
34112
34113 offset = i1 * stride,
34114
34115 alpha = ( t - t0 ) / ( t1 - t0 );
34116
34117 for ( var end = offset + stride; offset !== end; offset += 4 ) {
34118
34119 Quaternion.slerpFlat( result, 0, values, offset - stride, values, offset, alpha );
34120
34121 }
34122
34123 return result;
34124
34125 }
34126
34127 } );
34128
34129 /**
34130 *
34131 * A Track of quaternion keyframe values.
34132 *
34133 * @author Ben Houston / http://clara.io/
34134 * @author David Sarno / http://lighthaus.us/
34135 * @author tschw
34136 */
34137
34138 function QuaternionKeyframeTrack( name, times, values, interpolation ) {
34139
34140 KeyframeTrack.call( this, name, times, values, interpolation );
34141
34142 }
34143
34144 QuaternionKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
34145
34146 constructor: QuaternionKeyframeTrack,
34147
34148 ValueTypeName: 'quaternion',
34149
34150 // ValueBufferType is inherited
34151
34152 DefaultInterpolation: InterpolateLinear,
34153
34154 InterpolantFactoryMethodLinear: function ( result ) {
34155
34156 return new QuaternionLinearInterpolant( this.times, this.values, this.getValueSize(), result );
34157
34158 },
34159
34160 InterpolantFactoryMethodSmooth: undefined // not yet implemented
34161
34162 } );
34163
34164 /**
34165 *
34166 * A Track of keyframe values that represent color.
34167 *
34168 *
34169 * @author Ben Houston / http://clara.io/
34170 * @author David Sarno / http://lighthaus.us/
34171 * @author tschw
34172 */
34173
34174 function ColorKeyframeTrack( name, times, values, interpolation ) {
34175
34176 KeyframeTrack.call( this, name, times, values, interpolation );
34177
34178 }
34179
34180 ColorKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
34181
34182 constructor: ColorKeyframeTrack,
34183
34184 ValueTypeName: 'color'
34185
34186 // ValueBufferType is inherited
34187
34188 // DefaultInterpolation is inherited
34189
34190 // Note: Very basic implementation and nothing special yet.
34191 // However, this is the place for color space parameterization.
34192
34193 } );
34194
34195 /**
34196 *
34197 * A Track of numeric keyframe values.
34198 *
34199 * @author Ben Houston / http://clara.io/
34200 * @author David Sarno / http://lighthaus.us/
34201 * @author tschw
34202 */
34203
34204 function NumberKeyframeTrack( name, times, values, interpolation ) {
34205
34206 KeyframeTrack.call( this, name, times, values, interpolation );
34207
34208 }
34209
34210 NumberKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
34211
34212 constructor: NumberKeyframeTrack,
34213
34214 ValueTypeName: 'number'
34215
34216 // ValueBufferType is inherited
34217
34218 // DefaultInterpolation is inherited
34219
34220 } );
34221
34222 /**
34223 * Fast and simple cubic spline interpolant.
34224 *
34225 * It was derived from a Hermitian construction setting the first derivative
34226 * at each sample position to the linear slope between neighboring positions
34227 * over their parameter interval.
34228 *
34229 * @author tschw
34230 */
34231
34232 function CubicInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
34233
34234 Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );
34235
34236 this._weightPrev = - 0;
34237 this._offsetPrev = - 0;
34238 this._weightNext = - 0;
34239 this._offsetNext = - 0;
34240
34241 }
34242
34243 CubicInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {
34244
34245 constructor: CubicInterpolant,
34246
34247 DefaultSettings_: {
34248
34249 endingStart: ZeroCurvatureEnding,
34250 endingEnd: ZeroCurvatureEnding
34251
34252 },
34253
34254 intervalChanged_: function ( i1, t0, t1 ) {
34255
34256 var pp = this.parameterPositions,
34257 iPrev = i1 - 2,
34258 iNext = i1 + 1,
34259
34260 tPrev = pp[ iPrev ],
34261 tNext = pp[ iNext ];
34262
34263 if ( tPrev === undefined ) {
34264
34265 switch ( this.getSettings_().endingStart ) {
34266
34267 case ZeroSlopeEnding:
34268
34269 // f'(t0) = 0
34270 iPrev = i1;
34271 tPrev = 2 * t0 - t1;
34272
34273 break;
34274
34275 case WrapAroundEnding:
34276
34277 // use the other end of the curve
34278 iPrev = pp.length - 2;
34279 tPrev = t0 + pp[ iPrev ] - pp[ iPrev + 1 ];
34280
34281 break;
34282
34283 default: // ZeroCurvatureEnding
34284
34285 // f''(t0) = 0 a.k.a. Natural Spline
34286 iPrev = i1;
34287 tPrev = t1;
34288
34289 }
34290
34291 }
34292
34293 if ( tNext === undefined ) {
34294
34295 switch ( this.getSettings_().endingEnd ) {
34296
34297 case ZeroSlopeEnding:
34298
34299 // f'(tN) = 0
34300 iNext = i1;
34301 tNext = 2 * t1 - t0;
34302
34303 break;
34304
34305 case WrapAroundEnding:
34306
34307 // use the other end of the curve
34308 iNext = 1;
34309 tNext = t1 + pp[ 1 ] - pp[ 0 ];
34310
34311 break;
34312
34313 default: // ZeroCurvatureEnding
34314
34315 // f''(tN) = 0, a.k.a. Natural Spline
34316 iNext = i1 - 1;
34317 tNext = t0;
34318
34319 }
34320
34321 }
34322
34323 var halfDt = ( t1 - t0 ) * 0.5,
34324 stride = this.valueSize;
34325
34326 this._weightPrev = halfDt / ( t0 - tPrev );
34327 this._weightNext = halfDt / ( tNext - t1 );
34328 this._offsetPrev = iPrev * stride;
34329 this._offsetNext = iNext * stride;
34330
34331 },
34332
34333 interpolate_: function ( i1, t0, t, t1 ) {
34334
34335 var result = this.resultBuffer,
34336 values = this.sampleValues,
34337 stride = this.valueSize,
34338
34339 o1 = i1 * stride, o0 = o1 - stride,
34340 oP = this._offsetPrev, oN = this._offsetNext,
34341 wP = this._weightPrev, wN = this._weightNext,
34342
34343 p = ( t - t0 ) / ( t1 - t0 ),
34344 pp = p * p,
34345 ppp = pp * p;
34346
34347 // evaluate polynomials
34348
34349 var sP = - wP * ppp + 2 * wP * pp - wP * p;
34350 var s0 = ( 1 + wP ) * ppp + ( - 1.5 - 2 * wP ) * pp + ( - 0.5 + wP ) * p + 1;
34351 var s1 = ( - 1 - wN ) * ppp + ( 1.5 + wN ) * pp + 0.5 * p;
34352 var sN = wN * ppp - wN * pp;
34353
34354 // combine data linearly
34355
34356 for ( var i = 0; i !== stride; ++ i ) {
34357
34358 result[ i ] =
34359 sP * values[ oP + i ] +
34360 s0 * values[ o0 + i ] +
34361 s1 * values[ o1 + i ] +
34362 sN * values[ oN + i ];
34363
34364 }
34365
34366 return result;
34367
34368 }
34369
34370 } );
34371
34372 /**
34373 * @author tschw
34374 */
34375
34376 function LinearInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
34377
34378 Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );
34379
34380 }
34381
34382 LinearInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {
34383
34384 constructor: LinearInterpolant,
34385
34386 interpolate_: function ( i1, t0, t, t1 ) {
34387
34388 var result = this.resultBuffer,
34389 values = this.sampleValues,
34390 stride = this.valueSize,
34391
34392 offset1 = i1 * stride,
34393 offset0 = offset1 - stride,
34394
34395 weight1 = ( t - t0 ) / ( t1 - t0 ),
34396 weight0 = 1 - weight1;
34397
34398 for ( var i = 0; i !== stride; ++ i ) {
34399
34400 result[ i ] =
34401 values[ offset0 + i ] * weight0 +
34402 values[ offset1 + i ] * weight1;
34403
34404 }
34405
34406 return result;
34407
34408 }
34409
34410 } );
34411
34412 /**
34413 *
34414 * Interpolant that evaluates to the sample value at the position preceeding
34415 * the parameter.
34416 *
34417 * @author tschw
34418 */
34419
34420 function DiscreteInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
34421
34422 Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );
34423
34424 }
34425
34426 DiscreteInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {
34427
34428 constructor: DiscreteInterpolant,
34429
34430 interpolate_: function ( i1 /*, t0, t, t1 */ ) {
34431
34432 return this.copySampleValue_( i1 - 1 );
34433
34434 }
34435
34436 } );
34437
34438 /**
34439 * @author tschw
34440 * @author Ben Houston / http://clara.io/
34441 * @author David Sarno / http://lighthaus.us/
34442 */
34443
34444 var AnimationUtils = {
34445
34446 // same as Array.prototype.slice, but also works on typed arrays
34447 arraySlice: function ( array, from, to ) {
34448
34449 if ( AnimationUtils.isTypedArray( array ) ) {
34450
34451 // in ios9 array.subarray(from, undefined) will return empty array
34452 // but array.subarray(from) or array.subarray(from, len) is correct
34453 return new array.constructor( array.subarray( from, to !== undefined ? to : array.length ) );
34454
34455 }
34456
34457 return array.slice( from, to );
34458
34459 },
34460
34461 // converts an array to a specific type
34462 convertArray: function ( array, type, forceClone ) {
34463
34464 if ( ! array || // let 'undefined' and 'null' pass
34465 ! forceClone && array.constructor === type ) return array;
34466
34467 if ( typeof type.BYTES_PER_ELEMENT === 'number' ) {
34468
34469 return new type( array ); // create typed array
34470
34471 }
34472
34473 return Array.prototype.slice.call( array ); // create Array
34474
34475 },
34476
34477 isTypedArray: function ( object ) {
34478
34479 return ArrayBuffer.isView( object ) &&
34480 ! ( object instanceof DataView );
34481
34482 },
34483
34484 // returns an array by which times and values can be sorted
34485 getKeyframeOrder: function ( times ) {
34486
34487 function compareTime( i, j ) {
34488
34489 return times[ i ] - times[ j ];
34490
34491 }
34492
34493 var n = times.length;
34494 var result = new Array( n );
34495 for ( var i = 0; i !== n; ++ i ) result[ i ] = i;
34496
34497 result.sort( compareTime );
34498
34499 return result;
34500
34501 },
34502
34503 // uses the array previously returned by 'getKeyframeOrder' to sort data
34504 sortedArray: function ( values, stride, order ) {
34505
34506 var nValues = values.length;
34507 var result = new values.constructor( nValues );
34508
34509 for ( var i = 0, dstOffset = 0; dstOffset !== nValues; ++ i ) {
34510
34511 var srcOffset = order[ i ] * stride;
34512
34513 for ( var j = 0; j !== stride; ++ j ) {
34514
34515 result[ dstOffset ++ ] = values[ srcOffset + j ];
34516
34517 }
34518
34519 }
34520
34521 return result;
34522
34523 },
34524
34525 // function for parsing AOS keyframe formats
34526 flattenJSON: function ( jsonKeys, times, values, valuePropertyName ) {
34527
34528 var i = 1, key = jsonKeys[ 0 ];
34529
34530 while ( key !== undefined && key[ valuePropertyName ] === undefined ) {
34531
34532 key = jsonKeys[ i ++ ];
34533
34534 }
34535
34536 if ( key === undefined ) return; // no data
34537
34538 var value = key[ valuePropertyName ];
34539 if ( value === undefined ) return; // no data
34540
34541 if ( Array.isArray( value ) ) {
34542
34543 do {
34544
34545 value = key[ valuePropertyName ];
34546
34547 if ( value !== undefined ) {
34548
34549 times.push( key.time );
34550 values.push.apply( values, value ); // push all elements
34551
34552 }
34553
34554 key = jsonKeys[ i ++ ];
34555
34556 } while ( key !== undefined );
34557
34558 } else if ( value.toArray !== undefined ) {
34559
34560 // ...assume THREE.Math-ish
34561
34562 do {
34563
34564 value = key[ valuePropertyName ];
34565
34566 if ( value !== undefined ) {
34567
34568 times.push( key.time );
34569 value.toArray( values, values.length );
34570
34571 }
34572
34573 key = jsonKeys[ i ++ ];
34574
34575 } while ( key !== undefined );
34576
34577 } else {
34578
34579 // otherwise push as-is
34580
34581 do {
34582
34583 value = key[ valuePropertyName ];
34584
34585 if ( value !== undefined ) {
34586
34587 times.push( key.time );
34588 values.push( value );
34589
34590 }
34591
34592 key = jsonKeys[ i ++ ];
34593
34594 } while ( key !== undefined );
34595
34596 }
34597
34598 }
34599
34600 };
34601
34602 /**
34603 *
34604 * A timed sequence of keyframes for a specific property.
34605 *
34606 *
34607 * @author Ben Houston / http://clara.io/
34608 * @author David Sarno / http://lighthaus.us/
34609 * @author tschw
34610 */
34611
34612 function KeyframeTrack( name, times, values, interpolation ) {
34613
34614 if ( name === undefined ) throw new Error( 'THREE.KeyframeTrack: track name is undefined' );
34615 if ( times === undefined || times.length === 0 ) throw new Error( 'THREE.KeyframeTrack: no keyframes in track named ' + name );
34616
34617 this.name = name;
34618
34619 this.times = AnimationUtils.convertArray( times, this.TimeBufferType );
34620 this.values = AnimationUtils.convertArray( values, this.ValueBufferType );
34621
34622 this.setInterpolation( interpolation || this.DefaultInterpolation );
34623
34624 this.validate();
34625 this.optimize();
34626
34627 }
34628
34629 // Static methods:
34630
34631 Object.assign( KeyframeTrack, {
34632
34633 // Serialization (in static context, because of constructor invocation
34634 // and automatic invocation of .toJSON):
34635
34636 parse: function ( json ) {
34637
34638 if ( json.type === undefined ) {
34639
34640 throw new Error( 'THREE.KeyframeTrack: track type undefined, can not parse' );
34641
34642 }
34643
34644 var trackType = KeyframeTrack._getTrackTypeForValueTypeName( json.type );
34645
34646 if ( json.times === undefined ) {
34647
34648 var times = [], values = [];
34649
34650 AnimationUtils.flattenJSON( json.keys, times, values, 'value' );
34651
34652 json.times = times;
34653 json.values = values;
34654
34655 }
34656
34657 // derived classes can define a static parse method
34658 if ( trackType.parse !== undefined ) {
34659
34660 return trackType.parse( json );
34661
34662 } else {
34663
34664 // by default, we assume a constructor compatible with the base
34665 return new trackType( json.name, json.times, json.values, json.interpolation );
34666
34667 }
34668
34669 },
34670
34671 toJSON: function ( track ) {
34672
34673 var trackType = track.constructor;
34674
34675 var json;
34676
34677 // derived classes can define a static toJSON method
34678 if ( trackType.toJSON !== undefined ) {
34679
34680 json = trackType.toJSON( track );
34681
34682 } else {
34683
34684 // by default, we assume the data can be serialized as-is
34685 json = {
34686
34687 'name': track.name,
34688 'times': AnimationUtils.convertArray( track.times, Array ),
34689 'values': AnimationUtils.convertArray( track.values, Array )
34690
34691 };
34692
34693 var interpolation = track.getInterpolation();
34694
34695 if ( interpolation !== track.DefaultInterpolation ) {
34696
34697 json.interpolation = interpolation;
34698
34699 }
34700
34701 }
34702
34703 json.type = track.ValueTypeName; // mandatory
34704
34705 return json;
34706
34707 },
34708
34709 _getTrackTypeForValueTypeName: function ( typeName ) {
34710
34711 switch ( typeName.toLowerCase() ) {
34712
34713 case 'scalar':
34714 case 'double':
34715 case 'float':
34716 case 'number':
34717 case 'integer':
34718
34719 return NumberKeyframeTrack;
34720
34721 case 'vector':
34722 case 'vector2':
34723 case 'vector3':
34724 case 'vector4':
34725
34726 return VectorKeyframeTrack;
34727
34728 case 'color':
34729
34730 return ColorKeyframeTrack;
34731
34732 case 'quaternion':
34733
34734 return QuaternionKeyframeTrack;
34735
34736 case 'bool':
34737 case 'boolean':
34738
34739 return BooleanKeyframeTrack;
34740
34741 case 'string':
34742
34743 return StringKeyframeTrack;
34744
34745 }
34746
34747 throw new Error( 'THREE.KeyframeTrack: Unsupported typeName: ' + typeName );
34748
34749 }
34750
34751 } );
34752
34753 Object.assign( KeyframeTrack.prototype, {
34754
34755 constructor: KeyframeTrack,
34756
34757 TimeBufferType: Float32Array,
34758
34759 ValueBufferType: Float32Array,
34760
34761 DefaultInterpolation: InterpolateLinear,
34762
34763 InterpolantFactoryMethodDiscrete: function ( result ) {
34764
34765 return new DiscreteInterpolant( this.times, this.values, this.getValueSize(), result );
34766
34767 },
34768
34769 InterpolantFactoryMethodLinear: function ( result ) {
34770
34771 return new LinearInterpolant( this.times, this.values, this.getValueSize(), result );
34772
34773 },
34774
34775 InterpolantFactoryMethodSmooth: function ( result ) {
34776
34777 return new CubicInterpolant( this.times, this.values, this.getValueSize(), result );
34778
34779 },
34780
34781 setInterpolation: function ( interpolation ) {
34782
34783 var factoryMethod;
34784
34785 switch ( interpolation ) {
34786
34787 case InterpolateDiscrete:
34788
34789 factoryMethod = this.InterpolantFactoryMethodDiscrete;
34790
34791 break;
34792
34793 case InterpolateLinear:
34794
34795 factoryMethod = this.InterpolantFactoryMethodLinear;
34796
34797 break;
34798
34799 case InterpolateSmooth:
34800
34801 factoryMethod = this.InterpolantFactoryMethodSmooth;
34802
34803 break;
34804
34805 }
34806
34807 if ( factoryMethod === undefined ) {
34808
34809 var message = "unsupported interpolation for " +
34810 this.ValueTypeName + " keyframe track named " + this.name;
34811
34812 if ( this.createInterpolant === undefined ) {
34813
34814 // fall back to default, unless the default itself is messed up
34815 if ( interpolation !== this.DefaultInterpolation ) {
34816
34817 this.setInterpolation( this.DefaultInterpolation );
34818
34819 } else {
34820
34821 throw new Error( message ); // fatal, in this case
34822
34823 }
34824
34825 }
34826
34827 console.warn( 'THREE.KeyframeTrack:', message );
34828 return;
34829
34830 }
34831
34832 this.createInterpolant = factoryMethod;
34833
34834 },
34835
34836 getInterpolation: function () {
34837
34838 switch ( this.createInterpolant ) {
34839
34840 case this.InterpolantFactoryMethodDiscrete:
34841
34842 return InterpolateDiscrete;
34843
34844 case this.InterpolantFactoryMethodLinear:
34845
34846 return InterpolateLinear;
34847
34848 case this.InterpolantFactoryMethodSmooth:
34849
34850 return InterpolateSmooth;
34851
34852 }
34853
34854 },
34855
34856 getValueSize: function () {
34857
34858 return this.values.length / this.times.length;
34859
34860 },
34861
34862 // move all keyframes either forwards or backwards in time
34863 shift: function ( timeOffset ) {
34864
34865 if ( timeOffset !== 0.0 ) {
34866
34867 var times = this.times;
34868
34869 for ( var i = 0, n = times.length; i !== n; ++ i ) {
34870
34871 times[ i ] += timeOffset;
34872
34873 }
34874
34875 }
34876
34877 return this;
34878
34879 },
34880
34881 // scale all keyframe times by a factor (useful for frame <-> seconds conversions)
34882 scale: function ( timeScale ) {
34883
34884 if ( timeScale !== 1.0 ) {
34885
34886 var times = this.times;
34887
34888 for ( var i = 0, n = times.length; i !== n; ++ i ) {
34889
34890 times[ i ] *= timeScale;
34891
34892 }
34893
34894 }
34895
34896 return this;
34897
34898 },
34899
34900 // removes keyframes before and after animation without changing any values within the range [startTime, endTime].
34901 // IMPORTANT: We do not shift around keys to the start of the track time, because for interpolated keys this will change their values
34902 trim: function ( startTime, endTime ) {
34903
34904 var times = this.times,
34905 nKeys = times.length,
34906 from = 0,
34907 to = nKeys - 1;
34908
34909 while ( from !== nKeys && times[ from ] < startTime ) {
34910
34911 ++ from;
34912
34913 }
34914
34915 while ( to !== - 1 && times[ to ] > endTime ) {
34916
34917 -- to;
34918
34919 }
34920
34921 ++ to; // inclusive -> exclusive bound
34922
34923 if ( from !== 0 || to !== nKeys ) {
34924
34925 // empty tracks are forbidden, so keep at least one keyframe
34926 if ( from >= to ) to = Math.max( to, 1 ), from = to - 1;
34927
34928 var stride = this.getValueSize();
34929 this.times = AnimationUtils.arraySlice( times, from, to );
34930 this.values = AnimationUtils.arraySlice( this.values, from * stride, to * stride );
34931
34932 }
34933
34934 return this;
34935
34936 },
34937
34938 // ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable
34939 validate: function () {
34940
34941 var valid = true;
34942
34943 var valueSize = this.getValueSize();
34944 if ( valueSize - Math.floor( valueSize ) !== 0 ) {
34945
34946 console.error( 'THREE.KeyframeTrack: Invalid value size in track.', this );
34947 valid = false;
34948
34949 }
34950
34951 var times = this.times,
34952 values = this.values,
34953
34954 nKeys = times.length;
34955
34956 if ( nKeys === 0 ) {
34957
34958 console.error( 'THREE.KeyframeTrack: Track is empty.', this );
34959 valid = false;
34960
34961 }
34962
34963 var prevTime = null;
34964
34965 for ( var i = 0; i !== nKeys; i ++ ) {
34966
34967 var currTime = times[ i ];
34968
34969 if ( typeof currTime === 'number' && isNaN( currTime ) ) {
34970
34971 console.error( 'THREE.KeyframeTrack: Time is not a valid number.', this, i, currTime );
34972 valid = false;
34973 break;
34974
34975 }
34976
34977 if ( prevTime !== null && prevTime > currTime ) {
34978
34979 console.error( 'THREE.KeyframeTrack: Out of order keys.', this, i, currTime, prevTime );
34980 valid = false;
34981 break;
34982
34983 }
34984
34985 prevTime = currTime;
34986
34987 }
34988
34989 if ( values !== undefined ) {
34990
34991 if ( AnimationUtils.isTypedArray( values ) ) {
34992
34993 for ( var i = 0, n = values.length; i !== n; ++ i ) {
34994
34995 var value = values[ i ];
34996
34997 if ( isNaN( value ) ) {
34998
34999 console.error( 'THREE.KeyframeTrack: Value is not a valid number.', this, i, value );
35000 valid = false;
35001 break;
35002
35003 }
35004
35005 }
35006
35007 }
35008
35009 }
35010
35011 return valid;
35012
35013 },
35014
35015 // removes equivalent sequential keys as common in morph target sequences
35016 // (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0)
35017 optimize: function () {
35018
35019 var times = this.times,
35020 values = this.values,
35021 stride = this.getValueSize(),
35022
35023 smoothInterpolation = this.getInterpolation() === InterpolateSmooth,
35024
35025 writeIndex = 1,
35026 lastIndex = times.length - 1;
35027
35028 for ( var i = 1; i < lastIndex; ++ i ) {
35029
35030 var keep = false;
35031
35032 var time = times[ i ];
35033 var timeNext = times[ i + 1 ];
35034
35035 // remove adjacent keyframes scheduled at the same time
35036
35037 if ( time !== timeNext && ( i !== 1 || time !== time[ 0 ] ) ) {
35038
35039 if ( ! smoothInterpolation ) {
35040
35041 // remove unnecessary keyframes same as their neighbors
35042
35043 var offset = i * stride,
35044 offsetP = offset - stride,
35045 offsetN = offset + stride;
35046
35047 for ( var j = 0; j !== stride; ++ j ) {
35048
35049 var value = values[ offset + j ];
35050
35051 if ( value !== values[ offsetP + j ] ||
35052 value !== values[ offsetN + j ] ) {
35053
35054 keep = true;
35055 break;
35056
35057 }
35058
35059 }
35060
35061 } else {
35062
35063 keep = true;
35064
35065 }
35066
35067 }
35068
35069 // in-place compaction
35070
35071 if ( keep ) {
35072
35073 if ( i !== writeIndex ) {
35074
35075 times[ writeIndex ] = times[ i ];
35076
35077 var readOffset = i * stride,
35078 writeOffset = writeIndex * stride;
35079
35080 for ( var j = 0; j !== stride; ++ j ) {
35081
35082 values[ writeOffset + j ] = values[ readOffset + j ];
35083
35084 }
35085
35086 }
35087
35088 ++ writeIndex;
35089
35090 }
35091
35092 }
35093
35094 // flush last keyframe (compaction looks ahead)
35095
35096 if ( lastIndex > 0 ) {
35097
35098 times[ writeIndex ] = times[ lastIndex ];
35099
35100 for ( var readOffset = lastIndex * stride, writeOffset = writeIndex * stride, j = 0; j !== stride; ++ j ) {
35101
35102 values[ writeOffset + j ] = values[ readOffset + j ];
35103
35104 }
35105
35106 ++ writeIndex;
35107
35108 }
35109
35110 if ( writeIndex !== times.length ) {
35111
35112 this.times = AnimationUtils.arraySlice( times, 0, writeIndex );
35113 this.values = AnimationUtils.arraySlice( values, 0, writeIndex * stride );
35114
35115 }
35116
35117 return this;
35118
35119 }
35120
35121 } );
35122
35123 /**
35124 *
35125 * A Track of vectored keyframe values.
35126 *
35127 *
35128 * @author Ben Houston / http://clara.io/
35129 * @author David Sarno / http://lighthaus.us/
35130 * @author tschw
35131 */
35132
35133 function VectorKeyframeTrack( name, times, values, interpolation ) {
35134
35135 KeyframeTrack.call( this, name, times, values, interpolation );
35136
35137 }
35138
35139 VectorKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
35140
35141 constructor: VectorKeyframeTrack,
35142
35143 ValueTypeName: 'vector'
35144
35145 // ValueBufferType is inherited
35146
35147 // DefaultInterpolation is inherited
35148
35149 } );
35150
35151 /**
35152 *
35153 * Reusable set of Tracks that represent an animation.
35154 *
35155 * @author Ben Houston / http://clara.io/
35156 * @author David Sarno / http://lighthaus.us/
35157 */
35158
35159 function AnimationClip( name, duration, tracks ) {
35160
35161 this.name = name;
35162 this.tracks = tracks;
35163 this.duration = ( duration !== undefined ) ? duration : - 1;
35164
35165 this.uuid = _Math.generateUUID();
35166
35167 // this means it should figure out its duration by scanning the tracks
35168 if ( this.duration < 0 ) {
35169
35170 this.resetDuration();
35171
35172 }
35173
35174 this.optimize();
35175
35176 }
35177
35178 Object.assign( AnimationClip, {
35179
35180 parse: function ( json ) {
35181
35182 var tracks = [],
35183 jsonTracks = json.tracks,
35184 frameTime = 1.0 / ( json.fps || 1.0 );
35185
35186 for ( var i = 0, n = jsonTracks.length; i !== n; ++ i ) {
35187
35188 tracks.push( KeyframeTrack.parse( jsonTracks[ i ] ).scale( frameTime ) );
35189
35190 }
35191
35192 return new AnimationClip( json.name, json.duration, tracks );
35193
35194 },
35195
35196 toJSON: function ( clip ) {
35197
35198 var tracks = [],
35199 clipTracks = clip.tracks;
35200
35201 var json = {
35202
35203 'name': clip.name,
35204 'duration': clip.duration,
35205 'tracks': tracks
35206
35207 };
35208
35209 for ( var i = 0, n = clipTracks.length; i !== n; ++ i ) {
35210
35211 tracks.push( KeyframeTrack.toJSON( clipTracks[ i ] ) );
35212
35213 }
35214
35215 return json;
35216
35217 },
35218
35219 CreateFromMorphTargetSequence: function ( name, morphTargetSequence, fps, noLoop ) {
35220
35221 var numMorphTargets = morphTargetSequence.length;
35222 var tracks = [];
35223
35224 for ( var i = 0; i < numMorphTargets; i ++ ) {
35225
35226 var times = [];
35227 var values = [];
35228
35229 times.push(
35230 ( i + numMorphTargets - 1 ) % numMorphTargets,
35231 i,
35232 ( i + 1 ) % numMorphTargets );
35233
35234 values.push( 0, 1, 0 );
35235
35236 var order = AnimationUtils.getKeyframeOrder( times );
35237 times = AnimationUtils.sortedArray( times, 1, order );
35238 values = AnimationUtils.sortedArray( values, 1, order );
35239
35240 // if there is a key at the first frame, duplicate it as the
35241 // last frame as well for perfect loop.
35242 if ( ! noLoop && times[ 0 ] === 0 ) {
35243
35244 times.push( numMorphTargets );
35245 values.push( values[ 0 ] );
35246
35247 }
35248
35249 tracks.push(
35250 new NumberKeyframeTrack(
35251 '.morphTargetInfluences[' + morphTargetSequence[ i ].name + ']',
35252 times, values
35253 ).scale( 1.0 / fps ) );
35254
35255 }
35256
35257 return new AnimationClip( name, - 1, tracks );
35258
35259 },
35260
35261 findByName: function ( objectOrClipArray, name ) {
35262
35263 var clipArray = objectOrClipArray;
35264
35265 if ( ! Array.isArray( objectOrClipArray ) ) {
35266
35267 var o = objectOrClipArray;
35268 clipArray = o.geometry && o.geometry.animations || o.animations;
35269
35270 }
35271
35272 for ( var i = 0; i < clipArray.length; i ++ ) {
35273
35274 if ( clipArray[ i ].name === name ) {
35275
35276 return clipArray[ i ];
35277
35278 }
35279
35280 }
35281
35282 return null;
35283
35284 },
35285
35286 CreateClipsFromMorphTargetSequences: function ( morphTargets, fps, noLoop ) {
35287
35288 var animationToMorphTargets = {};
35289
35290 // tested with https://regex101.com/ on trick sequences
35291 // such flamingo_flyA_003, flamingo_run1_003, crdeath0059
35292 var pattern = /^([\w-]*?)([\d]+)$/;
35293
35294 // sort morph target names into animation groups based
35295 // patterns like Walk_001, Walk_002, Run_001, Run_002
35296 for ( var i = 0, il = morphTargets.length; i < il; i ++ ) {
35297
35298 var morphTarget = morphTargets[ i ];
35299 var parts = morphTarget.name.match( pattern );
35300
35301 if ( parts && parts.length > 1 ) {
35302
35303 var name = parts[ 1 ];
35304
35305 var animationMorphTargets = animationToMorphTargets[ name ];
35306 if ( ! animationMorphTargets ) {
35307
35308 animationToMorphTargets[ name ] = animationMorphTargets = [];
35309
35310 }
35311
35312 animationMorphTargets.push( morphTarget );
35313
35314 }
35315
35316 }
35317
35318 var clips = [];
35319
35320 for ( var name in animationToMorphTargets ) {
35321
35322 clips.push( AnimationClip.CreateFromMorphTargetSequence( name, animationToMorphTargets[ name ], fps, noLoop ) );
35323
35324 }
35325
35326 return clips;
35327
35328 },
35329
35330 // parse the animation.hierarchy format
35331 parseAnimation: function ( animation, bones ) {
35332
35333 if ( ! animation ) {
35334
35335 console.error( 'THREE.AnimationClip: No animation in JSONLoader data.' );
35336 return null;
35337
35338 }
35339
35340 var addNonemptyTrack = function ( trackType, trackName, animationKeys, propertyName, destTracks ) {
35341
35342 // only return track if there are actually keys.
35343 if ( animationKeys.length !== 0 ) {
35344
35345 var times = [];
35346 var values = [];
35347
35348 AnimationUtils.flattenJSON( animationKeys, times, values, propertyName );
35349
35350 // empty keys are filtered out, so check again
35351 if ( times.length !== 0 ) {
35352
35353 destTracks.push( new trackType( trackName, times, values ) );
35354
35355 }
35356
35357 }
35358
35359 };
35360
35361 var tracks = [];
35362
35363 var clipName = animation.name || 'default';
35364 // automatic length determination in AnimationClip.
35365 var duration = animation.length || - 1;
35366 var fps = animation.fps || 30;
35367
35368 var hierarchyTracks = animation.hierarchy || [];
35369
35370 for ( var h = 0; h < hierarchyTracks.length; h ++ ) {
35371
35372 var animationKeys = hierarchyTracks[ h ].keys;
35373
35374 // skip empty tracks
35375 if ( ! animationKeys || animationKeys.length === 0 ) continue;
35376
35377 // process morph targets
35378 if ( animationKeys[ 0 ].morphTargets ) {
35379
35380 // figure out all morph targets used in this track
35381 var morphTargetNames = {};
35382
35383 for ( var k = 0; k < animationKeys.length; k ++ ) {
35384
35385 if ( animationKeys[ k ].morphTargets ) {
35386
35387 for ( var m = 0; m < animationKeys[ k ].morphTargets.length; m ++ ) {
35388
35389 morphTargetNames[ animationKeys[ k ].morphTargets[ m ] ] = - 1;
35390
35391 }
35392
35393 }
35394
35395 }
35396
35397 // create a track for each morph target with all zero
35398 // morphTargetInfluences except for the keys in which
35399 // the morphTarget is named.
35400 for ( var morphTargetName in morphTargetNames ) {
35401
35402 var times = [];
35403 var values = [];
35404
35405 for ( var m = 0; m !== animationKeys[ k ].morphTargets.length; ++ m ) {
35406
35407 var animationKey = animationKeys[ k ];
35408
35409 times.push( animationKey.time );
35410 values.push( ( animationKey.morphTarget === morphTargetName ) ? 1 : 0 );
35411
35412 }
35413
35414 tracks.push( new NumberKeyframeTrack( '.morphTargetInfluence[' + morphTargetName + ']', times, values ) );
35415
35416 }
35417
35418 duration = morphTargetNames.length * ( fps || 1.0 );
35419
35420 } else {
35421
35422 // ...assume skeletal animation
35423
35424 var boneName = '.bones[' + bones[ h ].name + ']';
35425
35426 addNonemptyTrack(
35427 VectorKeyframeTrack, boneName + '.position',
35428 animationKeys, 'pos', tracks );
35429
35430 addNonemptyTrack(
35431 QuaternionKeyframeTrack, boneName + '.quaternion',
35432 animationKeys, 'rot', tracks );
35433
35434 addNonemptyTrack(
35435 VectorKeyframeTrack, boneName + '.scale',
35436 animationKeys, 'scl', tracks );
35437
35438 }
35439
35440 }
35441
35442 if ( tracks.length === 0 ) {
35443
35444 return null;
35445
35446 }
35447
35448 var clip = new AnimationClip( clipName, duration, tracks );
35449
35450 return clip;
35451
35452 }
35453
35454 } );
35455
35456 Object.assign( AnimationClip.prototype, {
35457
35458 resetDuration: function () {
35459
35460 var tracks = this.tracks, duration = 0;
35461
35462 for ( var i = 0, n = tracks.length; i !== n; ++ i ) {
35463
35464 var track = this.tracks[ i ];
35465
35466 duration = Math.max( duration, track.times[ track.times.length - 1 ] );
35467
35468 }
35469
35470 this.duration = duration;
35471
35472 },
35473
35474 trim: function () {
35475
35476 for ( var i = 0; i < this.tracks.length; i ++ ) {
35477
35478 this.tracks[ i ].trim( 0, this.duration );
35479
35480 }
35481
35482 return this;
35483
35484 },
35485
35486 optimize: function () {
35487
35488 for ( var i = 0; i < this.tracks.length; i ++ ) {
35489
35490 this.tracks[ i ].optimize();
35491
35492 }
35493
35494 return this;
35495
35496 }
35497
35498 } );
35499
35500 /**
35501 * @author mrdoob / http://mrdoob.com/
35502 */
35503
35504 function MaterialLoader( manager ) {
35505
35506 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
35507 this.textures = {};
35508
35509 }
35510
35511 Object.assign( MaterialLoader.prototype, {
35512
35513 load: function ( url, onLoad, onProgress, onError ) {
35514
35515 var scope = this;
35516
35517 var loader = new FileLoader( scope.manager );
35518 loader.load( url, function ( text ) {
35519
35520 onLoad( scope.parse( JSON.parse( text ) ) );
35521
35522 }, onProgress, onError );
35523
35524 },
35525
35526 setTextures: function ( value ) {
35527
35528 this.textures = value;
35529
35530 },
35531
35532 parse: function ( json ) {
35533
35534 var textures = this.textures;
35535
35536 function getTexture( name ) {
35537
35538 if ( textures[ name ] === undefined ) {
35539
35540 console.warn( 'THREE.MaterialLoader: Undefined texture', name );
35541
35542 }
35543
35544 return textures[ name ];
35545
35546 }
35547
35548 var material = new Materials[ json.type ]();
35549
35550 if ( json.uuid !== undefined ) material.uuid = json.uuid;
35551 if ( json.name !== undefined ) material.name = json.name;
35552 if ( json.color !== undefined ) material.color.setHex( json.color );
35553 if ( json.roughness !== undefined ) material.roughness = json.roughness;
35554 if ( json.metalness !== undefined ) material.metalness = json.metalness;
35555 if ( json.emissive !== undefined ) material.emissive.setHex( json.emissive );
35556 if ( json.specular !== undefined ) material.specular.setHex( json.specular );
35557 if ( json.shininess !== undefined ) material.shininess = json.shininess;
35558 if ( json.clearCoat !== undefined ) material.clearCoat = json.clearCoat;
35559 if ( json.clearCoatRoughness !== undefined ) material.clearCoatRoughness = json.clearCoatRoughness;
35560 if ( json.uniforms !== undefined ) material.uniforms = json.uniforms;
35561 if ( json.vertexShader !== undefined ) material.vertexShader = json.vertexShader;
35562 if ( json.fragmentShader !== undefined ) material.fragmentShader = json.fragmentShader;
35563 if ( json.vertexColors !== undefined ) material.vertexColors = json.vertexColors;
35564 if ( json.fog !== undefined ) material.fog = json.fog;
35565 if ( json.flatShading !== undefined ) material.flatShading = json.flatShading;
35566 if ( json.blending !== undefined ) material.blending = json.blending;
35567 if ( json.side !== undefined ) material.side = json.side;
35568 if ( json.opacity !== undefined ) material.opacity = json.opacity;
35569 if ( json.transparent !== undefined ) material.transparent = json.transparent;
35570 if ( json.alphaTest !== undefined ) material.alphaTest = json.alphaTest;
35571 if ( json.depthTest !== undefined ) material.depthTest = json.depthTest;
35572 if ( json.depthWrite !== undefined ) material.depthWrite = json.depthWrite;
35573 if ( json.colorWrite !== undefined ) material.colorWrite = json.colorWrite;
35574 if ( json.wireframe !== undefined ) material.wireframe = json.wireframe;
35575 if ( json.wireframeLinewidth !== undefined ) material.wireframeLinewidth = json.wireframeLinewidth;
35576 if ( json.wireframeLinecap !== undefined ) material.wireframeLinecap = json.wireframeLinecap;
35577 if ( json.wireframeLinejoin !== undefined ) material.wireframeLinejoin = json.wireframeLinejoin;
35578
35579 if ( json.rotation !== undefined ) material.rotation = json.rotation;
35580
35581 if ( json.linewidth !== 1 ) material.linewidth = json.linewidth;
35582 if ( json.dashSize !== undefined ) material.dashSize = json.dashSize;
35583 if ( json.gapSize !== undefined ) material.gapSize = json.gapSize;
35584 if ( json.scale !== undefined ) material.scale = json.scale;
35585
35586 if ( json.polygonOffset !== undefined ) material.polygonOffset = json.polygonOffset;
35587 if ( json.polygonOffsetFactor !== undefined ) material.polygonOffsetFactor = json.polygonOffsetFactor;
35588 if ( json.polygonOffsetUnits !== undefined ) material.polygonOffsetUnits = json.polygonOffsetUnits;
35589
35590 if ( json.skinning !== undefined ) material.skinning = json.skinning;
35591 if ( json.morphTargets !== undefined ) material.morphTargets = json.morphTargets;
35592 if ( json.dithering !== undefined ) material.dithering = json.dithering;
35593
35594 if ( json.visible !== undefined ) material.visible = json.visible;
35595 if ( json.userData !== undefined ) material.userData = json.userData;
35596
35597 // Deprecated
35598
35599 if ( json.shading !== undefined ) material.flatShading = json.shading === 1; // THREE.FlatShading
35600
35601 // for PointsMaterial
35602
35603 if ( json.size !== undefined ) material.size = json.size;
35604 if ( json.sizeAttenuation !== undefined ) material.sizeAttenuation = json.sizeAttenuation;
35605
35606 // maps
35607
35608 if ( json.map !== undefined ) material.map = getTexture( json.map );
35609
35610 if ( json.alphaMap !== undefined ) {
35611
35612 material.alphaMap = getTexture( json.alphaMap );
35613 material.transparent = true;
35614
35615 }
35616
35617 if ( json.bumpMap !== undefined ) material.bumpMap = getTexture( json.bumpMap );
35618 if ( json.bumpScale !== undefined ) material.bumpScale = json.bumpScale;
35619
35620 if ( json.normalMap !== undefined ) material.normalMap = getTexture( json.normalMap );
35621 if ( json.normalScale !== undefined ) {
35622
35623 var normalScale = json.normalScale;
35624
35625 if ( Array.isArray( normalScale ) === false ) {
35626
35627 // Blender exporter used to export a scalar. See #7459
35628
35629 normalScale = [ normalScale, normalScale ];
35630
35631 }
35632
35633 material.normalScale = new Vector2().fromArray( normalScale );
35634
35635 }
35636
35637 if ( json.displacementMap !== undefined ) material.displacementMap = getTexture( json.displacementMap );
35638 if ( json.displacementScale !== undefined ) material.displacementScale = json.displacementScale;
35639 if ( json.displacementBias !== undefined ) material.displacementBias = json.displacementBias;
35640
35641 if ( json.roughnessMap !== undefined ) material.roughnessMap = getTexture( json.roughnessMap );
35642 if ( json.metalnessMap !== undefined ) material.metalnessMap = getTexture( json.metalnessMap );
35643
35644 if ( json.emissiveMap !== undefined ) material.emissiveMap = getTexture( json.emissiveMap );
35645 if ( json.emissiveIntensity !== undefined ) material.emissiveIntensity = json.emissiveIntensity;
35646
35647 if ( json.specularMap !== undefined ) material.specularMap = getTexture( json.specularMap );
35648
35649 if ( json.envMap !== undefined ) material.envMap = getTexture( json.envMap );
35650
35651 if ( json.reflectivity !== undefined ) material.reflectivity = json.reflectivity;
35652
35653 if ( json.lightMap !== undefined ) material.lightMap = getTexture( json.lightMap );
35654 if ( json.lightMapIntensity !== undefined ) material.lightMapIntensity = json.lightMapIntensity;
35655
35656 if ( json.aoMap !== undefined ) material.aoMap = getTexture( json.aoMap );
35657 if ( json.aoMapIntensity !== undefined ) material.aoMapIntensity = json.aoMapIntensity;
35658
35659 if ( json.gradientMap !== undefined ) material.gradientMap = getTexture( json.gradientMap );
35660
35661 return material;
35662
35663 }
35664
35665 } );
35666
35667 /**
35668 * @author mrdoob / http://mrdoob.com/
35669 */
35670
35671 function BufferGeometryLoader( manager ) {
35672
35673 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
35674
35675 }
35676
35677 Object.assign( BufferGeometryLoader.prototype, {
35678
35679 load: function ( url, onLoad, onProgress, onError ) {
35680
35681 var scope = this;
35682
35683 var loader = new FileLoader( scope.manager );
35684 loader.load( url, function ( text ) {
35685
35686 onLoad( scope.parse( JSON.parse( text ) ) );
35687
35688 }, onProgress, onError );
35689
35690 },
35691
35692 parse: function ( json ) {
35693
35694 var geometry = new BufferGeometry();
35695
35696 var index = json.data.index;
35697
35698 if ( index !== undefined ) {
35699
35700 var typedArray = new TYPED_ARRAYS[ index.type ]( index.array );
35701 geometry.setIndex( new BufferAttribute( typedArray, 1 ) );
35702
35703 }
35704
35705 var attributes = json.data.attributes;
35706
35707 for ( var key in attributes ) {
35708
35709 var attribute = attributes[ key ];
35710 var typedArray = new TYPED_ARRAYS[ attribute.type ]( attribute.array );
35711
35712 geometry.addAttribute( key, new BufferAttribute( typedArray, attribute.itemSize, attribute.normalized ) );
35713
35714 }
35715
35716 var groups = json.data.groups || json.data.drawcalls || json.data.offsets;
35717
35718 if ( groups !== undefined ) {
35719
35720 for ( var i = 0, n = groups.length; i !== n; ++ i ) {
35721
35722 var group = groups[ i ];
35723
35724 geometry.addGroup( group.start, group.count, group.materialIndex );
35725
35726 }
35727
35728 }
35729
35730 var boundingSphere = json.data.boundingSphere;
35731
35732 if ( boundingSphere !== undefined ) {
35733
35734 var center = new Vector3();
35735
35736 if ( boundingSphere.center !== undefined ) {
35737
35738 center.fromArray( boundingSphere.center );
35739
35740 }
35741
35742 geometry.boundingSphere = new Sphere( center, boundingSphere.radius );
35743
35744 }
35745
35746 return geometry;
35747
35748 }
35749
35750 } );
35751
35752 var TYPED_ARRAYS = {
35753 Int8Array: Int8Array,
35754 Uint8Array: Uint8Array,
35755 // Workaround for IE11 pre KB2929437. See #11440
35756 Uint8ClampedArray: typeof Uint8ClampedArray !== 'undefined' ? Uint8ClampedArray : Uint8Array,
35757 Int16Array: Int16Array,
35758 Uint16Array: Uint16Array,
35759 Int32Array: Int32Array,
35760 Uint32Array: Uint32Array,
35761 Float32Array: Float32Array,
35762 Float64Array: Float64Array
35763 };
35764
35765 /**
35766 * @author alteredq / http://alteredqualia.com/
35767 */
35768
35769 function Loader() {}
35770
35771 Loader.Handlers = {
35772
35773 handlers: [],
35774
35775 add: function ( regex, loader ) {
35776
35777 this.handlers.push( regex, loader );
35778
35779 },
35780
35781 get: function ( file ) {
35782
35783 var handlers = this.handlers;
35784
35785 for ( var i = 0, l = handlers.length; i < l; i += 2 ) {
35786
35787 var regex = handlers[ i ];
35788 var loader = handlers[ i + 1 ];
35789
35790 if ( regex.test( file ) ) {
35791
35792 return loader;
35793
35794 }
35795
35796 }
35797
35798 return null;
35799
35800 }
35801
35802 };
35803
35804 Object.assign( Loader.prototype, {
35805
35806 crossOrigin: undefined,
35807
35808 onLoadStart: function () {},
35809
35810 onLoadProgress: function () {},
35811
35812 onLoadComplete: function () {},
35813
35814 initMaterials: function ( materials, texturePath, crossOrigin ) {
35815
35816 var array = [];
35817
35818 for ( var i = 0; i < materials.length; ++ i ) {
35819
35820 array[ i ] = this.createMaterial( materials[ i ], texturePath, crossOrigin );
35821
35822 }
35823
35824 return array;
35825
35826 },
35827
35828 createMaterial: ( function () {
35829
35830 var BlendingMode = {
35831 NoBlending: NoBlending,
35832 NormalBlending: NormalBlending,
35833 AdditiveBlending: AdditiveBlending,
35834 SubtractiveBlending: SubtractiveBlending,
35835 MultiplyBlending: MultiplyBlending,
35836 CustomBlending: CustomBlending
35837 };
35838
35839 var color = new Color();
35840 var textureLoader = new TextureLoader();
35841 var materialLoader = new MaterialLoader();
35842
35843 return function createMaterial( m, texturePath, crossOrigin ) {
35844
35845 // convert from old material format
35846
35847 var textures = {};
35848
35849 function loadTexture( path, repeat, offset, wrap, anisotropy ) {
35850
35851 var fullPath = texturePath + path;
35852 var loader = Loader.Handlers.get( fullPath );
35853
35854 var texture;
35855
35856 if ( loader !== null ) {
35857
35858 texture = loader.load( fullPath );
35859
35860 } else {
35861
35862 textureLoader.setCrossOrigin( crossOrigin );
35863 texture = textureLoader.load( fullPath );
35864
35865 }
35866
35867 if ( repeat !== undefined ) {
35868
35869 texture.repeat.fromArray( repeat );
35870
35871 if ( repeat[ 0 ] !== 1 ) texture.wrapS = RepeatWrapping;
35872 if ( repeat[ 1 ] !== 1 ) texture.wrapT = RepeatWrapping;
35873
35874 }
35875
35876 if ( offset !== undefined ) {
35877
35878 texture.offset.fromArray( offset );
35879
35880 }
35881
35882 if ( wrap !== undefined ) {
35883
35884 if ( wrap[ 0 ] === 'repeat' ) texture.wrapS = RepeatWrapping;
35885 if ( wrap[ 0 ] === 'mirror' ) texture.wrapS = MirroredRepeatWrapping;
35886
35887 if ( wrap[ 1 ] === 'repeat' ) texture.wrapT = RepeatWrapping;
35888 if ( wrap[ 1 ] === 'mirror' ) texture.wrapT = MirroredRepeatWrapping;
35889
35890 }
35891
35892 if ( anisotropy !== undefined ) {
35893
35894 texture.anisotropy = anisotropy;
35895
35896 }
35897
35898 var uuid = _Math.generateUUID();
35899
35900 textures[ uuid ] = texture;
35901
35902 return uuid;
35903
35904 }
35905
35906 //
35907
35908 var json = {
35909 uuid: _Math.generateUUID(),
35910 type: 'MeshLambertMaterial'
35911 };
35912
35913 for ( var name in m ) {
35914
35915 var value = m[ name ];
35916
35917 switch ( name ) {
35918
35919 case 'DbgColor':
35920 case 'DbgIndex':
35921 case 'opticalDensity':
35922 case 'illumination':
35923 break;
35924 case 'DbgName':
35925 json.name = value;
35926 break;
35927 case 'blending':
35928 json.blending = BlendingMode[ value ];
35929 break;
35930 case 'colorAmbient':
35931 case 'mapAmbient':
35932 console.warn( 'THREE.Loader.createMaterial:', name, 'is no longer supported.' );
35933 break;
35934 case 'colorDiffuse':
35935 json.color = color.fromArray( value ).getHex();
35936 break;
35937 case 'colorSpecular':
35938 json.specular = color.fromArray( value ).getHex();
35939 break;
35940 case 'colorEmissive':
35941 json.emissive = color.fromArray( value ).getHex();
35942 break;
35943 case 'specularCoef':
35944 json.shininess = value;
35945 break;
35946 case 'shading':
35947 if ( value.toLowerCase() === 'basic' ) json.type = 'MeshBasicMaterial';
35948 if ( value.toLowerCase() === 'phong' ) json.type = 'MeshPhongMaterial';
35949 if ( value.toLowerCase() === 'standard' ) json.type = 'MeshStandardMaterial';
35950 break;
35951 case 'mapDiffuse':
35952 json.map = loadTexture( value, m.mapDiffuseRepeat, m.mapDiffuseOffset, m.mapDiffuseWrap, m.mapDiffuseAnisotropy );
35953 break;
35954 case 'mapDiffuseRepeat':
35955 case 'mapDiffuseOffset':
35956 case 'mapDiffuseWrap':
35957 case 'mapDiffuseAnisotropy':
35958 break;
35959 case 'mapEmissive':
35960 json.emissiveMap = loadTexture( value, m.mapEmissiveRepeat, m.mapEmissiveOffset, m.mapEmissiveWrap, m.mapEmissiveAnisotropy );
35961 break;
35962 case 'mapEmissiveRepeat':
35963 case 'mapEmissiveOffset':
35964 case 'mapEmissiveWrap':
35965 case 'mapEmissiveAnisotropy':
35966 break;
35967 case 'mapLight':
35968 json.lightMap = loadTexture( value, m.mapLightRepeat, m.mapLightOffset, m.mapLightWrap, m.mapLightAnisotropy );
35969 break;
35970 case 'mapLightRepeat':
35971 case 'mapLightOffset':
35972 case 'mapLightWrap':
35973 case 'mapLightAnisotropy':
35974 break;
35975 case 'mapAO':
35976 json.aoMap = loadTexture( value, m.mapAORepeat, m.mapAOOffset, m.mapAOWrap, m.mapAOAnisotropy );
35977 break;
35978 case 'mapAORepeat':
35979 case 'mapAOOffset':
35980 case 'mapAOWrap':
35981 case 'mapAOAnisotropy':
35982 break;
35983 case 'mapBump':
35984 json.bumpMap = loadTexture( value, m.mapBumpRepeat, m.mapBumpOffset, m.mapBumpWrap, m.mapBumpAnisotropy );
35985 break;
35986 case 'mapBumpScale':
35987 json.bumpScale = value;
35988 break;
35989 case 'mapBumpRepeat':
35990 case 'mapBumpOffset':
35991 case 'mapBumpWrap':
35992 case 'mapBumpAnisotropy':
35993 break;
35994 case 'mapNormal':
35995 json.normalMap = loadTexture( value, m.mapNormalRepeat, m.mapNormalOffset, m.mapNormalWrap, m.mapNormalAnisotropy );
35996 break;
35997 case 'mapNormalFactor':
35998 json.normalScale = value;
35999 break;
36000 case 'mapNormalRepeat':
36001 case 'mapNormalOffset':
36002 case 'mapNormalWrap':
36003 case 'mapNormalAnisotropy':
36004 break;
36005 case 'mapSpecular':
36006 json.specularMap = loadTexture( value, m.mapSpecularRepeat, m.mapSpecularOffset, m.mapSpecularWrap, m.mapSpecularAnisotropy );
36007 break;
36008 case 'mapSpecularRepeat':
36009 case 'mapSpecularOffset':
36010 case 'mapSpecularWrap':
36011 case 'mapSpecularAnisotropy':
36012 break;
36013 case 'mapMetalness':
36014 json.metalnessMap = loadTexture( value, m.mapMetalnessRepeat, m.mapMetalnessOffset, m.mapMetalnessWrap, m.mapMetalnessAnisotropy );
36015 break;
36016 case 'mapMetalnessRepeat':
36017 case 'mapMetalnessOffset':
36018 case 'mapMetalnessWrap':
36019 case 'mapMetalnessAnisotropy':
36020 break;
36021 case 'mapRoughness':
36022 json.roughnessMap = loadTexture( value, m.mapRoughnessRepeat, m.mapRoughnessOffset, m.mapRoughnessWrap, m.mapRoughnessAnisotropy );
36023 break;
36024 case 'mapRoughnessRepeat':
36025 case 'mapRoughnessOffset':
36026 case 'mapRoughnessWrap':
36027 case 'mapRoughnessAnisotropy':
36028 break;
36029 case 'mapAlpha':
36030 json.alphaMap = loadTexture( value, m.mapAlphaRepeat, m.mapAlphaOffset, m.mapAlphaWrap, m.mapAlphaAnisotropy );
36031 break;
36032 case 'mapAlphaRepeat':
36033 case 'mapAlphaOffset':
36034 case 'mapAlphaWrap':
36035 case 'mapAlphaAnisotropy':
36036 break;
36037 case 'flipSided':
36038 json.side = BackSide;
36039 break;
36040 case 'doubleSided':
36041 json.side = DoubleSide;
36042 break;
36043 case 'transparency':
36044 console.warn( 'THREE.Loader.createMaterial: transparency has been renamed to opacity' );
36045 json.opacity = value;
36046 break;
36047 case 'depthTest':
36048 case 'depthWrite':
36049 case 'colorWrite':
36050 case 'opacity':
36051 case 'reflectivity':
36052 case 'transparent':
36053 case 'visible':
36054 case 'wireframe':
36055 json[ name ] = value;
36056 break;
36057 case 'vertexColors':
36058 if ( value === true ) json.vertexColors = VertexColors;
36059 if ( value === 'face' ) json.vertexColors = FaceColors;
36060 break;
36061 default:
36062 console.error( 'THREE.Loader.createMaterial: Unsupported', name, value );
36063 break;
36064
36065 }
36066
36067 }
36068
36069 if ( json.type === 'MeshBasicMaterial' ) delete json.emissive;
36070 if ( json.type !== 'MeshPhongMaterial' ) delete json.specular;
36071
36072 if ( json.opacity < 1 ) json.transparent = true;
36073
36074 materialLoader.setTextures( textures );
36075
36076 return materialLoader.parse( json );
36077
36078 };
36079
36080 } )()
36081
36082 } );
36083
36084 /**
36085 * @author Don McCurdy / https://www.donmccurdy.com
36086 */
36087
36088 var LoaderUtils = {
36089
36090 decodeText: function ( array ) {
36091
36092 if ( typeof TextDecoder !== 'undefined' ) {
36093
36094 return new TextDecoder().decode( array );
36095
36096 }
36097
36098 // Avoid the String.fromCharCode.apply(null, array) shortcut, which
36099 // throws a "maximum call stack size exceeded" error for large arrays.
36100
36101 var s = '';
36102
36103 for ( var i = 0, il = array.length; i < il; i ++ ) {
36104
36105 // Implicitly assumes little-endian.
36106 s += String.fromCharCode( array[ i ] );
36107
36108 }
36109
36110 // Merges multi-byte utf-8 characters.
36111 return decodeURIComponent( escape( s ) );
36112
36113 },
36114
36115 extractUrlBase: function ( url ) {
36116
36117 var index = url.lastIndexOf( '/' );
36118
36119 if ( index === - 1 ) return './';
36120
36121 return url.substr( 0, index + 1 );
36122
36123 }
36124
36125 };
36126
36127 /**
36128 * @author mrdoob / http://mrdoob.com/
36129 * @author alteredq / http://alteredqualia.com/
36130 */
36131
36132 function JSONLoader( manager ) {
36133
36134 if ( typeof manager === 'boolean' ) {
36135
36136 console.warn( 'THREE.JSONLoader: showStatus parameter has been removed from constructor.' );
36137 manager = undefined;
36138
36139 }
36140
36141 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
36142
36143 this.withCredentials = false;
36144
36145 }
36146
36147 Object.assign( JSONLoader.prototype, {
36148
36149 load: function ( url, onLoad, onProgress, onError ) {
36150
36151 var scope = this;
36152
36153 var texturePath = this.texturePath && ( typeof this.texturePath === 'string' ) ? this.texturePath : LoaderUtils.extractUrlBase( url );
36154
36155 var loader = new FileLoader( this.manager );
36156 loader.setWithCredentials( this.withCredentials );
36157 loader.load( url, function ( text ) {
36158
36159 var json = JSON.parse( text );
36160 var metadata = json.metadata;
36161
36162 if ( metadata !== undefined ) {
36163
36164 var type = metadata.type;
36165
36166 if ( type !== undefined ) {
36167
36168 if ( type.toLowerCase() === 'object' ) {
36169
36170 console.error( 'THREE.JSONLoader: ' + url + ' should be loaded with THREE.ObjectLoader instead.' );
36171 return;
36172
36173 }
36174
36175 }
36176
36177 }
36178
36179 var object = scope.parse( json, texturePath );
36180 onLoad( object.geometry, object.materials );
36181
36182 }, onProgress, onError );
36183
36184 },
36185
36186 setTexturePath: function ( value ) {
36187
36188 this.texturePath = value;
36189
36190 },
36191
36192 parse: ( function () {
36193
36194 function parseModel( json, geometry ) {
36195
36196 function isBitSet( value, position ) {
36197
36198 return value & ( 1 << position );
36199
36200 }
36201
36202 var i, j, fi,
36203
36204 offset, zLength,
36205
36206 colorIndex, normalIndex, uvIndex, materialIndex,
36207
36208 type,
36209 isQuad,
36210 hasMaterial,
36211 hasFaceVertexUv,
36212 hasFaceNormal, hasFaceVertexNormal,
36213 hasFaceColor, hasFaceVertexColor,
36214
36215 vertex, face, faceA, faceB, hex, normal,
36216
36217 uvLayer, uv, u, v,
36218
36219 faces = json.faces,
36220 vertices = json.vertices,
36221 normals = json.normals,
36222 colors = json.colors,
36223
36224 scale = json.scale,
36225
36226 nUvLayers = 0;
36227
36228
36229 if ( json.uvs !== undefined ) {
36230
36231 // disregard empty arrays
36232
36233 for ( i = 0; i < json.uvs.length; i ++ ) {
36234
36235 if ( json.uvs[ i ].length ) nUvLayers ++;
36236
36237 }
36238
36239 for ( i = 0; i < nUvLayers; i ++ ) {
36240
36241 geometry.faceVertexUvs[ i ] = [];
36242
36243 }
36244
36245 }
36246
36247 offset = 0;
36248 zLength = vertices.length;
36249
36250 while ( offset < zLength ) {
36251
36252 vertex = new Vector3();
36253
36254 vertex.x = vertices[ offset ++ ] * scale;
36255 vertex.y = vertices[ offset ++ ] * scale;
36256 vertex.z = vertices[ offset ++ ] * scale;
36257
36258 geometry.vertices.push( vertex );
36259
36260 }
36261
36262 offset = 0;
36263 zLength = faces.length;
36264
36265 while ( offset < zLength ) {
36266
36267 type = faces[ offset ++ ];
36268
36269 isQuad = isBitSet( type, 0 );
36270 hasMaterial = isBitSet( type, 1 );
36271 hasFaceVertexUv = isBitSet( type, 3 );
36272 hasFaceNormal = isBitSet( type, 4 );
36273 hasFaceVertexNormal = isBitSet( type, 5 );
36274 hasFaceColor = isBitSet( type, 6 );
36275 hasFaceVertexColor = isBitSet( type, 7 );
36276
36277 // console.log("type", type, "bits", isQuad, hasMaterial, hasFaceVertexUv, hasFaceNormal, hasFaceVertexNormal, hasFaceColor, hasFaceVertexColor);
36278
36279 if ( isQuad ) {
36280
36281 faceA = new Face3();
36282 faceA.a = faces[ offset ];
36283 faceA.b = faces[ offset + 1 ];
36284 faceA.c = faces[ offset + 3 ];
36285
36286 faceB = new Face3();
36287 faceB.a = faces[ offset + 1 ];
36288 faceB.b = faces[ offset + 2 ];
36289 faceB.c = faces[ offset + 3 ];
36290
36291 offset += 4;
36292
36293 if ( hasMaterial ) {
36294
36295 materialIndex = faces[ offset ++ ];
36296 faceA.materialIndex = materialIndex;
36297 faceB.materialIndex = materialIndex;
36298
36299 }
36300
36301 // to get face <=> uv index correspondence
36302
36303 fi = geometry.faces.length;
36304
36305 if ( hasFaceVertexUv ) {
36306
36307 for ( i = 0; i < nUvLayers; i ++ ) {
36308
36309 uvLayer = json.uvs[ i ];
36310
36311 geometry.faceVertexUvs[ i ][ fi ] = [];
36312 geometry.faceVertexUvs[ i ][ fi + 1 ] = [];
36313
36314 for ( j = 0; j < 4; j ++ ) {
36315
36316 uvIndex = faces[ offset ++ ];
36317
36318 u = uvLayer[ uvIndex * 2 ];
36319 v = uvLayer[ uvIndex * 2 + 1 ];
36320
36321 uv = new Vector2( u, v );
36322
36323 if ( j !== 2 ) geometry.faceVertexUvs[ i ][ fi ].push( uv );
36324 if ( j !== 0 ) geometry.faceVertexUvs[ i ][ fi + 1 ].push( uv );
36325
36326 }
36327
36328 }
36329
36330 }
36331
36332 if ( hasFaceNormal ) {
36333
36334 normalIndex = faces[ offset ++ ] * 3;
36335
36336 faceA.normal.set(
36337 normals[ normalIndex ++ ],
36338 normals[ normalIndex ++ ],
36339 normals[ normalIndex ]
36340 );
36341
36342 faceB.normal.copy( faceA.normal );
36343
36344 }
36345
36346 if ( hasFaceVertexNormal ) {
36347
36348 for ( i = 0; i < 4; i ++ ) {
36349
36350 normalIndex = faces[ offset ++ ] * 3;
36351
36352 normal = new Vector3(
36353 normals[ normalIndex ++ ],
36354 normals[ normalIndex ++ ],
36355 normals[ normalIndex ]
36356 );
36357
36358
36359 if ( i !== 2 ) faceA.vertexNormals.push( normal );
36360 if ( i !== 0 ) faceB.vertexNormals.push( normal );
36361
36362 }
36363
36364 }
36365
36366
36367 if ( hasFaceColor ) {
36368
36369 colorIndex = faces[ offset ++ ];
36370 hex = colors[ colorIndex ];
36371
36372 faceA.color.setHex( hex );
36373 faceB.color.setHex( hex );
36374
36375 }
36376
36377
36378 if ( hasFaceVertexColor ) {
36379
36380 for ( i = 0; i < 4; i ++ ) {
36381
36382 colorIndex = faces[ offset ++ ];
36383 hex = colors[ colorIndex ];
36384
36385 if ( i !== 2 ) faceA.vertexColors.push( new Color( hex ) );
36386 if ( i !== 0 ) faceB.vertexColors.push( new Color( hex ) );
36387
36388 }
36389
36390 }
36391
36392 geometry.faces.push( faceA );
36393 geometry.faces.push( faceB );
36394
36395 } else {
36396
36397 face = new Face3();
36398 face.a = faces[ offset ++ ];
36399 face.b = faces[ offset ++ ];
36400 face.c = faces[ offset ++ ];
36401
36402 if ( hasMaterial ) {
36403
36404 materialIndex = faces[ offset ++ ];
36405 face.materialIndex = materialIndex;
36406
36407 }
36408
36409 // to get face <=> uv index correspondence
36410
36411 fi = geometry.faces.length;
36412
36413 if ( hasFaceVertexUv ) {
36414
36415 for ( i = 0; i < nUvLayers; i ++ ) {
36416
36417 uvLayer = json.uvs[ i ];
36418
36419 geometry.faceVertexUvs[ i ][ fi ] = [];
36420
36421 for ( j = 0; j < 3; j ++ ) {
36422
36423 uvIndex = faces[ offset ++ ];
36424
36425 u = uvLayer[ uvIndex * 2 ];
36426 v = uvLayer[ uvIndex * 2 + 1 ];
36427
36428 uv = new Vector2( u, v );
36429
36430 geometry.faceVertexUvs[ i ][ fi ].push( uv );
36431
36432 }
36433
36434 }
36435
36436 }
36437
36438 if ( hasFaceNormal ) {
36439
36440 normalIndex = faces[ offset ++ ] * 3;
36441
36442 face.normal.set(
36443 normals[ normalIndex ++ ],
36444 normals[ normalIndex ++ ],
36445 normals[ normalIndex ]
36446 );
36447
36448 }
36449
36450 if ( hasFaceVertexNormal ) {
36451
36452 for ( i = 0; i < 3; i ++ ) {
36453
36454 normalIndex = faces[ offset ++ ] * 3;
36455
36456 normal = new Vector3(
36457 normals[ normalIndex ++ ],
36458 normals[ normalIndex ++ ],
36459 normals[ normalIndex ]
36460 );
36461
36462 face.vertexNormals.push( normal );
36463
36464 }
36465
36466 }
36467
36468
36469 if ( hasFaceColor ) {
36470
36471 colorIndex = faces[ offset ++ ];
36472 face.color.setHex( colors[ colorIndex ] );
36473
36474 }
36475
36476
36477 if ( hasFaceVertexColor ) {
36478
36479 for ( i = 0; i < 3; i ++ ) {
36480
36481 colorIndex = faces[ offset ++ ];
36482 face.vertexColors.push( new Color( colors[ colorIndex ] ) );
36483
36484 }
36485
36486 }
36487
36488 geometry.faces.push( face );
36489
36490 }
36491
36492 }
36493
36494 }
36495
36496 function parseSkin( json, geometry ) {
36497
36498 var influencesPerVertex = ( json.influencesPerVertex !== undefined ) ? json.influencesPerVertex : 2;
36499
36500 if ( json.skinWeights ) {
36501
36502 for ( var i = 0, l = json.skinWeights.length; i < l; i += influencesPerVertex ) {
36503
36504 var x = json.skinWeights[ i ];
36505 var y = ( influencesPerVertex > 1 ) ? json.skinWeights[ i + 1 ] : 0;
36506 var z = ( influencesPerVertex > 2 ) ? json.skinWeights[ i + 2 ] : 0;
36507 var w = ( influencesPerVertex > 3 ) ? json.skinWeights[ i + 3 ] : 0;
36508
36509 geometry.skinWeights.push( new Vector4( x, y, z, w ) );
36510
36511 }
36512
36513 }
36514
36515 if ( json.skinIndices ) {
36516
36517 for ( var i = 0, l = json.skinIndices.length; i < l; i += influencesPerVertex ) {
36518
36519 var a = json.skinIndices[ i ];
36520 var b = ( influencesPerVertex > 1 ) ? json.skinIndices[ i + 1 ] : 0;
36521 var c = ( influencesPerVertex > 2 ) ? json.skinIndices[ i + 2 ] : 0;
36522 var d = ( influencesPerVertex > 3 ) ? json.skinIndices[ i + 3 ] : 0;
36523
36524 geometry.skinIndices.push( new Vector4( a, b, c, d ) );
36525
36526 }
36527
36528 }
36529
36530 geometry.bones = json.bones;
36531
36532 if ( geometry.bones && geometry.bones.length > 0 && ( geometry.skinWeights.length !== geometry.skinIndices.length || geometry.skinIndices.length !== geometry.vertices.length ) ) {
36533
36534 console.warn( 'When skinning, number of vertices (' + geometry.vertices.length + '), skinIndices (' +
36535 geometry.skinIndices.length + '), and skinWeights (' + geometry.skinWeights.length + ') should match.' );
36536
36537 }
36538
36539 }
36540
36541 function parseMorphing( json, geometry ) {
36542
36543 var scale = json.scale;
36544
36545 if ( json.morphTargets !== undefined ) {
36546
36547 for ( var i = 0, l = json.morphTargets.length; i < l; i ++ ) {
36548
36549 geometry.morphTargets[ i ] = {};
36550 geometry.morphTargets[ i ].name = json.morphTargets[ i ].name;
36551 geometry.morphTargets[ i ].vertices = [];
36552
36553 var dstVertices = geometry.morphTargets[ i ].vertices;
36554 var srcVertices = json.morphTargets[ i ].vertices;
36555
36556 for ( var v = 0, vl = srcVertices.length; v < vl; v += 3 ) {
36557
36558 var vertex = new Vector3();
36559 vertex.x = srcVertices[ v ] * scale;
36560 vertex.y = srcVertices[ v + 1 ] * scale;
36561 vertex.z = srcVertices[ v + 2 ] * scale;
36562
36563 dstVertices.push( vertex );
36564
36565 }
36566
36567 }
36568
36569 }
36570
36571 if ( json.morphColors !== undefined && json.morphColors.length > 0 ) {
36572
36573 console.warn( 'THREE.JSONLoader: "morphColors" no longer supported. Using them as face colors.' );
36574
36575 var faces = geometry.faces;
36576 var morphColors = json.morphColors[ 0 ].colors;
36577
36578 for ( var i = 0, l = faces.length; i < l; i ++ ) {
36579
36580 faces[ i ].color.fromArray( morphColors, i * 3 );
36581
36582 }
36583
36584 }
36585
36586 }
36587
36588 function parseAnimations( json, geometry ) {
36589
36590 var outputAnimations = [];
36591
36592 // parse old style Bone/Hierarchy animations
36593 var animations = [];
36594
36595 if ( json.animation !== undefined ) {
36596
36597 animations.push( json.animation );
36598
36599 }
36600
36601 if ( json.animations !== undefined ) {
36602
36603 if ( json.animations.length ) {
36604
36605 animations = animations.concat( json.animations );
36606
36607 } else {
36608
36609 animations.push( json.animations );
36610
36611 }
36612
36613 }
36614
36615 for ( var i = 0; i < animations.length; i ++ ) {
36616
36617 var clip = AnimationClip.parseAnimation( animations[ i ], geometry.bones );
36618 if ( clip ) outputAnimations.push( clip );
36619
36620 }
36621
36622 // parse implicit morph animations
36623 if ( geometry.morphTargets ) {
36624
36625 // TODO: Figure out what an appropraite FPS is for morph target animations -- defaulting to 10, but really it is completely arbitrary.
36626 var morphAnimationClips = AnimationClip.CreateClipsFromMorphTargetSequences( geometry.morphTargets, 10 );
36627 outputAnimations = outputAnimations.concat( morphAnimationClips );
36628
36629 }
36630
36631 if ( outputAnimations.length > 0 ) geometry.animations = outputAnimations;
36632
36633 }
36634
36635 return function parse( json, texturePath ) {
36636
36637 if ( json.data !== undefined ) {
36638
36639 // Geometry 4.0 spec
36640 json = json.data;
36641
36642 }
36643
36644 if ( json.scale !== undefined ) {
36645
36646 json.scale = 1.0 / json.scale;
36647
36648 } else {
36649
36650 json.scale = 1.0;
36651
36652 }
36653
36654 var geometry = new Geometry();
36655
36656 parseModel( json, geometry );
36657 parseSkin( json, geometry );
36658 parseMorphing( json, geometry );
36659 parseAnimations( json, geometry );
36660
36661 geometry.computeFaceNormals();
36662 geometry.computeBoundingSphere();
36663
36664 if ( json.materials === undefined || json.materials.length === 0 ) {
36665
36666 return { geometry: geometry };
36667
36668 } else {
36669
36670 var materials = Loader.prototype.initMaterials( json.materials, texturePath, this.crossOrigin );
36671
36672 return { geometry: geometry, materials: materials };
36673
36674 }
36675
36676 };
36677
36678 } )()
36679
36680 } );
36681
36682 /**
36683 * @author mrdoob / http://mrdoob.com/
36684 */
36685
36686 function ObjectLoader( manager ) {
36687
36688 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
36689 this.texturePath = '';
36690
36691 }
36692
36693 Object.assign( ObjectLoader.prototype, {
36694
36695 load: function ( url, onLoad, onProgress, onError ) {
36696
36697 if ( this.texturePath === '' ) {
36698
36699 this.texturePath = url.substring( 0, url.lastIndexOf( '/' ) + 1 );
36700
36701 }
36702
36703 var scope = this;
36704
36705 var loader = new FileLoader( scope.manager );
36706 loader.load( url, function ( text ) {
36707
36708 var json = null;
36709
36710 try {
36711
36712 json = JSON.parse( text );
36713
36714 } catch ( error ) {
36715
36716 if ( onError !== undefined ) onError( error );
36717
36718 console.error( 'THREE:ObjectLoader: Can\'t parse ' + url + '.', error.message );
36719
36720 return;
36721
36722 }
36723
36724 var metadata = json.metadata;
36725
36726 if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) {
36727
36728 console.error( 'THREE.ObjectLoader: Can\'t load ' + url + '. Use THREE.JSONLoader instead.' );
36729 return;
36730
36731 }
36732
36733 scope.parse( json, onLoad );
36734
36735 }, onProgress, onError );
36736
36737 },
36738
36739 setTexturePath: function ( value ) {
36740
36741 this.texturePath = value;
36742
36743 },
36744
36745 setCrossOrigin: function ( value ) {
36746
36747 this.crossOrigin = value;
36748
36749 },
36750
36751 parse: function ( json, onLoad ) {
36752
36753 var shapes = this.parseShape( json.shapes );
36754 var geometries = this.parseGeometries( json.geometries, shapes );
36755
36756 var images = this.parseImages( json.images, function () {
36757
36758 if ( onLoad !== undefined ) onLoad( object );
36759
36760 } );
36761
36762 var textures = this.parseTextures( json.textures, images );
36763 var materials = this.parseMaterials( json.materials, textures );
36764
36765 var object = this.parseObject( json.object, geometries, materials );
36766
36767 if ( json.animations ) {
36768
36769 object.animations = this.parseAnimations( json.animations );
36770
36771 }
36772
36773 if ( json.images === undefined || json.images.length === 0 ) {
36774
36775 if ( onLoad !== undefined ) onLoad( object );
36776
36777 }
36778
36779 return object;
36780
36781 },
36782
36783 parseShape: function ( json ) {
36784
36785 var shapes = {};
36786
36787 if ( json !== undefined ) {
36788
36789 for ( var i = 0, l = json.length; i < l; i ++ ) {
36790
36791 var shape = new Shape().fromJSON( json[ i ] );
36792
36793 shapes[ shape.uuid ] = shape;
36794
36795 }
36796
36797 }
36798
36799 return shapes;
36800
36801 },
36802
36803 parseGeometries: function ( json, shapes ) {
36804
36805 var geometries = {};
36806
36807 if ( json !== undefined ) {
36808
36809 var geometryLoader = new JSONLoader();
36810 var bufferGeometryLoader = new BufferGeometryLoader();
36811
36812 for ( var i = 0, l = json.length; i < l; i ++ ) {
36813
36814 var geometry;
36815 var data = json[ i ];
36816
36817 switch ( data.type ) {
36818
36819 case 'PlaneGeometry':
36820 case 'PlaneBufferGeometry':
36821
36822 geometry = new Geometries[ data.type ](
36823 data.width,
36824 data.height,
36825 data.widthSegments,
36826 data.heightSegments
36827 );
36828
36829 break;
36830
36831 case 'BoxGeometry':
36832 case 'BoxBufferGeometry':
36833 case 'CubeGeometry': // backwards compatible
36834
36835 geometry = new Geometries[ data.type ](
36836 data.width,
36837 data.height,
36838 data.depth,
36839 data.widthSegments,
36840 data.heightSegments,
36841 data.depthSegments
36842 );
36843
36844 break;
36845
36846 case 'CircleGeometry':
36847 case 'CircleBufferGeometry':
36848
36849 geometry = new Geometries[ data.type ](
36850 data.radius,
36851 data.segments,
36852 data.thetaStart,
36853 data.thetaLength
36854 );
36855
36856 break;
36857
36858 case 'CylinderGeometry':
36859 case 'CylinderBufferGeometry':
36860
36861 geometry = new Geometries[ data.type ](
36862 data.radiusTop,
36863 data.radiusBottom,
36864 data.height,
36865 data.radialSegments,
36866 data.heightSegments,
36867 data.openEnded,
36868 data.thetaStart,
36869 data.thetaLength
36870 );
36871
36872 break;
36873
36874 case 'ConeGeometry':
36875 case 'ConeBufferGeometry':
36876
36877 geometry = new Geometries[ data.type ](
36878 data.radius,
36879 data.height,
36880 data.radialSegments,
36881 data.heightSegments,
36882 data.openEnded,
36883 data.thetaStart,
36884 data.thetaLength
36885 );
36886
36887 break;
36888
36889 case 'SphereGeometry':
36890 case 'SphereBufferGeometry':
36891
36892 geometry = new Geometries[ data.type ](
36893 data.radius,
36894 data.widthSegments,
36895 data.heightSegments,
36896 data.phiStart,
36897 data.phiLength,
36898 data.thetaStart,
36899 data.thetaLength
36900 );
36901
36902 break;
36903
36904 case 'DodecahedronGeometry':
36905 case 'DodecahedronBufferGeometry':
36906 case 'IcosahedronGeometry':
36907 case 'IcosahedronBufferGeometry':
36908 case 'OctahedronGeometry':
36909 case 'OctahedronBufferGeometry':
36910 case 'TetrahedronGeometry':
36911 case 'TetrahedronBufferGeometry':
36912
36913 geometry = new Geometries[ data.type ](
36914 data.radius,
36915 data.detail
36916 );
36917
36918 break;
36919
36920 case 'RingGeometry':
36921 case 'RingBufferGeometry':
36922
36923 geometry = new Geometries[ data.type ](
36924 data.innerRadius,
36925 data.outerRadius,
36926 data.thetaSegments,
36927 data.phiSegments,
36928 data.thetaStart,
36929 data.thetaLength
36930 );
36931
36932 break;
36933
36934 case 'TorusGeometry':
36935 case 'TorusBufferGeometry':
36936
36937 geometry = new Geometries[ data.type ](
36938 data.radius,
36939 data.tube,
36940 data.radialSegments,
36941 data.tubularSegments,
36942 data.arc
36943 );
36944
36945 break;
36946
36947 case 'TorusKnotGeometry':
36948 case 'TorusKnotBufferGeometry':
36949
36950 geometry = new Geometries[ data.type ](
36951 data.radius,
36952 data.tube,
36953 data.tubularSegments,
36954 data.radialSegments,
36955 data.p,
36956 data.q
36957 );
36958
36959 break;
36960
36961 case 'LatheGeometry':
36962 case 'LatheBufferGeometry':
36963
36964 geometry = new Geometries[ data.type ](
36965 data.points,
36966 data.segments,
36967 data.phiStart,
36968 data.phiLength
36969 );
36970
36971 break;
36972
36973 case 'PolyhedronGeometry':
36974 case 'PolyhedronBufferGeometry':
36975
36976 geometry = new Geometries[ data.type ](
36977 data.vertices,
36978 data.indices,
36979 data.radius,
36980 data.details
36981 );
36982
36983 break;
36984
36985 case 'ShapeGeometry':
36986 case 'ShapeBufferGeometry':
36987
36988 var geometryShapes = [];
36989
36990 for ( var j = 0, jl = data.shapes.length; j < jl; j ++ ) {
36991
36992 var shape = shapes[ data.shapes[ j ] ];
36993
36994 geometryShapes.push( shape );
36995
36996 }
36997
36998 geometry = new Geometries[ data.type ](
36999 geometryShapes,
37000 data.curveSegments
37001 );
37002
37003 break;
37004
37005 case 'BufferGeometry':
37006
37007 geometry = bufferGeometryLoader.parse( data );
37008
37009 break;
37010
37011 case 'Geometry':
37012
37013 geometry = geometryLoader.parse( data, this.texturePath ).geometry;
37014
37015 break;
37016
37017 default:
37018
37019 console.warn( 'THREE.ObjectLoader: Unsupported geometry type "' + data.type + '"' );
37020
37021 continue;
37022
37023 }
37024
37025 geometry.uuid = data.uuid;
37026
37027 if ( data.name !== undefined ) geometry.name = data.name;
37028
37029 geometries[ data.uuid ] = geometry;
37030
37031 }
37032
37033 }
37034
37035 return geometries;
37036
37037 },
37038
37039 parseMaterials: function ( json, textures ) {
37040
37041 var materials = {};
37042
37043 if ( json !== undefined ) {
37044
37045 var loader = new MaterialLoader();
37046 loader.setTextures( textures );
37047
37048 for ( var i = 0, l = json.length; i < l; i ++ ) {
37049
37050 var data = json[ i ];
37051
37052 if ( data.type === 'MultiMaterial' ) {
37053
37054 // Deprecated
37055
37056 var array = [];
37057
37058 for ( var j = 0; j < data.materials.length; j ++ ) {
37059
37060 array.push( loader.parse( data.materials[ j ] ) );
37061
37062 }
37063
37064 materials[ data.uuid ] = array;
37065
37066 } else {
37067
37068 materials[ data.uuid ] = loader.parse( data );
37069
37070 }
37071
37072 }
37073
37074 }
37075
37076 return materials;
37077
37078 },
37079
37080 parseAnimations: function ( json ) {
37081
37082 var animations = [];
37083
37084 for ( var i = 0; i < json.length; i ++ ) {
37085
37086 var clip = AnimationClip.parse( json[ i ] );
37087
37088 animations.push( clip );
37089
37090 }
37091
37092 return animations;
37093
37094 },
37095
37096 parseImages: function ( json, onLoad ) {
37097
37098 var scope = this;
37099 var images = {};
37100
37101 function loadImage( url ) {
37102
37103 scope.manager.itemStart( url );
37104
37105 return loader.load( url, function () {
37106
37107 scope.manager.itemEnd( url );
37108
37109 }, undefined, function () {
37110
37111 scope.manager.itemEnd( url );
37112 scope.manager.itemError( url );
37113
37114 } );
37115
37116 }
37117
37118 if ( json !== undefined && json.length > 0 ) {
37119
37120 var manager = new LoadingManager( onLoad );
37121
37122 var loader = new ImageLoader( manager );
37123 loader.setCrossOrigin( this.crossOrigin );
37124
37125 for ( var i = 0, l = json.length; i < l; i ++ ) {
37126
37127 var image = json[ i ];
37128 var path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( image.url ) ? image.url : scope.texturePath + image.url;
37129
37130 images[ image.uuid ] = loadImage( path );
37131
37132 }
37133
37134 }
37135
37136 return images;
37137
37138 },
37139
37140 parseTextures: function ( json, images ) {
37141
37142 function parseConstant( value, type ) {
37143
37144 if ( typeof value === 'number' ) return value;
37145
37146 console.warn( 'THREE.ObjectLoader.parseTexture: Constant should be in numeric form.', value );
37147
37148 return type[ value ];
37149
37150 }
37151
37152 var textures = {};
37153
37154 if ( json !== undefined ) {
37155
37156 for ( var i = 0, l = json.length; i < l; i ++ ) {
37157
37158 var data = json[ i ];
37159
37160 if ( data.image === undefined ) {
37161
37162 console.warn( 'THREE.ObjectLoader: No "image" specified for', data.uuid );
37163
37164 }
37165
37166 if ( images[ data.image ] === undefined ) {
37167
37168 console.warn( 'THREE.ObjectLoader: Undefined image', data.image );
37169
37170 }
37171
37172 var texture = new Texture( images[ data.image ] );
37173 texture.needsUpdate = true;
37174
37175 texture.uuid = data.uuid;
37176
37177 if ( data.name !== undefined ) texture.name = data.name;
37178
37179 if ( data.mapping !== undefined ) texture.mapping = parseConstant( data.mapping, TEXTURE_MAPPING );
37180
37181 if ( data.offset !== undefined ) texture.offset.fromArray( data.offset );
37182 if ( data.repeat !== undefined ) texture.repeat.fromArray( data.repeat );
37183 if ( data.center !== undefined ) texture.center.fromArray( data.center );
37184 if ( data.rotation !== undefined ) texture.rotation = data.rotation;
37185
37186 if ( data.wrap !== undefined ) {
37187
37188 texture.wrapS = parseConstant( data.wrap[ 0 ], TEXTURE_WRAPPING );
37189 texture.wrapT = parseConstant( data.wrap[ 1 ], TEXTURE_WRAPPING );
37190
37191 }
37192
37193 if ( data.format !== undefined ) texture.format = data.format;
37194
37195 if ( data.minFilter !== undefined ) texture.minFilter = parseConstant( data.minFilter, TEXTURE_FILTER );
37196 if ( data.magFilter !== undefined ) texture.magFilter = parseConstant( data.magFilter, TEXTURE_FILTER );
37197 if ( data.anisotropy !== undefined ) texture.anisotropy = data.anisotropy;
37198
37199 if ( data.flipY !== undefined ) texture.flipY = data.flipY;
37200
37201 textures[ data.uuid ] = texture;
37202
37203 }
37204
37205 }
37206
37207 return textures;
37208
37209 },
37210
37211 parseObject: function ( data, geometries, materials ) {
37212
37213 var object;
37214
37215 function getGeometry( name ) {
37216
37217 if ( geometries[ name ] === undefined ) {
37218
37219 console.warn( 'THREE.ObjectLoader: Undefined geometry', name );
37220
37221 }
37222
37223 return geometries[ name ];
37224
37225 }
37226
37227 function getMaterial( name ) {
37228
37229 if ( name === undefined ) return undefined;
37230
37231 if ( Array.isArray( name ) ) {
37232
37233 var array = [];
37234
37235 for ( var i = 0, l = name.length; i < l; i ++ ) {
37236
37237 var uuid = name[ i ];
37238
37239 if ( materials[ uuid ] === undefined ) {
37240
37241 console.warn( 'THREE.ObjectLoader: Undefined material', uuid );
37242
37243 }
37244
37245 array.push( materials[ uuid ] );
37246
37247 }
37248
37249 return array;
37250
37251 }
37252
37253 if ( materials[ name ] === undefined ) {
37254
37255 console.warn( 'THREE.ObjectLoader: Undefined material', name );
37256
37257 }
37258
37259 return materials[ name ];
37260
37261 }
37262
37263 switch ( data.type ) {
37264
37265 case 'Scene':
37266
37267 object = new Scene();
37268
37269 if ( data.background !== undefined ) {
37270
37271 if ( Number.isInteger( data.background ) ) {
37272
37273 object.background = new Color( data.background );
37274
37275 }
37276
37277 }
37278
37279 if ( data.fog !== undefined ) {
37280
37281 if ( data.fog.type === 'Fog' ) {
37282
37283 object.fog = new Fog( data.fog.color, data.fog.near, data.fog.far );
37284
37285 } else if ( data.fog.type === 'FogExp2' ) {
37286
37287 object.fog = new FogExp2( data.fog.color, data.fog.density );
37288
37289 }
37290
37291 }
37292
37293 break;
37294
37295 case 'PerspectiveCamera':
37296
37297 object = new PerspectiveCamera( data.fov, data.aspect, data.near, data.far );
37298
37299 if ( data.focus !== undefined ) object.focus = data.focus;
37300 if ( data.zoom !== undefined ) object.zoom = data.zoom;
37301 if ( data.filmGauge !== undefined ) object.filmGauge = data.filmGauge;
37302 if ( data.filmOffset !== undefined ) object.filmOffset = data.filmOffset;
37303 if ( data.view !== undefined ) object.view = Object.assign( {}, data.view );
37304
37305 break;
37306
37307 case 'OrthographicCamera':
37308
37309 object = new OrthographicCamera( data.left, data.right, data.top, data.bottom, data.near, data.far );
37310
37311 if ( data.zoom !== undefined ) object.zoom = data.zoom;
37312 if ( data.view !== undefined ) object.view = Object.assign( {}, data.view );
37313
37314 break;
37315
37316 case 'AmbientLight':
37317
37318 object = new AmbientLight( data.color, data.intensity );
37319
37320 break;
37321
37322 case 'DirectionalLight':
37323
37324 object = new DirectionalLight( data.color, data.intensity );
37325
37326 break;
37327
37328 case 'PointLight':
37329
37330 object = new PointLight( data.color, data.intensity, data.distance, data.decay );
37331
37332 break;
37333
37334 case 'RectAreaLight':
37335
37336 object = new RectAreaLight( data.color, data.intensity, data.width, data.height );
37337
37338 break;
37339
37340 case 'SpotLight':
37341
37342 object = new SpotLight( data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay );
37343
37344 break;
37345
37346 case 'HemisphereLight':
37347
37348 object = new HemisphereLight( data.color, data.groundColor, data.intensity );
37349
37350 break;
37351
37352 case 'SkinnedMesh':
37353
37354 console.warn( 'THREE.ObjectLoader.parseObject() does not support SkinnedMesh yet.' );
37355
37356 case 'Mesh':
37357
37358 var geometry = getGeometry( data.geometry );
37359 var material = getMaterial( data.material );
37360
37361 if ( geometry.bones && geometry.bones.length > 0 ) {
37362
37363 object = new SkinnedMesh( geometry, material );
37364
37365 } else {
37366
37367 object = new Mesh( geometry, material );
37368
37369 }
37370
37371 break;
37372
37373 case 'LOD':
37374
37375 object = new LOD();
37376
37377 break;
37378
37379 case 'Line':
37380
37381 object = new Line( getGeometry( data.geometry ), getMaterial( data.material ), data.mode );
37382
37383 break;
37384
37385 case 'LineLoop':
37386
37387 object = new LineLoop( getGeometry( data.geometry ), getMaterial( data.material ) );
37388
37389 break;
37390
37391 case 'LineSegments':
37392
37393 object = new LineSegments( getGeometry( data.geometry ), getMaterial( data.material ) );
37394
37395 break;
37396
37397 case 'PointCloud':
37398 case 'Points':
37399
37400 object = new Points( getGeometry( data.geometry ), getMaterial( data.material ) );
37401
37402 break;
37403
37404 case 'Sprite':
37405
37406 object = new Sprite( getMaterial( data.material ) );
37407
37408 break;
37409
37410 case 'Group':
37411
37412 object = new Group();
37413
37414 break;
37415
37416 default:
37417
37418 object = new Object3D();
37419
37420 }
37421
37422 object.uuid = data.uuid;
37423
37424 if ( data.name !== undefined ) object.name = data.name;
37425
37426 if ( data.matrix !== undefined ) {
37427
37428 object.matrix.fromArray( data.matrix );
37429
37430 if ( data.matrixAutoUpdate !== undefined ) object.matrixAutoUpdate = data.matrixAutoUpdate;
37431 if ( object.matrixAutoUpdate ) object.matrix.decompose( object.position, object.quaternion, object.scale );
37432
37433 } else {
37434
37435 if ( data.position !== undefined ) object.position.fromArray( data.position );
37436 if ( data.rotation !== undefined ) object.rotation.fromArray( data.rotation );
37437 if ( data.quaternion !== undefined ) object.quaternion.fromArray( data.quaternion );
37438 if ( data.scale !== undefined ) object.scale.fromArray( data.scale );
37439
37440 }
37441
37442 if ( data.castShadow !== undefined ) object.castShadow = data.castShadow;
37443 if ( data.receiveShadow !== undefined ) object.receiveShadow = data.receiveShadow;
37444
37445 if ( data.shadow ) {
37446
37447 if ( data.shadow.bias !== undefined ) object.shadow.bias = data.shadow.bias;
37448 if ( data.shadow.radius !== undefined ) object.shadow.radius = data.shadow.radius;
37449 if ( data.shadow.mapSize !== undefined ) object.shadow.mapSize.fromArray( data.shadow.mapSize );
37450 if ( data.shadow.camera !== undefined ) object.shadow.camera = this.parseObject( data.shadow.camera );
37451
37452 }
37453
37454 if ( data.visible !== undefined ) object.visible = data.visible;
37455 if ( data.frustumCulled !== undefined ) object.frustumCulled = data.frustumCulled;
37456 if ( data.renderOrder !== undefined ) object.renderOrder = data.renderOrder;
37457 if ( data.userData !== undefined ) object.userData = data.userData;
37458
37459 if ( data.children !== undefined ) {
37460
37461 var children = data.children;
37462
37463 for ( var i = 0; i < children.length; i ++ ) {
37464
37465 object.add( this.parseObject( children[ i ], geometries, materials ) );
37466
37467 }
37468
37469 }
37470
37471 if ( data.type === 'LOD' ) {
37472
37473 var levels = data.levels;
37474
37475 for ( var l = 0; l < levels.length; l ++ ) {
37476
37477 var level = levels[ l ];
37478 var child = object.getObjectByProperty( 'uuid', level.object );
37479
37480 if ( child !== undefined ) {
37481
37482 object.addLevel( child, level.distance );
37483
37484 }
37485
37486 }
37487
37488 }
37489
37490 return object;
37491
37492 }
37493
37494 } );
37495
37496 var TEXTURE_MAPPING = {
37497 UVMapping: UVMapping,
37498 CubeReflectionMapping: CubeReflectionMapping,
37499 CubeRefractionMapping: CubeRefractionMapping,
37500 EquirectangularReflectionMapping: EquirectangularReflectionMapping,
37501 EquirectangularRefractionMapping: EquirectangularRefractionMapping,
37502 SphericalReflectionMapping: SphericalReflectionMapping,
37503 CubeUVReflectionMapping: CubeUVReflectionMapping,
37504 CubeUVRefractionMapping: CubeUVRefractionMapping
37505 };
37506
37507 var TEXTURE_WRAPPING = {
37508 RepeatWrapping: RepeatWrapping,
37509 ClampToEdgeWrapping: ClampToEdgeWrapping,
37510 MirroredRepeatWrapping: MirroredRepeatWrapping
37511 };
37512
37513 var TEXTURE_FILTER = {
37514 NearestFilter: NearestFilter,
37515 NearestMipMapNearestFilter: NearestMipMapNearestFilter,
37516 NearestMipMapLinearFilter: NearestMipMapLinearFilter,
37517 LinearFilter: LinearFilter,
37518 LinearMipMapNearestFilter: LinearMipMapNearestFilter,
37519 LinearMipMapLinearFilter: LinearMipMapLinearFilter
37520 };
37521
37522 /**
37523 * @author thespite / http://clicktorelease.com/
37524 */
37525
37526 function ImageBitmapLoader( manager ) {
37527
37528 if ( typeof createImageBitmap === 'undefined' ) {
37529
37530 console.warn( 'THREE.ImageBitmapLoader: createImageBitmap() not supported.' );
37531
37532 }
37533
37534 if ( typeof fetch === 'undefined' ) {
37535
37536 console.warn( 'THREE.ImageBitmapLoader: fetch() not supported.' );
37537
37538 }
37539
37540 this.manager = manager !== undefined ? manager : DefaultLoadingManager;
37541 this.options = undefined;
37542
37543 }
37544
37545 ImageBitmapLoader.prototype = {
37546
37547 constructor: ImageBitmapLoader,
37548
37549 setOptions: function setOptions( options ) {
37550
37551 this.options = options;
37552
37553 return this;
37554
37555 },
37556
37557 load: function load( url, onLoad, onProgress, onError ) {
37558
37559 if ( url === undefined ) url = '';
37560
37561 if ( this.path !== undefined ) url = this.path + url;
37562
37563 var scope = this;
37564
37565 var cached = Cache.get( url );
37566
37567 if ( cached !== undefined ) {
37568
37569 scope.manager.itemStart( url );
37570
37571 setTimeout( function () {
37572
37573 if ( onLoad ) onLoad( cached );
37574
37575 scope.manager.itemEnd( url );
37576
37577 }, 0 );
37578
37579 return cached;
37580
37581 }
37582
37583 fetch( url ).then( function ( res ) {
37584
37585 return res.blob();
37586
37587 } ).then( function ( blob ) {
37588
37589 return createImageBitmap( blob, scope.options );
37590
37591 } ).then( function ( imageBitmap ) {
37592
37593 Cache.add( url, imageBitmap );
37594
37595 if ( onLoad ) onLoad( imageBitmap );
37596
37597 scope.manager.itemEnd( url );
37598
37599 } ).catch( function ( e ) {
37600
37601 if ( onError ) onError( e );
37602
37603 scope.manager.itemEnd( url );
37604 scope.manager.itemError( url );
37605
37606 } );
37607
37608 },
37609
37610 setCrossOrigin: function ( /* value */ ) {
37611
37612 return this;
37613
37614 },
37615
37616 setPath: function ( value ) {
37617
37618 this.path = value;
37619 return this;
37620
37621 }
37622
37623 };
37624
37625 /**
37626 * @author zz85 / http://www.lab4games.net/zz85/blog
37627 * minimal class for proxing functions to Path. Replaces old "extractSubpaths()"
37628 **/
37629
37630 function ShapePath() {
37631
37632 this.type = 'ShapePath';
37633
37634 this.color = new Color();
37635
37636 this.subPaths = [];
37637 this.currentPath = null;
37638
37639 }
37640
37641 Object.assign( ShapePath.prototype, {
37642
37643 moveTo: function ( x, y ) {
37644
37645 this.currentPath = new Path();
37646 this.subPaths.push( this.currentPath );
37647 this.currentPath.moveTo( x, y );
37648
37649 },
37650
37651 lineTo: function ( x, y ) {
37652
37653 this.currentPath.lineTo( x, y );
37654
37655 },
37656
37657 quadraticCurveTo: function ( aCPx, aCPy, aX, aY ) {
37658
37659 this.currentPath.quadraticCurveTo( aCPx, aCPy, aX, aY );
37660
37661 },
37662
37663 bezierCurveTo: function ( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) {
37664
37665 this.currentPath.bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY );
37666
37667 },
37668
37669 splineThru: function ( pts ) {
37670
37671 this.currentPath.splineThru( pts );
37672
37673 },
37674
37675 toShapes: function ( isCCW, noHoles ) {
37676
37677 function toShapesNoHoles( inSubpaths ) {
37678
37679 var shapes = [];
37680
37681 for ( var i = 0, l = inSubpaths.length; i < l; i ++ ) {
37682
37683 var tmpPath = inSubpaths[ i ];
37684
37685 var tmpShape = new Shape();
37686 tmpShape.curves = tmpPath.curves;
37687
37688 shapes.push( tmpShape );
37689
37690 }
37691
37692 return shapes;
37693
37694 }
37695
37696 function isPointInsidePolygon( inPt, inPolygon ) {
37697
37698 var polyLen = inPolygon.length;
37699
37700 // inPt on polygon contour => immediate success or
37701 // toggling of inside/outside at every single! intersection point of an edge
37702 // with the horizontal line through inPt, left of inPt
37703 // not counting lowerY endpoints of edges and whole edges on that line
37704 var inside = false;
37705 for ( var p = polyLen - 1, q = 0; q < polyLen; p = q ++ ) {
37706
37707 var edgeLowPt = inPolygon[ p ];
37708 var edgeHighPt = inPolygon[ q ];
37709
37710 var edgeDx = edgeHighPt.x - edgeLowPt.x;
37711 var edgeDy = edgeHighPt.y - edgeLowPt.y;
37712
37713 if ( Math.abs( edgeDy ) > Number.EPSILON ) {
37714
37715 // not parallel
37716 if ( edgeDy < 0 ) {
37717
37718 edgeLowPt = inPolygon[ q ]; edgeDx = - edgeDx;
37719 edgeHighPt = inPolygon[ p ]; edgeDy = - edgeDy;
37720
37721 }
37722 if ( ( inPt.y < edgeLowPt.y ) || ( inPt.y > edgeHighPt.y ) ) continue;
37723
37724 if ( inPt.y === edgeLowPt.y ) {
37725
37726 if ( inPt.x === edgeLowPt.x ) return true; // inPt is on contour ?
37727 // continue; // no intersection or edgeLowPt => doesn't count !!!
37728
37729 } else {
37730
37731 var perpEdge = edgeDy * ( inPt.x - edgeLowPt.x ) - edgeDx * ( inPt.y - edgeLowPt.y );
37732 if ( perpEdge === 0 ) return true; // inPt is on contour ?
37733 if ( perpEdge < 0 ) continue;
37734 inside = ! inside; // true intersection left of inPt
37735
37736 }
37737
37738 } else {
37739
37740 // parallel or collinear
37741 if ( inPt.y !== edgeLowPt.y ) continue; // parallel
37742 // edge lies on the same horizontal line as inPt
37743 if ( ( ( edgeHighPt.x <= inPt.x ) && ( inPt.x <= edgeLowPt.x ) ) ||
37744 ( ( edgeLowPt.x <= inPt.x ) && ( inPt.x <= edgeHighPt.x ) ) ) return true; // inPt: Point on contour !
37745 // continue;
37746
37747 }
37748
37749 }
37750
37751 return inside;
37752
37753 }
37754
37755 var isClockWise = ShapeUtils.isClockWise;
37756
37757 var subPaths = this.subPaths;
37758 if ( subPaths.length === 0 ) return [];
37759
37760 if ( noHoles === true ) return toShapesNoHoles( subPaths );
37761
37762
37763 var solid, tmpPath, tmpShape, shapes = [];
37764
37765 if ( subPaths.length === 1 ) {
37766
37767 tmpPath = subPaths[ 0 ];
37768 tmpShape = new Shape();
37769 tmpShape.curves = tmpPath.curves;
37770 shapes.push( tmpShape );
37771 return shapes;
37772
37773 }
37774
37775 var holesFirst = ! isClockWise( subPaths[ 0 ].getPoints() );
37776 holesFirst = isCCW ? ! holesFirst : holesFirst;
37777
37778 // console.log("Holes first", holesFirst);
37779
37780 var betterShapeHoles = [];
37781 var newShapes = [];
37782 var newShapeHoles = [];
37783 var mainIdx = 0;
37784 var tmpPoints;
37785
37786 newShapes[ mainIdx ] = undefined;
37787 newShapeHoles[ mainIdx ] = [];
37788
37789 for ( var i = 0, l = subPaths.length; i < l; i ++ ) {
37790
37791 tmpPath = subPaths[ i ];
37792 tmpPoints = tmpPath.getPoints();
37793 solid = isClockWise( tmpPoints );
37794 solid = isCCW ? ! solid : solid;
37795
37796 if ( solid ) {
37797
37798 if ( ( ! holesFirst ) && ( newShapes[ mainIdx ] ) ) mainIdx ++;
37799
37800 newShapes[ mainIdx ] = { s: new Shape(), p: tmpPoints };
37801 newShapes[ mainIdx ].s.curves = tmpPath.curves;
37802
37803 if ( holesFirst ) mainIdx ++;
37804 newShapeHoles[ mainIdx ] = [];
37805
37806 //console.log('cw', i);
37807
37808 } else {
37809
37810 newShapeHoles[ mainIdx ].push( { h: tmpPath, p: tmpPoints[ 0 ] } );
37811
37812 //console.log('ccw', i);
37813
37814 }
37815
37816 }
37817
37818 // only Holes? -> probably all Shapes with wrong orientation
37819 if ( ! newShapes[ 0 ] ) return toShapesNoHoles( subPaths );
37820
37821
37822 if ( newShapes.length > 1 ) {
37823
37824 var ambiguous = false;
37825 var toChange = [];
37826
37827 for ( var sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
37828
37829 betterShapeHoles[ sIdx ] = [];
37830
37831 }
37832
37833 for ( var sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
37834
37835 var sho = newShapeHoles[ sIdx ];
37836
37837 for ( var hIdx = 0; hIdx < sho.length; hIdx ++ ) {
37838
37839 var ho = sho[ hIdx ];
37840 var hole_unassigned = true;
37841
37842 for ( var s2Idx = 0; s2Idx < newShapes.length; s2Idx ++ ) {
37843
37844 if ( isPointInsidePolygon( ho.p, newShapes[ s2Idx ].p ) ) {
37845
37846 if ( sIdx !== s2Idx ) toChange.push( { froms: sIdx, tos: s2Idx, hole: hIdx } );
37847 if ( hole_unassigned ) {
37848
37849 hole_unassigned = false;
37850 betterShapeHoles[ s2Idx ].push( ho );
37851
37852 } else {
37853
37854 ambiguous = true;
37855
37856 }
37857
37858 }
37859
37860 }
37861 if ( hole_unassigned ) {
37862
37863 betterShapeHoles[ sIdx ].push( ho );
37864
37865 }
37866
37867 }
37868
37869 }
37870 // console.log("ambiguous: ", ambiguous);
37871 if ( toChange.length > 0 ) {
37872
37873 // console.log("to change: ", toChange);
37874 if ( ! ambiguous ) newShapeHoles = betterShapeHoles;
37875
37876 }
37877
37878 }
37879
37880 var tmpHoles;
37881
37882 for ( var i = 0, il = newShapes.length; i < il; i ++ ) {
37883
37884 tmpShape = newShapes[ i ].s;
37885 shapes.push( tmpShape );
37886 tmpHoles = newShapeHoles[ i ];
37887
37888 for ( var j = 0, jl = tmpHoles.length; j < jl; j ++ ) {
37889
37890 tmpShape.holes.push( tmpHoles[ j ].h );
37891
37892 }
37893
37894 }
37895
37896 //console.log("shape", shapes);
37897
37898 return shapes;
37899
37900 }
37901
37902 } );
37903
37904 /**
37905 * @author zz85 / http://www.lab4games.net/zz85/blog
37906 * @author mrdoob / http://mrdoob.com/
37907 */
37908
37909 function Font( data ) {
37910
37911 this.type = 'Font';
37912
37913 this.data = data;
37914
37915 }
37916
37917 Object.assign( Font.prototype, {
37918
37919 isFont: true,
37920
37921 generateShapes: function ( text, size, divisions ) {
37922
37923 if ( size === undefined ) size = 100;
37924 if ( divisions === undefined ) divisions = 4;
37925
37926 var shapes = [];
37927 var paths = createPaths( text, size, divisions, this.data );
37928
37929 for ( var p = 0, pl = paths.length; p < pl; p ++ ) {
37930
37931 Array.prototype.push.apply( shapes, paths[ p ].toShapes() );
37932
37933 }
37934
37935 return shapes;
37936
37937 }
37938
37939 } );
37940
37941 function createPaths( text, size, divisions, data ) {
37942
37943 var chars = String( text ).split( '' );
37944 var scale = size / data.resolution;
37945 var line_height = ( data.boundingBox.yMax - data.boundingBox.yMin + data.underlineThickness ) * scale;
37946
37947 var paths = [];
37948
37949 var offsetX = 0, offsetY = 0;
37950
37951 for ( var i = 0; i < chars.length; i ++ ) {
37952
37953 var char = chars[ i ];
37954
37955 if ( char === '\n' ) {
37956
37957 offsetX = 0;
37958 offsetY -= line_height;
37959
37960 } else {
37961
37962 var ret = createPath( char, divisions, scale, offsetX, offsetY, data );
37963 offsetX += ret.offsetX;
37964 paths.push( ret.path );
37965
37966 }
37967
37968 }
37969
37970 return paths;
37971
37972 }
37973
37974 function createPath( char, divisions, scale, offsetX, offsetY, data ) {
37975
37976 var glyph = data.glyphs[ char ] || data.glyphs[ '?' ];
37977
37978 if ( ! glyph ) return;
37979
37980 var path = new ShapePath();
37981
37982 var x, y, cpx, cpy, cpx1, cpy1, cpx2, cpy2;
37983
37984 if ( glyph.o ) {
37985
37986 var outline = glyph._cachedOutline || ( glyph._cachedOutline = glyph.o.split( ' ' ) );
37987
37988 for ( var i = 0, l = outline.length; i < l; ) {
37989
37990 var action = outline[ i ++ ];
37991
37992 switch ( action ) {
37993
37994 case 'm': // moveTo
37995
37996 x = outline[ i ++ ] * scale + offsetX;
37997 y = outline[ i ++ ] * scale + offsetY;
37998
37999 path.moveTo( x, y );
38000
38001 break;
38002
38003 case 'l': // lineTo
38004
38005 x = outline[ i ++ ] * scale + offsetX;
38006 y = outline[ i ++ ] * scale + offsetY;
38007
38008 path.lineTo( x, y );
38009
38010 break;
38011
38012 case 'q': // quadraticCurveTo
38013
38014 cpx = outline[ i ++ ] * scale + offsetX;
38015 cpy = outline[ i ++ ] * scale + offsetY;
38016 cpx1 = outline[ i ++ ] * scale + offsetX;
38017 cpy1 = outline[ i ++ ] * scale + offsetY;
38018
38019 path.quadraticCurveTo( cpx1, cpy1, cpx, cpy );
38020
38021 break;
38022
38023 case 'b': // bezierCurveTo
38024
38025 cpx = outline[ i ++ ] * scale + offsetX;
38026 cpy = outline[ i ++ ] * scale + offsetY;
38027 cpx1 = outline[ i ++ ] * scale + offsetX;
38028 cpy1 = outline[ i ++ ] * scale + offsetY;
38029 cpx2 = outline[ i ++ ] * scale + offsetX;
38030 cpy2 = outline[ i ++ ] * scale + offsetY;
38031
38032 path.bezierCurveTo( cpx1, cpy1, cpx2, cpy2, cpx, cpy );
38033
38034 break;
38035
38036 }
38037
38038 }
38039
38040 }
38041
38042 return { offsetX: glyph.ha * scale, path: path };
38043
38044 }
38045
38046 /**
38047 * @author mrdoob / http://mrdoob.com/
38048 */
38049
38050 function FontLoader( manager ) {
38051
38052 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
38053
38054 }
38055
38056 Object.assign( FontLoader.prototype, {
38057
38058 load: function ( url, onLoad, onProgress, onError ) {
38059
38060 var scope = this;
38061
38062 var loader = new FileLoader( this.manager );
38063 loader.setPath( this.path );
38064 loader.load( url, function ( text ) {
38065
38066 var json;
38067
38068 try {
38069
38070 json = JSON.parse( text );
38071
38072 } catch ( e ) {
38073
38074 console.warn( 'THREE.FontLoader: typeface.js support is being deprecated. Use typeface.json instead.' );
38075 json = JSON.parse( text.substring( 65, text.length - 2 ) );
38076
38077 }
38078
38079 var font = scope.parse( json );
38080
38081 if ( onLoad ) onLoad( font );
38082
38083 }, onProgress, onError );
38084
38085 },
38086
38087 parse: function ( json ) {
38088
38089 return new Font( json );
38090
38091 },
38092
38093 setPath: function ( value ) {
38094
38095 this.path = value;
38096 return this;
38097
38098 }
38099
38100 } );
38101
38102 /**
38103 * @author mrdoob / http://mrdoob.com/
38104 */
38105
38106 var context;
38107
38108 var AudioContext = {
38109
38110 getContext: function () {
38111
38112 if ( context === undefined ) {
38113
38114 context = new ( window.AudioContext || window.webkitAudioContext )();
38115
38116 }
38117
38118 return context;
38119
38120 },
38121
38122 setContext: function ( value ) {
38123
38124 context = value;
38125
38126 }
38127
38128 };
38129
38130 /**
38131 * @author Reece Aaron Lecrivain / http://reecenotes.com/
38132 */
38133
38134 function AudioLoader( manager ) {
38135
38136 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
38137
38138 }
38139
38140 Object.assign( AudioLoader.prototype, {
38141
38142 load: function ( url, onLoad, onProgress, onError ) {
38143
38144 var loader = new FileLoader( this.manager );
38145 loader.setResponseType( 'arraybuffer' );
38146 loader.load( url, function ( buffer ) {
38147
38148 var context = AudioContext.getContext();
38149
38150 context.decodeAudioData( buffer, function ( audioBuffer ) {
38151
38152 onLoad( audioBuffer );
38153
38154 } );
38155
38156 }, onProgress, onError );
38157
38158 }
38159
38160 } );
38161
38162 /**
38163 * @author mrdoob / http://mrdoob.com/
38164 */
38165
38166 function StereoCamera() {
38167
38168 this.type = 'StereoCamera';
38169
38170 this.aspect = 1;
38171
38172 this.eyeSep = 0.064;
38173
38174 this.cameraL = new PerspectiveCamera();
38175 this.cameraL.layers.enable( 1 );
38176 this.cameraL.matrixAutoUpdate = false;
38177
38178 this.cameraR = new PerspectiveCamera();
38179 this.cameraR.layers.enable( 2 );
38180 this.cameraR.matrixAutoUpdate = false;
38181
38182 }
38183
38184 Object.assign( StereoCamera.prototype, {
38185
38186 update: ( function () {
38187
38188 var instance, focus, fov, aspect, near, far, zoom, eyeSep;
38189
38190 var eyeRight = new Matrix4();
38191 var eyeLeft = new Matrix4();
38192
38193 return function update( camera ) {
38194
38195 var needsUpdate = instance !== this || focus !== camera.focus || fov !== camera.fov ||
38196 aspect !== camera.aspect * this.aspect || near !== camera.near ||
38197 far !== camera.far || zoom !== camera.zoom || eyeSep !== this.eyeSep;
38198
38199 if ( needsUpdate ) {
38200
38201 instance = this;
38202 focus = camera.focus;
38203 fov = camera.fov;
38204 aspect = camera.aspect * this.aspect;
38205 near = camera.near;
38206 far = camera.far;
38207 zoom = camera.zoom;
38208
38209 // Off-axis stereoscopic effect based on
38210 // http://paulbourke.net/stereographics/stereorender/
38211
38212 var projectionMatrix = camera.projectionMatrix.clone();
38213 eyeSep = this.eyeSep / 2;
38214 var eyeSepOnProjection = eyeSep * near / focus;
38215 var ymax = ( near * Math.tan( _Math.DEG2RAD * fov * 0.5 ) ) / zoom;
38216 var xmin, xmax;
38217
38218 // translate xOffset
38219
38220 eyeLeft.elements[ 12 ] = - eyeSep;
38221 eyeRight.elements[ 12 ] = eyeSep;
38222
38223 // for left eye
38224
38225 xmin = - ymax * aspect + eyeSepOnProjection;
38226 xmax = ymax * aspect + eyeSepOnProjection;
38227
38228 projectionMatrix.elements[ 0 ] = 2 * near / ( xmax - xmin );
38229 projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
38230
38231 this.cameraL.projectionMatrix.copy( projectionMatrix );
38232
38233 // for right eye
38234
38235 xmin = - ymax * aspect - eyeSepOnProjection;
38236 xmax = ymax * aspect - eyeSepOnProjection;
38237
38238 projectionMatrix.elements[ 0 ] = 2 * near / ( xmax - xmin );
38239 projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
38240
38241 this.cameraR.projectionMatrix.copy( projectionMatrix );
38242
38243 }
38244
38245 this.cameraL.matrixWorld.copy( camera.matrixWorld ).multiply( eyeLeft );
38246 this.cameraR.matrixWorld.copy( camera.matrixWorld ).multiply( eyeRight );
38247
38248 };
38249
38250 } )()
38251
38252 } );
38253
38254 /**
38255 * Camera for rendering cube maps
38256 * - renders scene into axis-aligned cube
38257 *
38258 * @author alteredq / http://alteredqualia.com/
38259 */
38260
38261 function CubeCamera( near, far, cubeResolution ) {
38262
38263 Object3D.call( this );
38264
38265 this.type = 'CubeCamera';
38266
38267 var fov = 90, aspect = 1;
38268
38269 var cameraPX = new PerspectiveCamera( fov, aspect, near, far );
38270 cameraPX.up.set( 0, - 1, 0 );
38271 cameraPX.lookAt( new Vector3( 1, 0, 0 ) );
38272 this.add( cameraPX );
38273
38274 var cameraNX = new PerspectiveCamera( fov, aspect, near, far );
38275 cameraNX.up.set( 0, - 1, 0 );
38276 cameraNX.lookAt( new Vector3( - 1, 0, 0 ) );
38277 this.add( cameraNX );
38278
38279 var cameraPY = new PerspectiveCamera( fov, aspect, near, far );
38280 cameraPY.up.set( 0, 0, 1 );
38281 cameraPY.lookAt( new Vector3( 0, 1, 0 ) );
38282 this.add( cameraPY );
38283
38284 var cameraNY = new PerspectiveCamera( fov, aspect, near, far );
38285 cameraNY.up.set( 0, 0, - 1 );
38286 cameraNY.lookAt( new Vector3( 0, - 1, 0 ) );
38287 this.add( cameraNY );
38288
38289 var cameraPZ = new PerspectiveCamera( fov, aspect, near, far );
38290 cameraPZ.up.set( 0, - 1, 0 );
38291 cameraPZ.lookAt( new Vector3( 0, 0, 1 ) );
38292 this.add( cameraPZ );
38293
38294 var cameraNZ = new PerspectiveCamera( fov, aspect, near, far );
38295 cameraNZ.up.set( 0, - 1, 0 );
38296 cameraNZ.lookAt( new Vector3( 0, 0, - 1 ) );
38297 this.add( cameraNZ );
38298
38299 var options = { format: RGBFormat, magFilter: LinearFilter, minFilter: LinearFilter };
38300
38301 this.renderTarget = new WebGLRenderTargetCube( cubeResolution, cubeResolution, options );
38302 this.renderTarget.texture.name = "CubeCamera";
38303
38304 this.update = function ( renderer, scene ) {
38305
38306 if ( this.parent === null ) this.updateMatrixWorld();
38307
38308 var renderTarget = this.renderTarget;
38309 var generateMipmaps = renderTarget.texture.generateMipmaps;
38310
38311 renderTarget.texture.generateMipmaps = false;
38312
38313 renderTarget.activeCubeFace = 0;
38314 renderer.render( scene, cameraPX, renderTarget );
38315
38316 renderTarget.activeCubeFace = 1;
38317 renderer.render( scene, cameraNX, renderTarget );
38318
38319 renderTarget.activeCubeFace = 2;
38320 renderer.render( scene, cameraPY, renderTarget );
38321
38322 renderTarget.activeCubeFace = 3;
38323 renderer.render( scene, cameraNY, renderTarget );
38324
38325 renderTarget.activeCubeFace = 4;
38326 renderer.render( scene, cameraPZ, renderTarget );
38327
38328 renderTarget.texture.generateMipmaps = generateMipmaps;
38329
38330 renderTarget.activeCubeFace = 5;
38331 renderer.render( scene, cameraNZ, renderTarget );
38332
38333 renderer.setRenderTarget( null );
38334
38335 };
38336
38337 this.clear = function ( renderer, color, depth, stencil ) {
38338
38339 var renderTarget = this.renderTarget;
38340
38341 for ( var i = 0; i < 6; i ++ ) {
38342
38343 renderTarget.activeCubeFace = i;
38344 renderer.setRenderTarget( renderTarget );
38345
38346 renderer.clear( color, depth, stencil );
38347
38348 }
38349
38350 renderer.setRenderTarget( null );
38351
38352 };
38353
38354 }
38355
38356 CubeCamera.prototype = Object.create( Object3D.prototype );
38357 CubeCamera.prototype.constructor = CubeCamera;
38358
38359 /**
38360 * @author mrdoob / http://mrdoob.com/
38361 */
38362
38363 function AudioListener() {
38364
38365 Object3D.call( this );
38366
38367 this.type = 'AudioListener';
38368
38369 this.context = AudioContext.getContext();
38370
38371 this.gain = this.context.createGain();
38372 this.gain.connect( this.context.destination );
38373
38374 this.filter = null;
38375
38376 }
38377
38378 AudioListener.prototype = Object.assign( Object.create( Object3D.prototype ), {
38379
38380 constructor: AudioListener,
38381
38382 getInput: function () {
38383
38384 return this.gain;
38385
38386 },
38387
38388 removeFilter: function ( ) {
38389
38390 if ( this.filter !== null ) {
38391
38392 this.gain.disconnect( this.filter );
38393 this.filter.disconnect( this.context.destination );
38394 this.gain.connect( this.context.destination );
38395 this.filter = null;
38396
38397 }
38398
38399 },
38400
38401 getFilter: function () {
38402
38403 return this.filter;
38404
38405 },
38406
38407 setFilter: function ( value ) {
38408
38409 if ( this.filter !== null ) {
38410
38411 this.gain.disconnect( this.filter );
38412 this.filter.disconnect( this.context.destination );
38413
38414 } else {
38415
38416 this.gain.disconnect( this.context.destination );
38417
38418 }
38419
38420 this.filter = value;
38421 this.gain.connect( this.filter );
38422 this.filter.connect( this.context.destination );
38423
38424 },
38425
38426 getMasterVolume: function () {
38427
38428 return this.gain.gain.value;
38429
38430 },
38431
38432 setMasterVolume: function ( value ) {
38433
38434 this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 );
38435
38436 },
38437
38438 updateMatrixWorld: ( function () {
38439
38440 var position = new Vector3();
38441 var quaternion = new Quaternion();
38442 var scale = new Vector3();
38443
38444 var orientation = new Vector3();
38445
38446 return function updateMatrixWorld( force ) {
38447
38448 Object3D.prototype.updateMatrixWorld.call( this, force );
38449
38450 var listener = this.context.listener;
38451 var up = this.up;
38452
38453 this.matrixWorld.decompose( position, quaternion, scale );
38454
38455 orientation.set( 0, 0, - 1 ).applyQuaternion( quaternion );
38456
38457 if ( listener.positionX ) {
38458
38459 listener.positionX.setValueAtTime( position.x, this.context.currentTime );
38460 listener.positionY.setValueAtTime( position.y, this.context.currentTime );
38461 listener.positionZ.setValueAtTime( position.z, this.context.currentTime );
38462 listener.forwardX.setValueAtTime( orientation.x, this.context.currentTime );
38463 listener.forwardY.setValueAtTime( orientation.y, this.context.currentTime );
38464 listener.forwardZ.setValueAtTime( orientation.z, this.context.currentTime );
38465 listener.upX.setValueAtTime( up.x, this.context.currentTime );
38466 listener.upY.setValueAtTime( up.y, this.context.currentTime );
38467 listener.upZ.setValueAtTime( up.z, this.context.currentTime );
38468
38469 } else {
38470
38471 listener.setPosition( position.x, position.y, position.z );
38472 listener.setOrientation( orientation.x, orientation.y, orientation.z, up.x, up.y, up.z );
38473
38474 }
38475
38476 };
38477
38478 } )()
38479
38480 } );
38481
38482 /**
38483 * @author mrdoob / http://mrdoob.com/
38484 * @author Reece Aaron Lecrivain / http://reecenotes.com/
38485 */
38486
38487 function Audio( listener ) {
38488
38489 Object3D.call( this );
38490
38491 this.type = 'Audio';
38492
38493 this.context = listener.context;
38494
38495 this.gain = this.context.createGain();
38496 this.gain.connect( listener.getInput() );
38497
38498 this.autoplay = false;
38499
38500 this.buffer = null;
38501 this.loop = false;
38502 this.startTime = 0;
38503 this.offset = 0;
38504 this.playbackRate = 1;
38505 this.isPlaying = false;
38506 this.hasPlaybackControl = true;
38507 this.sourceType = 'empty';
38508
38509 this.filters = [];
38510
38511 }
38512
38513 Audio.prototype = Object.assign( Object.create( Object3D.prototype ), {
38514
38515 constructor: Audio,
38516
38517 getOutput: function () {
38518
38519 return this.gain;
38520
38521 },
38522
38523 setNodeSource: function ( audioNode ) {
38524
38525 this.hasPlaybackControl = false;
38526 this.sourceType = 'audioNode';
38527 this.source = audioNode;
38528 this.connect();
38529
38530 return this;
38531
38532 },
38533
38534 setBuffer: function ( audioBuffer ) {
38535
38536 this.buffer = audioBuffer;
38537 this.sourceType = 'buffer';
38538
38539 if ( this.autoplay ) this.play();
38540
38541 return this;
38542
38543 },
38544
38545 play: function () {
38546
38547 if ( this.isPlaying === true ) {
38548
38549 console.warn( 'THREE.Audio: Audio is already playing.' );
38550 return;
38551
38552 }
38553
38554 if ( this.hasPlaybackControl === false ) {
38555
38556 console.warn( 'THREE.Audio: this Audio has no playback control.' );
38557 return;
38558
38559 }
38560
38561 var source = this.context.createBufferSource();
38562
38563 source.buffer = this.buffer;
38564 source.loop = this.loop;
38565 source.onended = this.onEnded.bind( this );
38566 source.playbackRate.setValueAtTime( this.playbackRate, this.startTime );
38567 this.startTime = this.context.currentTime;
38568 source.start( this.startTime, this.offset );
38569
38570 this.isPlaying = true;
38571
38572 this.source = source;
38573
38574 return this.connect();
38575
38576 },
38577
38578 pause: function () {
38579
38580 if ( this.hasPlaybackControl === false ) {
38581
38582 console.warn( 'THREE.Audio: this Audio has no playback control.' );
38583 return;
38584
38585 }
38586
38587 if ( this.isPlaying === true ) {
38588
38589 this.source.stop();
38590 this.offset += ( this.context.currentTime - this.startTime ) * this.playbackRate;
38591 this.isPlaying = false;
38592
38593 }
38594
38595 return this;
38596
38597 },
38598
38599 stop: function () {
38600
38601 if ( this.hasPlaybackControl === false ) {
38602
38603 console.warn( 'THREE.Audio: this Audio has no playback control.' );
38604 return;
38605
38606 }
38607
38608 this.source.stop();
38609 this.offset = 0;
38610 this.isPlaying = false;
38611
38612 return this;
38613
38614 },
38615
38616 connect: function () {
38617
38618 if ( this.filters.length > 0 ) {
38619
38620 this.source.connect( this.filters[ 0 ] );
38621
38622 for ( var i = 1, l = this.filters.length; i < l; i ++ ) {
38623
38624 this.filters[ i - 1 ].connect( this.filters[ i ] );
38625
38626 }
38627
38628 this.filters[ this.filters.length - 1 ].connect( this.getOutput() );
38629
38630 } else {
38631
38632 this.source.connect( this.getOutput() );
38633
38634 }
38635
38636 return this;
38637
38638 },
38639
38640 disconnect: function () {
38641
38642 if ( this.filters.length > 0 ) {
38643
38644 this.source.disconnect( this.filters[ 0 ] );
38645
38646 for ( var i = 1, l = this.filters.length; i < l; i ++ ) {
38647
38648 this.filters[ i - 1 ].disconnect( this.filters[ i ] );
38649
38650 }
38651
38652 this.filters[ this.filters.length - 1 ].disconnect( this.getOutput() );
38653
38654 } else {
38655
38656 this.source.disconnect( this.getOutput() );
38657
38658 }
38659
38660 return this;
38661
38662 },
38663
38664 getFilters: function () {
38665
38666 return this.filters;
38667
38668 },
38669
38670 setFilters: function ( value ) {
38671
38672 if ( ! value ) value = [];
38673
38674 if ( this.isPlaying === true ) {
38675
38676 this.disconnect();
38677 this.filters = value;
38678 this.connect();
38679
38680 } else {
38681
38682 this.filters = value;
38683
38684 }
38685
38686 return this;
38687
38688 },
38689
38690 getFilter: function () {
38691
38692 return this.getFilters()[ 0 ];
38693
38694 },
38695
38696 setFilter: function ( filter ) {
38697
38698 return this.setFilters( filter ? [ filter ] : [] );
38699
38700 },
38701
38702 setPlaybackRate: function ( value ) {
38703
38704 if ( this.hasPlaybackControl === false ) {
38705
38706 console.warn( 'THREE.Audio: this Audio has no playback control.' );
38707 return;
38708
38709 }
38710
38711 this.playbackRate = value;
38712
38713 if ( this.isPlaying === true ) {
38714
38715 this.source.playbackRate.setValueAtTime( this.playbackRate, this.context.currentTime );
38716
38717 }
38718
38719 return this;
38720
38721 },
38722
38723 getPlaybackRate: function () {
38724
38725 return this.playbackRate;
38726
38727 },
38728
38729 onEnded: function () {
38730
38731 this.isPlaying = false;
38732
38733 },
38734
38735 getLoop: function () {
38736
38737 if ( this.hasPlaybackControl === false ) {
38738
38739 console.warn( 'THREE.Audio: this Audio has no playback control.' );
38740 return false;
38741
38742 }
38743
38744 return this.loop;
38745
38746 },
38747
38748 setLoop: function ( value ) {
38749
38750 if ( this.hasPlaybackControl === false ) {
38751
38752 console.warn( 'THREE.Audio: this Audio has no playback control.' );
38753 return;
38754
38755 }
38756
38757 this.loop = value;
38758
38759 if ( this.isPlaying === true ) {
38760
38761 this.source.loop = this.loop;
38762
38763 }
38764
38765 return this;
38766
38767 },
38768
38769 getVolume: function () {
38770
38771 return this.gain.gain.value;
38772
38773 },
38774
38775 setVolume: function ( value ) {
38776
38777 this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 );
38778
38779 return this;
38780
38781 }
38782
38783 } );
38784
38785 /**
38786 * @author mrdoob / http://mrdoob.com/
38787 */
38788
38789 function PositionalAudio( listener ) {
38790
38791 Audio.call( this, listener );
38792
38793 this.panner = this.context.createPanner();
38794 this.panner.connect( this.gain );
38795
38796 }
38797
38798 PositionalAudio.prototype = Object.assign( Object.create( Audio.prototype ), {
38799
38800 constructor: PositionalAudio,
38801
38802 getOutput: function () {
38803
38804 return this.panner;
38805
38806 },
38807
38808 getRefDistance: function () {
38809
38810 return this.panner.refDistance;
38811
38812 },
38813
38814 setRefDistance: function ( value ) {
38815
38816 this.panner.refDistance = value;
38817
38818 },
38819
38820 getRolloffFactor: function () {
38821
38822 return this.panner.rolloffFactor;
38823
38824 },
38825
38826 setRolloffFactor: function ( value ) {
38827
38828 this.panner.rolloffFactor = value;
38829
38830 },
38831
38832 getDistanceModel: function () {
38833
38834 return this.panner.distanceModel;
38835
38836 },
38837
38838 setDistanceModel: function ( value ) {
38839
38840 this.panner.distanceModel = value;
38841
38842 },
38843
38844 getMaxDistance: function () {
38845
38846 return this.panner.maxDistance;
38847
38848 },
38849
38850 setMaxDistance: function ( value ) {
38851
38852 this.panner.maxDistance = value;
38853
38854 },
38855
38856 updateMatrixWorld: ( function () {
38857
38858 var position = new Vector3();
38859
38860 return function updateMatrixWorld( force ) {
38861
38862 Object3D.prototype.updateMatrixWorld.call( this, force );
38863
38864 position.setFromMatrixPosition( this.matrixWorld );
38865
38866 this.panner.setPosition( position.x, position.y, position.z );
38867
38868 };
38869
38870 } )()
38871
38872
38873 } );
38874
38875 /**
38876 * @author mrdoob / http://mrdoob.com/
38877 */
38878
38879 function AudioAnalyser( audio, fftSize ) {
38880
38881 this.analyser = audio.context.createAnalyser();
38882 this.analyser.fftSize = fftSize !== undefined ? fftSize : 2048;
38883
38884 this.data = new Uint8Array( this.analyser.frequencyBinCount );
38885
38886 audio.getOutput().connect( this.analyser );
38887
38888 }
38889
38890 Object.assign( AudioAnalyser.prototype, {
38891
38892 getFrequencyData: function () {
38893
38894 this.analyser.getByteFrequencyData( this.data );
38895
38896 return this.data;
38897
38898 },
38899
38900 getAverageFrequency: function () {
38901
38902 var value = 0, data = this.getFrequencyData();
38903
38904 for ( var i = 0; i < data.length; i ++ ) {
38905
38906 value += data[ i ];
38907
38908 }
38909
38910 return value / data.length;
38911
38912 }
38913
38914 } );
38915
38916 /**
38917 *
38918 * Buffered scene graph property that allows weighted accumulation.
38919 *
38920 *
38921 * @author Ben Houston / http://clara.io/
38922 * @author David Sarno / http://lighthaus.us/
38923 * @author tschw
38924 */
38925
38926 function PropertyMixer( binding, typeName, valueSize ) {
38927
38928 this.binding = binding;
38929 this.valueSize = valueSize;
38930
38931 var bufferType = Float64Array,
38932 mixFunction;
38933
38934 switch ( typeName ) {
38935
38936 case 'quaternion':
38937 mixFunction = this._slerp;
38938 break;
38939
38940 case 'string':
38941 case 'bool':
38942 bufferType = Array;
38943 mixFunction = this._select;
38944 break;
38945
38946 default:
38947 mixFunction = this._lerp;
38948
38949 }
38950
38951 this.buffer = new bufferType( valueSize * 4 );
38952 // layout: [ incoming | accu0 | accu1 | orig ]
38953 //
38954 // interpolators can use .buffer as their .result
38955 // the data then goes to 'incoming'
38956 //
38957 // 'accu0' and 'accu1' are used frame-interleaved for
38958 // the cumulative result and are compared to detect
38959 // changes
38960 //
38961 // 'orig' stores the original state of the property
38962
38963 this._mixBufferRegion = mixFunction;
38964
38965 this.cumulativeWeight = 0;
38966
38967 this.useCount = 0;
38968 this.referenceCount = 0;
38969
38970 }
38971
38972 Object.assign( PropertyMixer.prototype, {
38973
38974 // accumulate data in the 'incoming' region into 'accu<i>'
38975 accumulate: function ( accuIndex, weight ) {
38976
38977 // note: happily accumulating nothing when weight = 0, the caller knows
38978 // the weight and shouldn't have made the call in the first place
38979
38980 var buffer = this.buffer,
38981 stride = this.valueSize,
38982 offset = accuIndex * stride + stride,
38983
38984 currentWeight = this.cumulativeWeight;
38985
38986 if ( currentWeight === 0 ) {
38987
38988 // accuN := incoming * weight
38989
38990 for ( var i = 0; i !== stride; ++ i ) {
38991
38992 buffer[ offset + i ] = buffer[ i ];
38993
38994 }
38995
38996 currentWeight = weight;
38997
38998 } else {
38999
39000 // accuN := accuN + incoming * weight
39001
39002 currentWeight += weight;
39003 var mix = weight / currentWeight;
39004 this._mixBufferRegion( buffer, offset, 0, mix, stride );
39005
39006 }
39007
39008 this.cumulativeWeight = currentWeight;
39009
39010 },
39011
39012 // apply the state of 'accu<i>' to the binding when accus differ
39013 apply: function ( accuIndex ) {
39014
39015 var stride = this.valueSize,
39016 buffer = this.buffer,
39017 offset = accuIndex * stride + stride,
39018
39019 weight = this.cumulativeWeight,
39020
39021 binding = this.binding;
39022
39023 this.cumulativeWeight = 0;
39024
39025 if ( weight < 1 ) {
39026
39027 // accuN := accuN + original * ( 1 - cumulativeWeight )
39028
39029 var originalValueOffset = stride * 3;
39030
39031 this._mixBufferRegion(
39032 buffer, offset, originalValueOffset, 1 - weight, stride );
39033
39034 }
39035
39036 for ( var i = stride, e = stride + stride; i !== e; ++ i ) {
39037
39038 if ( buffer[ i ] !== buffer[ i + stride ] ) {
39039
39040 // value has changed -> update scene graph
39041
39042 binding.setValue( buffer, offset );
39043 break;
39044
39045 }
39046
39047 }
39048
39049 },
39050
39051 // remember the state of the bound property and copy it to both accus
39052 saveOriginalState: function () {
39053
39054 var binding = this.binding;
39055
39056 var buffer = this.buffer,
39057 stride = this.valueSize,
39058
39059 originalValueOffset = stride * 3;
39060
39061 binding.getValue( buffer, originalValueOffset );
39062
39063 // accu[0..1] := orig -- initially detect changes against the original
39064 for ( var i = stride, e = originalValueOffset; i !== e; ++ i ) {
39065
39066 buffer[ i ] = buffer[ originalValueOffset + ( i % stride ) ];
39067
39068 }
39069
39070 this.cumulativeWeight = 0;
39071
39072 },
39073
39074 // apply the state previously taken via 'saveOriginalState' to the binding
39075 restoreOriginalState: function () {
39076
39077 var originalValueOffset = this.valueSize * 3;
39078 this.binding.setValue( this.buffer, originalValueOffset );
39079
39080 },
39081
39082
39083 // mix functions
39084
39085 _select: function ( buffer, dstOffset, srcOffset, t, stride ) {
39086
39087 if ( t >= 0.5 ) {
39088
39089 for ( var i = 0; i !== stride; ++ i ) {
39090
39091 buffer[ dstOffset + i ] = buffer[ srcOffset + i ];
39092
39093 }
39094
39095 }
39096
39097 },
39098
39099 _slerp: function ( buffer, dstOffset, srcOffset, t ) {
39100
39101 Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, srcOffset, t );
39102
39103 },
39104
39105 _lerp: function ( buffer, dstOffset, srcOffset, t, stride ) {
39106
39107 var s = 1 - t;
39108
39109 for ( var i = 0; i !== stride; ++ i ) {
39110
39111 var j = dstOffset + i;
39112
39113 buffer[ j ] = buffer[ j ] * s + buffer[ srcOffset + i ] * t;
39114
39115 }
39116
39117 }
39118
39119 } );
39120
39121 /**
39122 *
39123 * A reference to a real property in the scene graph.
39124 *
39125 *
39126 * @author Ben Houston / http://clara.io/
39127 * @author David Sarno / http://lighthaus.us/
39128 * @author tschw
39129 */
39130
39131 // Characters [].:/ are reserved for track binding syntax.
39132 var RESERVED_CHARS_RE = '\\[\\]\\.:\\/';
39133
39134 function Composite( targetGroup, path, optionalParsedPath ) {
39135
39136 var parsedPath = optionalParsedPath || PropertyBinding.parseTrackName( path );
39137
39138 this._targetGroup = targetGroup;
39139 this._bindings = targetGroup.subscribe_( path, parsedPath );
39140
39141 }
39142
39143 Object.assign( Composite.prototype, {
39144
39145 getValue: function ( array, offset ) {
39146
39147 this.bind(); // bind all binding
39148
39149 var firstValidIndex = this._targetGroup.nCachedObjects_,
39150 binding = this._bindings[ firstValidIndex ];
39151
39152 // and only call .getValue on the first
39153 if ( binding !== undefined ) binding.getValue( array, offset );
39154
39155 },
39156
39157 setValue: function ( array, offset ) {
39158
39159 var bindings = this._bindings;
39160
39161 for ( var i = this._targetGroup.nCachedObjects_,
39162 n = bindings.length; i !== n; ++ i ) {
39163
39164 bindings[ i ].setValue( array, offset );
39165
39166 }
39167
39168 },
39169
39170 bind: function () {
39171
39172 var bindings = this._bindings;
39173
39174 for ( var i = this._targetGroup.nCachedObjects_,
39175 n = bindings.length; i !== n; ++ i ) {
39176
39177 bindings[ i ].bind();
39178
39179 }
39180
39181 },
39182
39183 unbind: function () {
39184
39185 var bindings = this._bindings;
39186
39187 for ( var i = this._targetGroup.nCachedObjects_,
39188 n = bindings.length; i !== n; ++ i ) {
39189
39190 bindings[ i ].unbind();
39191
39192 }
39193
39194 }
39195
39196 } );
39197
39198
39199 function PropertyBinding( rootNode, path, parsedPath ) {
39200
39201 this.path = path;
39202 this.parsedPath = parsedPath || PropertyBinding.parseTrackName( path );
39203
39204 this.node = PropertyBinding.findNode( rootNode, this.parsedPath.nodeName ) || rootNode;
39205
39206 this.rootNode = rootNode;
39207
39208 }
39209
39210 Object.assign( PropertyBinding, {
39211
39212 Composite: Composite,
39213
39214 create: function ( root, path, parsedPath ) {
39215
39216 if ( ! ( root && root.isAnimationObjectGroup ) ) {
39217
39218 return new PropertyBinding( root, path, parsedPath );
39219
39220 } else {
39221
39222 return new PropertyBinding.Composite( root, path, parsedPath );
39223
39224 }
39225
39226 },
39227
39228 /**
39229 * Replaces spaces with underscores and removes unsupported characters from
39230 * node names, to ensure compatibility with parseTrackName().
39231 *
39232 * @param {string} name Node name to be sanitized.
39233 * @return {string}
39234 */
39235 sanitizeNodeName: ( function () {
39236
39237 var reservedRe = new RegExp( '[' + RESERVED_CHARS_RE + ']', 'g' );
39238
39239 return function sanitizeNodeName( name ) {
39240
39241 return name.replace( /\s/g, '_' ).replace( reservedRe, '' );
39242
39243 };
39244
39245 }() ),
39246
39247 parseTrackName: function () {
39248
39249 // Attempts to allow node names from any language. ES5's `\w` regexp matches
39250 // only latin characters, and the unicode \p{L} is not yet supported. So
39251 // instead, we exclude reserved characters and match everything else.
39252 var wordChar = '[^' + RESERVED_CHARS_RE + ']';
39253 var wordCharOrDot = '[^' + RESERVED_CHARS_RE.replace( '\\.', '' ) + ']';
39254
39255 // Parent directories, delimited by '/' or ':'. Currently unused, but must
39256 // be matched to parse the rest of the track name.
39257 var directoryRe = /((?:WC+[\/:])*)/.source.replace( 'WC', wordChar );
39258
39259 // Target node. May contain word characters (a-zA-Z0-9_) and '.' or '-'.
39260 var nodeRe = /(WCOD+)?/.source.replace( 'WCOD', wordCharOrDot );
39261
39262 // Object on target node, and accessor. May not contain reserved
39263 // characters. Accessor may contain any character except closing bracket.
39264 var objectRe = /(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace( 'WC', wordChar );
39265
39266 // Property and accessor. May not contain reserved characters. Accessor may
39267 // contain any non-bracket characters.
39268 var propertyRe = /\.(WC+)(?:\[(.+)\])?/.source.replace( 'WC', wordChar );
39269
39270 var trackRe = new RegExp( ''
39271 + '^'
39272 + directoryRe
39273 + nodeRe
39274 + objectRe
39275 + propertyRe
39276 + '$'
39277 );
39278
39279 var supportedObjectNames = [ 'material', 'materials', 'bones' ];
39280
39281 return function parseTrackName( trackName ) {
39282
39283 var matches = trackRe.exec( trackName );
39284
39285 if ( ! matches ) {
39286
39287 throw new Error( 'PropertyBinding: Cannot parse trackName: ' + trackName );
39288
39289 }
39290
39291 var results = {
39292 // directoryName: matches[ 1 ], // (tschw) currently unused
39293 nodeName: matches[ 2 ],
39294 objectName: matches[ 3 ],
39295 objectIndex: matches[ 4 ],
39296 propertyName: matches[ 5 ], // required
39297 propertyIndex: matches[ 6 ]
39298 };
39299
39300 var lastDot = results.nodeName && results.nodeName.lastIndexOf( '.' );
39301
39302 if ( lastDot !== undefined && lastDot !== - 1 ) {
39303
39304 var objectName = results.nodeName.substring( lastDot + 1 );
39305
39306 // Object names must be checked against a whitelist. Otherwise, there
39307 // is no way to parse 'foo.bar.baz': 'baz' must be a property, but
39308 // 'bar' could be the objectName, or part of a nodeName (which can
39309 // include '.' characters).
39310 if ( supportedObjectNames.indexOf( objectName ) !== - 1 ) {
39311
39312 results.nodeName = results.nodeName.substring( 0, lastDot );
39313 results.objectName = objectName;
39314
39315 }
39316
39317 }
39318
39319 if ( results.propertyName === null || results.propertyName.length === 0 ) {
39320
39321 throw new Error( 'PropertyBinding: can not parse propertyName from trackName: ' + trackName );
39322
39323 }
39324
39325 return results;
39326
39327 };
39328
39329 }(),
39330
39331 findNode: function ( root, nodeName ) {
39332
39333 if ( ! nodeName || nodeName === "" || nodeName === "root" || nodeName === "." || nodeName === - 1 || nodeName === root.name || nodeName === root.uuid ) {
39334
39335 return root;
39336
39337 }
39338
39339 // search into skeleton bones.
39340 if ( root.skeleton ) {
39341
39342 var bone = root.skeleton.getBoneByName( nodeName );
39343
39344 if ( bone !== undefined ) {
39345
39346 return bone;
39347
39348 }
39349
39350 }
39351
39352 // search into node subtree.
39353 if ( root.children ) {
39354
39355 var searchNodeSubtree = function ( children ) {
39356
39357 for ( var i = 0; i < children.length; i ++ ) {
39358
39359 var childNode = children[ i ];
39360
39361 if ( childNode.name === nodeName || childNode.uuid === nodeName ) {
39362
39363 return childNode;
39364
39365 }
39366
39367 var result = searchNodeSubtree( childNode.children );
39368
39369 if ( result ) return result;
39370
39371 }
39372
39373 return null;
39374
39375 };
39376
39377 var subTreeNode = searchNodeSubtree( root.children );
39378
39379 if ( subTreeNode ) {
39380
39381 return subTreeNode;
39382
39383 }
39384
39385 }
39386
39387 return null;
39388
39389 }
39390
39391 } );
39392
39393 Object.assign( PropertyBinding.prototype, { // prototype, continued
39394
39395 // these are used to "bind" a nonexistent property
39396 _getValue_unavailable: function () {},
39397 _setValue_unavailable: function () {},
39398
39399 BindingType: {
39400 Direct: 0,
39401 EntireArray: 1,
39402 ArrayElement: 2,
39403 HasFromToArray: 3
39404 },
39405
39406 Versioning: {
39407 None: 0,
39408 NeedsUpdate: 1,
39409 MatrixWorldNeedsUpdate: 2
39410 },
39411
39412 GetterByBindingType: [
39413
39414 function getValue_direct( buffer, offset ) {
39415
39416 buffer[ offset ] = this.node[ this.propertyName ];
39417
39418 },
39419
39420 function getValue_array( buffer, offset ) {
39421
39422 var source = this.resolvedProperty;
39423
39424 for ( var i = 0, n = source.length; i !== n; ++ i ) {
39425
39426 buffer[ offset ++ ] = source[ i ];
39427
39428 }
39429
39430 },
39431
39432 function getValue_arrayElement( buffer, offset ) {
39433
39434 buffer[ offset ] = this.resolvedProperty[ this.propertyIndex ];
39435
39436 },
39437
39438 function getValue_toArray( buffer, offset ) {
39439
39440 this.resolvedProperty.toArray( buffer, offset );
39441
39442 }
39443
39444 ],
39445
39446 SetterByBindingTypeAndVersioning: [
39447
39448 [
39449 // Direct
39450
39451 function setValue_direct( buffer, offset ) {
39452
39453 this.targetObject[ this.propertyName ] = buffer[ offset ];
39454
39455 },
39456
39457 function setValue_direct_setNeedsUpdate( buffer, offset ) {
39458
39459 this.targetObject[ this.propertyName ] = buffer[ offset ];
39460 this.targetObject.needsUpdate = true;
39461
39462 },
39463
39464 function setValue_direct_setMatrixWorldNeedsUpdate( buffer, offset ) {
39465
39466 this.targetObject[ this.propertyName ] = buffer[ offset ];
39467 this.targetObject.matrixWorldNeedsUpdate = true;
39468
39469 }
39470
39471 ], [
39472
39473 // EntireArray
39474
39475 function setValue_array( buffer, offset ) {
39476
39477 var dest = this.resolvedProperty;
39478
39479 for ( var i = 0, n = dest.length; i !== n; ++ i ) {
39480
39481 dest[ i ] = buffer[ offset ++ ];
39482
39483 }
39484
39485 },
39486
39487 function setValue_array_setNeedsUpdate( buffer, offset ) {
39488
39489 var dest = this.resolvedProperty;
39490
39491 for ( var i = 0, n = dest.length; i !== n; ++ i ) {
39492
39493 dest[ i ] = buffer[ offset ++ ];
39494
39495 }
39496
39497 this.targetObject.needsUpdate = true;
39498
39499 },
39500
39501 function setValue_array_setMatrixWorldNeedsUpdate( buffer, offset ) {
39502
39503 var dest = this.resolvedProperty;
39504
39505 for ( var i = 0, n = dest.length; i !== n; ++ i ) {
39506
39507 dest[ i ] = buffer[ offset ++ ];
39508
39509 }
39510
39511 this.targetObject.matrixWorldNeedsUpdate = true;
39512
39513 }
39514
39515 ], [
39516
39517 // ArrayElement
39518
39519 function setValue_arrayElement( buffer, offset ) {
39520
39521 this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
39522
39523 },
39524
39525 function setValue_arrayElement_setNeedsUpdate( buffer, offset ) {
39526
39527 this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
39528 this.targetObject.needsUpdate = true;
39529
39530 },
39531
39532 function setValue_arrayElement_setMatrixWorldNeedsUpdate( buffer, offset ) {
39533
39534 this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
39535 this.targetObject.matrixWorldNeedsUpdate = true;
39536
39537 }
39538
39539 ], [
39540
39541 // HasToFromArray
39542
39543 function setValue_fromArray( buffer, offset ) {
39544
39545 this.resolvedProperty.fromArray( buffer, offset );
39546
39547 },
39548
39549 function setValue_fromArray_setNeedsUpdate( buffer, offset ) {
39550
39551 this.resolvedProperty.fromArray( buffer, offset );
39552 this.targetObject.needsUpdate = true;
39553
39554 },
39555
39556 function setValue_fromArray_setMatrixWorldNeedsUpdate( buffer, offset ) {
39557
39558 this.resolvedProperty.fromArray( buffer, offset );
39559 this.targetObject.matrixWorldNeedsUpdate = true;
39560
39561 }
39562
39563 ]
39564
39565 ],
39566
39567 getValue: function getValue_unbound( targetArray, offset ) {
39568
39569 this.bind();
39570 this.getValue( targetArray, offset );
39571
39572 // Note: This class uses a State pattern on a per-method basis:
39573 // 'bind' sets 'this.getValue' / 'setValue' and shadows the
39574 // prototype version of these methods with one that represents
39575 // the bound state. When the property is not found, the methods
39576 // become no-ops.
39577
39578 },
39579
39580 setValue: function getValue_unbound( sourceArray, offset ) {
39581
39582 this.bind();
39583 this.setValue( sourceArray, offset );
39584
39585 },
39586
39587 // create getter / setter pair for a property in the scene graph
39588 bind: function () {
39589
39590 var targetObject = this.node,
39591 parsedPath = this.parsedPath,
39592
39593 objectName = parsedPath.objectName,
39594 propertyName = parsedPath.propertyName,
39595 propertyIndex = parsedPath.propertyIndex;
39596
39597 if ( ! targetObject ) {
39598
39599 targetObject = PropertyBinding.findNode( this.rootNode, parsedPath.nodeName ) || this.rootNode;
39600
39601 this.node = targetObject;
39602
39603 }
39604
39605 // set fail state so we can just 'return' on error
39606 this.getValue = this._getValue_unavailable;
39607 this.setValue = this._setValue_unavailable;
39608
39609 // ensure there is a value node
39610 if ( ! targetObject ) {
39611
39612 console.error( 'THREE.PropertyBinding: Trying to update node for track: ' + this.path + ' but it wasn\'t found.' );
39613 return;
39614
39615 }
39616
39617 if ( objectName ) {
39618
39619 var objectIndex = parsedPath.objectIndex;
39620
39621 // special cases were we need to reach deeper into the hierarchy to get the face materials....
39622 switch ( objectName ) {
39623
39624 case 'materials':
39625
39626 if ( ! targetObject.material ) {
39627
39628 console.error( 'THREE.PropertyBinding: Can not bind to material as node does not have a material.', this );
39629 return;
39630
39631 }
39632
39633 if ( ! targetObject.material.materials ) {
39634
39635 console.error( 'THREE.PropertyBinding: Can not bind to material.materials as node.material does not have a materials array.', this );
39636 return;
39637
39638 }
39639
39640 targetObject = targetObject.material.materials;
39641
39642 break;
39643
39644 case 'bones':
39645
39646 if ( ! targetObject.skeleton ) {
39647
39648 console.error( 'THREE.PropertyBinding: Can not bind to bones as node does not have a skeleton.', this );
39649 return;
39650
39651 }
39652
39653 // potential future optimization: skip this if propertyIndex is already an integer
39654 // and convert the integer string to a true integer.
39655
39656 targetObject = targetObject.skeleton.bones;
39657
39658 // support resolving morphTarget names into indices.
39659 for ( var i = 0; i < targetObject.length; i ++ ) {
39660
39661 if ( targetObject[ i ].name === objectIndex ) {
39662
39663 objectIndex = i;
39664 break;
39665
39666 }
39667
39668 }
39669
39670 break;
39671
39672 default:
39673
39674 if ( targetObject[ objectName ] === undefined ) {
39675
39676 console.error( 'THREE.PropertyBinding: Can not bind to objectName of node undefined.', this );
39677 return;
39678
39679 }
39680
39681 targetObject = targetObject[ objectName ];
39682
39683 }
39684
39685
39686 if ( objectIndex !== undefined ) {
39687
39688 if ( targetObject[ objectIndex ] === undefined ) {
39689
39690 console.error( 'THREE.PropertyBinding: Trying to bind to objectIndex of objectName, but is undefined.', this, targetObject );
39691 return;
39692
39693 }
39694
39695 targetObject = targetObject[ objectIndex ];
39696
39697 }
39698
39699 }
39700
39701 // resolve property
39702 var nodeProperty = targetObject[ propertyName ];
39703
39704 if ( nodeProperty === undefined ) {
39705
39706 var nodeName = parsedPath.nodeName;
39707
39708 console.error( 'THREE.PropertyBinding: Trying to update property for track: ' + nodeName +
39709 '.' + propertyName + ' but it wasn\'t found.', targetObject );
39710 return;
39711
39712 }
39713
39714 // determine versioning scheme
39715 var versioning = this.Versioning.None;
39716
39717 if ( targetObject.needsUpdate !== undefined ) { // material
39718
39719 versioning = this.Versioning.NeedsUpdate;
39720 this.targetObject = targetObject;
39721
39722 } else if ( targetObject.matrixWorldNeedsUpdate !== undefined ) { // node transform
39723
39724 versioning = this.Versioning.MatrixWorldNeedsUpdate;
39725 this.targetObject = targetObject;
39726
39727 }
39728
39729 // determine how the property gets bound
39730 var bindingType = this.BindingType.Direct;
39731
39732 if ( propertyIndex !== undefined ) {
39733
39734 // access a sub element of the property array (only primitives are supported right now)
39735
39736 if ( propertyName === "morphTargetInfluences" ) {
39737
39738 // potential optimization, skip this if propertyIndex is already an integer, and convert the integer string to a true integer.
39739
39740 // support resolving morphTarget names into indices.
39741 if ( ! targetObject.geometry ) {
39742
39743 console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.', this );
39744 return;
39745
39746 }
39747
39748 if ( targetObject.geometry.isBufferGeometry ) {
39749
39750 if ( ! targetObject.geometry.morphAttributes ) {
39751
39752 console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphAttributes.', this );
39753 return;
39754
39755 }
39756
39757 for ( var i = 0; i < this.node.geometry.morphAttributes.position.length; i ++ ) {
39758
39759 if ( targetObject.geometry.morphAttributes.position[ i ].name === propertyIndex ) {
39760
39761 propertyIndex = i;
39762 break;
39763
39764 }
39765
39766 }
39767
39768
39769 } else {
39770
39771 if ( ! targetObject.geometry.morphTargets ) {
39772
39773 console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphTargets.', this );
39774 return;
39775
39776 }
39777
39778 for ( var i = 0; i < this.node.geometry.morphTargets.length; i ++ ) {
39779
39780 if ( targetObject.geometry.morphTargets[ i ].name === propertyIndex ) {
39781
39782 propertyIndex = i;
39783 break;
39784
39785 }
39786
39787 }
39788
39789 }
39790
39791 }
39792
39793 bindingType = this.BindingType.ArrayElement;
39794
39795 this.resolvedProperty = nodeProperty;
39796 this.propertyIndex = propertyIndex;
39797
39798 } else if ( nodeProperty.fromArray !== undefined && nodeProperty.toArray !== undefined ) {
39799
39800 // must use copy for Object3D.Euler/Quaternion
39801
39802 bindingType = this.BindingType.HasFromToArray;
39803
39804 this.resolvedProperty = nodeProperty;
39805
39806 } else if ( Array.isArray( nodeProperty ) ) {
39807
39808 bindingType = this.BindingType.EntireArray;
39809
39810 this.resolvedProperty = nodeProperty;
39811
39812 } else {
39813
39814 this.propertyName = propertyName;
39815
39816 }
39817
39818 // select getter / setter
39819 this.getValue = this.GetterByBindingType[ bindingType ];
39820 this.setValue = this.SetterByBindingTypeAndVersioning[ bindingType ][ versioning ];
39821
39822 },
39823
39824 unbind: function () {
39825
39826 this.node = null;
39827
39828 // back to the prototype version of getValue / setValue
39829 // note: avoiding to mutate the shape of 'this' via 'delete'
39830 this.getValue = this._getValue_unbound;
39831 this.setValue = this._setValue_unbound;
39832
39833 }
39834
39835 } );
39836
39837 //!\ DECLARE ALIAS AFTER assign prototype !
39838 Object.assign( PropertyBinding.prototype, {
39839
39840 // initial state of these methods that calls 'bind'
39841 _getValue_unbound: PropertyBinding.prototype.getValue,
39842 _setValue_unbound: PropertyBinding.prototype.setValue,
39843
39844 } );
39845
39846 /**
39847 *
39848 * A group of objects that receives a shared animation state.
39849 *
39850 * Usage:
39851 *
39852 * - Add objects you would otherwise pass as 'root' to the
39853 * constructor or the .clipAction method of AnimationMixer.
39854 *
39855 * - Instead pass this object as 'root'.
39856 *
39857 * - You can also add and remove objects later when the mixer
39858 * is running.
39859 *
39860 * Note:
39861 *
39862 * Objects of this class appear as one object to the mixer,
39863 * so cache control of the individual objects must be done
39864 * on the group.
39865 *
39866 * Limitation:
39867 *
39868 * - The animated properties must be compatible among the
39869 * all objects in the group.
39870 *
39871 * - A single property can either be controlled through a
39872 * target group or directly, but not both.
39873 *
39874 * @author tschw
39875 */
39876
39877 function AnimationObjectGroup() {
39878
39879 this.uuid = _Math.generateUUID();
39880
39881 // cached objects followed by the active ones
39882 this._objects = Array.prototype.slice.call( arguments );
39883
39884 this.nCachedObjects_ = 0; // threshold
39885 // note: read by PropertyBinding.Composite
39886
39887 var indices = {};
39888 this._indicesByUUID = indices; // for bookkeeping
39889
39890 for ( var i = 0, n = arguments.length; i !== n; ++ i ) {
39891
39892 indices[ arguments[ i ].uuid ] = i;
39893
39894 }
39895
39896 this._paths = []; // inside: string
39897 this._parsedPaths = []; // inside: { we don't care, here }
39898 this._bindings = []; // inside: Array< PropertyBinding >
39899 this._bindingsIndicesByPath = {}; // inside: indices in these arrays
39900
39901 var scope = this;
39902
39903 this.stats = {
39904
39905 objects: {
39906 get total() {
39907
39908 return scope._objects.length;
39909
39910 },
39911 get inUse() {
39912
39913 return this.total - scope.nCachedObjects_;
39914
39915 }
39916 },
39917 get bindingsPerObject() {
39918
39919 return scope._bindings.length;
39920
39921 }
39922
39923 };
39924
39925 }
39926
39927 Object.assign( AnimationObjectGroup.prototype, {
39928
39929 isAnimationObjectGroup: true,
39930
39931 add: function () {
39932
39933 var objects = this._objects,
39934 nObjects = objects.length,
39935 nCachedObjects = this.nCachedObjects_,
39936 indicesByUUID = this._indicesByUUID,
39937 paths = this._paths,
39938 parsedPaths = this._parsedPaths,
39939 bindings = this._bindings,
39940 nBindings = bindings.length,
39941 knownObject = undefined;
39942
39943 for ( var i = 0, n = arguments.length; i !== n; ++ i ) {
39944
39945 var object = arguments[ i ],
39946 uuid = object.uuid,
39947 index = indicesByUUID[ uuid ];
39948
39949 if ( index === undefined ) {
39950
39951 // unknown object -> add it to the ACTIVE region
39952
39953 index = nObjects ++;
39954 indicesByUUID[ uuid ] = index;
39955 objects.push( object );
39956
39957 // accounting is done, now do the same for all bindings
39958
39959 for ( var j = 0, m = nBindings; j !== m; ++ j ) {
39960
39961 bindings[ j ].push( new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ) );
39962
39963 }
39964
39965 } else if ( index < nCachedObjects ) {
39966
39967 knownObject = objects[ index ];
39968
39969 // move existing object to the ACTIVE region
39970
39971 var firstActiveIndex = -- nCachedObjects,
39972 lastCachedObject = objects[ firstActiveIndex ];
39973
39974 indicesByUUID[ lastCachedObject.uuid ] = index;
39975 objects[ index ] = lastCachedObject;
39976
39977 indicesByUUID[ uuid ] = firstActiveIndex;
39978 objects[ firstActiveIndex ] = object;
39979
39980 // accounting is done, now do the same for all bindings
39981
39982 for ( var j = 0, m = nBindings; j !== m; ++ j ) {
39983
39984 var bindingsForPath = bindings[ j ],
39985 lastCached = bindingsForPath[ firstActiveIndex ],
39986 binding = bindingsForPath[ index ];
39987
39988 bindingsForPath[ index ] = lastCached;
39989
39990 if ( binding === undefined ) {
39991
39992 // since we do not bother to create new bindings
39993 // for objects that are cached, the binding may
39994 // or may not exist
39995
39996 binding = new PropertyBinding( object, paths[ j ], parsedPaths[ j ] );
39997
39998 }
39999
40000 bindingsForPath[ firstActiveIndex ] = binding;
40001
40002 }
40003
40004 } else if ( objects[ index ] !== knownObject ) {
40005
40006 console.error( 'THREE.AnimationObjectGroup: Different objects with the same UUID ' +
40007 'detected. Clean the caches or recreate your infrastructure when reloading scenes.' );
40008
40009 } // else the object is already where we want it to be
40010
40011 } // for arguments
40012
40013 this.nCachedObjects_ = nCachedObjects;
40014
40015 },
40016
40017 remove: function () {
40018
40019 var objects = this._objects,
40020 nCachedObjects = this.nCachedObjects_,
40021 indicesByUUID = this._indicesByUUID,
40022 bindings = this._bindings,
40023 nBindings = bindings.length;
40024
40025 for ( var i = 0, n = arguments.length; i !== n; ++ i ) {
40026
40027 var object = arguments[ i ],
40028 uuid = object.uuid,
40029 index = indicesByUUID[ uuid ];
40030
40031 if ( index !== undefined && index >= nCachedObjects ) {
40032
40033 // move existing object into the CACHED region
40034
40035 var lastCachedIndex = nCachedObjects ++,
40036 firstActiveObject = objects[ lastCachedIndex ];
40037
40038 indicesByUUID[ firstActiveObject.uuid ] = index;
40039 objects[ index ] = firstActiveObject;
40040
40041 indicesByUUID[ uuid ] = lastCachedIndex;
40042 objects[ lastCachedIndex ] = object;
40043
40044 // accounting is done, now do the same for all bindings
40045
40046 for ( var j = 0, m = nBindings; j !== m; ++ j ) {
40047
40048 var bindingsForPath = bindings[ j ],
40049 firstActive = bindingsForPath[ lastCachedIndex ],
40050 binding = bindingsForPath[ index ];
40051
40052 bindingsForPath[ index ] = firstActive;
40053 bindingsForPath[ lastCachedIndex ] = binding;
40054
40055 }
40056
40057 }
40058
40059 } // for arguments
40060
40061 this.nCachedObjects_ = nCachedObjects;
40062
40063 },
40064
40065 // remove & forget
40066 uncache: function () {
40067
40068 var objects = this._objects,
40069 nObjects = objects.length,
40070 nCachedObjects = this.nCachedObjects_,
40071 indicesByUUID = this._indicesByUUID,
40072 bindings = this._bindings,
40073 nBindings = bindings.length;
40074
40075 for ( var i = 0, n = arguments.length; i !== n; ++ i ) {
40076
40077 var object = arguments[ i ],
40078 uuid = object.uuid,
40079 index = indicesByUUID[ uuid ];
40080
40081 if ( index !== undefined ) {
40082
40083 delete indicesByUUID[ uuid ];
40084
40085 if ( index < nCachedObjects ) {
40086
40087 // object is cached, shrink the CACHED region
40088
40089 var firstActiveIndex = -- nCachedObjects,
40090 lastCachedObject = objects[ firstActiveIndex ],
40091 lastIndex = -- nObjects,
40092 lastObject = objects[ lastIndex ];
40093
40094 // last cached object takes this object's place
40095 indicesByUUID[ lastCachedObject.uuid ] = index;
40096 objects[ index ] = lastCachedObject;
40097
40098 // last object goes to the activated slot and pop
40099 indicesByUUID[ lastObject.uuid ] = firstActiveIndex;
40100 objects[ firstActiveIndex ] = lastObject;
40101 objects.pop();
40102
40103 // accounting is done, now do the same for all bindings
40104
40105 for ( var j = 0, m = nBindings; j !== m; ++ j ) {
40106
40107 var bindingsForPath = bindings[ j ],
40108 lastCached = bindingsForPath[ firstActiveIndex ],
40109 last = bindingsForPath[ lastIndex ];
40110
40111 bindingsForPath[ index ] = lastCached;
40112 bindingsForPath[ firstActiveIndex ] = last;
40113 bindingsForPath.pop();
40114
40115 }
40116
40117 } else {
40118
40119 // object is active, just swap with the last and pop
40120
40121 var lastIndex = -- nObjects,
40122 lastObject = objects[ lastIndex ];
40123
40124 indicesByUUID[ lastObject.uuid ] = index;
40125 objects[ index ] = lastObject;
40126 objects.pop();
40127
40128 // accounting is done, now do the same for all bindings
40129
40130 for ( var j = 0, m = nBindings; j !== m; ++ j ) {
40131
40132 var bindingsForPath = bindings[ j ];
40133
40134 bindingsForPath[ index ] = bindingsForPath[ lastIndex ];
40135 bindingsForPath.pop();
40136
40137 }
40138
40139 } // cached or active
40140
40141 } // if object is known
40142
40143 } // for arguments
40144
40145 this.nCachedObjects_ = nCachedObjects;
40146
40147 },
40148
40149 // Internal interface used by befriended PropertyBinding.Composite:
40150
40151 subscribe_: function ( path, parsedPath ) {
40152
40153 // returns an array of bindings for the given path that is changed
40154 // according to the contained objects in the group
40155
40156 var indicesByPath = this._bindingsIndicesByPath,
40157 index = indicesByPath[ path ],
40158 bindings = this._bindings;
40159
40160 if ( index !== undefined ) return bindings[ index ];
40161
40162 var paths = this._paths,
40163 parsedPaths = this._parsedPaths,
40164 objects = this._objects,
40165 nObjects = objects.length,
40166 nCachedObjects = this.nCachedObjects_,
40167 bindingsForPath = new Array( nObjects );
40168
40169 index = bindings.length;
40170
40171 indicesByPath[ path ] = index;
40172
40173 paths.push( path );
40174 parsedPaths.push( parsedPath );
40175 bindings.push( bindingsForPath );
40176
40177 for ( var i = nCachedObjects, n = objects.length; i !== n; ++ i ) {
40178
40179 var object = objects[ i ];
40180 bindingsForPath[ i ] = new PropertyBinding( object, path, parsedPath );
40181
40182 }
40183
40184 return bindingsForPath;
40185
40186 },
40187
40188 unsubscribe_: function ( path ) {
40189
40190 // tells the group to forget about a property path and no longer
40191 // update the array previously obtained with 'subscribe_'
40192
40193 var indicesByPath = this._bindingsIndicesByPath,
40194 index = indicesByPath[ path ];
40195
40196 if ( index !== undefined ) {
40197
40198 var paths = this._paths,
40199 parsedPaths = this._parsedPaths,
40200 bindings = this._bindings,
40201 lastBindingsIndex = bindings.length - 1,
40202 lastBindings = bindings[ lastBindingsIndex ],
40203 lastBindingsPath = path[ lastBindingsIndex ];
40204
40205 indicesByPath[ lastBindingsPath ] = index;
40206
40207 bindings[ index ] = lastBindings;
40208 bindings.pop();
40209
40210 parsedPaths[ index ] = parsedPaths[ lastBindingsIndex ];
40211 parsedPaths.pop();
40212
40213 paths[ index ] = paths[ lastBindingsIndex ];
40214 paths.pop();
40215
40216 }
40217
40218 }
40219
40220 } );
40221
40222 /**
40223 *
40224 * Action provided by AnimationMixer for scheduling clip playback on specific
40225 * objects.
40226 *
40227 * @author Ben Houston / http://clara.io/
40228 * @author David Sarno / http://lighthaus.us/
40229 * @author tschw
40230 *
40231 */
40232
40233 function AnimationAction( mixer, clip, localRoot ) {
40234
40235 this._mixer = mixer;
40236 this._clip = clip;
40237 this._localRoot = localRoot || null;
40238
40239 var tracks = clip.tracks,
40240 nTracks = tracks.length,
40241 interpolants = new Array( nTracks );
40242
40243 var interpolantSettings = {
40244 endingStart: ZeroCurvatureEnding,
40245 endingEnd: ZeroCurvatureEnding
40246 };
40247
40248 for ( var i = 0; i !== nTracks; ++ i ) {
40249
40250 var interpolant = tracks[ i ].createInterpolant( null );
40251 interpolants[ i ] = interpolant;
40252 interpolant.settings = interpolantSettings;
40253
40254 }
40255
40256 this._interpolantSettings = interpolantSettings;
40257
40258 this._interpolants = interpolants; // bound by the mixer
40259
40260 // inside: PropertyMixer (managed by the mixer)
40261 this._propertyBindings = new Array( nTracks );
40262
40263 this._cacheIndex = null; // for the memory manager
40264 this._byClipCacheIndex = null; // for the memory manager
40265
40266 this._timeScaleInterpolant = null;
40267 this._weightInterpolant = null;
40268
40269 this.loop = LoopRepeat;
40270 this._loopCount = - 1;
40271
40272 // global mixer time when the action is to be started
40273 // it's set back to 'null' upon start of the action
40274 this._startTime = null;
40275
40276 // scaled local time of the action
40277 // gets clamped or wrapped to 0..clip.duration according to loop
40278 this.time = 0;
40279
40280 this.timeScale = 1;
40281 this._effectiveTimeScale = 1;
40282
40283 this.weight = 1;
40284 this._effectiveWeight = 1;
40285
40286 this.repetitions = Infinity; // no. of repetitions when looping
40287
40288 this.paused = false; // true -> zero effective time scale
40289 this.enabled = true; // false -> zero effective weight
40290
40291 this.clampWhenFinished = false; // keep feeding the last frame?
40292
40293 this.zeroSlopeAtStart = true; // for smooth interpolation w/o separate
40294 this.zeroSlopeAtEnd = true; // clips for start, loop and end
40295
40296 }
40297
40298 Object.assign( AnimationAction.prototype, {
40299
40300 // State & Scheduling
40301
40302 play: function () {
40303
40304 this._mixer._activateAction( this );
40305
40306 return this;
40307
40308 },
40309
40310 stop: function () {
40311
40312 this._mixer._deactivateAction( this );
40313
40314 return this.reset();
40315
40316 },
40317
40318 reset: function () {
40319
40320 this.paused = false;
40321 this.enabled = true;
40322
40323 this.time = 0; // restart clip
40324 this._loopCount = - 1; // forget previous loops
40325 this._startTime = null; // forget scheduling
40326
40327 return this.stopFading().stopWarping();
40328
40329 },
40330
40331 isRunning: function () {
40332
40333 return this.enabled && ! this.paused && this.timeScale !== 0 &&
40334 this._startTime === null && this._mixer._isActiveAction( this );
40335
40336 },
40337
40338 // return true when play has been called
40339 isScheduled: function () {
40340
40341 return this._mixer._isActiveAction( this );
40342
40343 },
40344
40345 startAt: function ( time ) {
40346
40347 this._startTime = time;
40348
40349 return this;
40350
40351 },
40352
40353 setLoop: function ( mode, repetitions ) {
40354
40355 this.loop = mode;
40356 this.repetitions = repetitions;
40357
40358 return this;
40359
40360 },
40361
40362 // Weight
40363
40364 // set the weight stopping any scheduled fading
40365 // although .enabled = false yields an effective weight of zero, this
40366 // method does *not* change .enabled, because it would be confusing
40367 setEffectiveWeight: function ( weight ) {
40368
40369 this.weight = weight;
40370
40371 // note: same logic as when updated at runtime
40372 this._effectiveWeight = this.enabled ? weight : 0;
40373
40374 return this.stopFading();
40375
40376 },
40377
40378 // return the weight considering fading and .enabled
40379 getEffectiveWeight: function () {
40380
40381 return this._effectiveWeight;
40382
40383 },
40384
40385 fadeIn: function ( duration ) {
40386
40387 return this._scheduleFading( duration, 0, 1 );
40388
40389 },
40390
40391 fadeOut: function ( duration ) {
40392
40393 return this._scheduleFading( duration, 1, 0 );
40394
40395 },
40396
40397 crossFadeFrom: function ( fadeOutAction, duration, warp ) {
40398
40399 fadeOutAction.fadeOut( duration );
40400 this.fadeIn( duration );
40401
40402 if ( warp ) {
40403
40404 var fadeInDuration = this._clip.duration,
40405 fadeOutDuration = fadeOutAction._clip.duration,
40406
40407 startEndRatio = fadeOutDuration / fadeInDuration,
40408 endStartRatio = fadeInDuration / fadeOutDuration;
40409
40410 fadeOutAction.warp( 1.0, startEndRatio, duration );
40411 this.warp( endStartRatio, 1.0, duration );
40412
40413 }
40414
40415 return this;
40416
40417 },
40418
40419 crossFadeTo: function ( fadeInAction, duration, warp ) {
40420
40421 return fadeInAction.crossFadeFrom( this, duration, warp );
40422
40423 },
40424
40425 stopFading: function () {
40426
40427 var weightInterpolant = this._weightInterpolant;
40428
40429 if ( weightInterpolant !== null ) {
40430
40431 this._weightInterpolant = null;
40432 this._mixer._takeBackControlInterpolant( weightInterpolant );
40433
40434 }
40435
40436 return this;
40437
40438 },
40439
40440 // Time Scale Control
40441
40442 // set the time scale stopping any scheduled warping
40443 // although .paused = true yields an effective time scale of zero, this
40444 // method does *not* change .paused, because it would be confusing
40445 setEffectiveTimeScale: function ( timeScale ) {
40446
40447 this.timeScale = timeScale;
40448 this._effectiveTimeScale = this.paused ? 0 : timeScale;
40449
40450 return this.stopWarping();
40451
40452 },
40453
40454 // return the time scale considering warping and .paused
40455 getEffectiveTimeScale: function () {
40456
40457 return this._effectiveTimeScale;
40458
40459 },
40460
40461 setDuration: function ( duration ) {
40462
40463 this.timeScale = this._clip.duration / duration;
40464
40465 return this.stopWarping();
40466
40467 },
40468
40469 syncWith: function ( action ) {
40470
40471 this.time = action.time;
40472 this.timeScale = action.timeScale;
40473
40474 return this.stopWarping();
40475
40476 },
40477
40478 halt: function ( duration ) {
40479
40480 return this.warp( this._effectiveTimeScale, 0, duration );
40481
40482 },
40483
40484 warp: function ( startTimeScale, endTimeScale, duration ) {
40485
40486 var mixer = this._mixer, now = mixer.time,
40487 interpolant = this._timeScaleInterpolant,
40488
40489 timeScale = this.timeScale;
40490
40491 if ( interpolant === null ) {
40492
40493 interpolant = mixer._lendControlInterpolant();
40494 this._timeScaleInterpolant = interpolant;
40495
40496 }
40497
40498 var times = interpolant.parameterPositions,
40499 values = interpolant.sampleValues;
40500
40501 times[ 0 ] = now;
40502 times[ 1 ] = now + duration;
40503
40504 values[ 0 ] = startTimeScale / timeScale;
40505 values[ 1 ] = endTimeScale / timeScale;
40506
40507 return this;
40508
40509 },
40510
40511 stopWarping: function () {
40512
40513 var timeScaleInterpolant = this._timeScaleInterpolant;
40514
40515 if ( timeScaleInterpolant !== null ) {
40516
40517 this._timeScaleInterpolant = null;
40518 this._mixer._takeBackControlInterpolant( timeScaleInterpolant );
40519
40520 }
40521
40522 return this;
40523
40524 },
40525
40526 // Object Accessors
40527
40528 getMixer: function () {
40529
40530 return this._mixer;
40531
40532 },
40533
40534 getClip: function () {
40535
40536 return this._clip;
40537
40538 },
40539
40540 getRoot: function () {
40541
40542 return this._localRoot || this._mixer._root;
40543
40544 },
40545
40546 // Interna
40547
40548 _update: function ( time, deltaTime, timeDirection, accuIndex ) {
40549
40550 // called by the mixer
40551
40552 if ( ! this.enabled ) {
40553
40554 // call ._updateWeight() to update ._effectiveWeight
40555
40556 this._updateWeight( time );
40557 return;
40558
40559 }
40560
40561 var startTime = this._startTime;
40562
40563 if ( startTime !== null ) {
40564
40565 // check for scheduled start of action
40566
40567 var timeRunning = ( time - startTime ) * timeDirection;
40568 if ( timeRunning < 0 || timeDirection === 0 ) {
40569
40570 return; // yet to come / don't decide when delta = 0
40571
40572 }
40573
40574 // start
40575
40576 this._startTime = null; // unschedule
40577 deltaTime = timeDirection * timeRunning;
40578
40579 }
40580
40581 // apply time scale and advance time
40582
40583 deltaTime *= this._updateTimeScale( time );
40584 var clipTime = this._updateTime( deltaTime );
40585
40586 // note: _updateTime may disable the action resulting in
40587 // an effective weight of 0
40588
40589 var weight = this._updateWeight( time );
40590
40591 if ( weight > 0 ) {
40592
40593 var interpolants = this._interpolants;
40594 var propertyMixers = this._propertyBindings;
40595
40596 for ( var j = 0, m = interpolants.length; j !== m; ++ j ) {
40597
40598 interpolants[ j ].evaluate( clipTime );
40599 propertyMixers[ j ].accumulate( accuIndex, weight );
40600
40601 }
40602
40603 }
40604
40605 },
40606
40607 _updateWeight: function ( time ) {
40608
40609 var weight = 0;
40610
40611 if ( this.enabled ) {
40612
40613 weight = this.weight;
40614 var interpolant = this._weightInterpolant;
40615
40616 if ( interpolant !== null ) {
40617
40618 var interpolantValue = interpolant.evaluate( time )[ 0 ];
40619
40620 weight *= interpolantValue;
40621
40622 if ( time > interpolant.parameterPositions[ 1 ] ) {
40623
40624 this.stopFading();
40625
40626 if ( interpolantValue === 0 ) {
40627
40628 // faded out, disable
40629 this.enabled = false;
40630
40631 }
40632
40633 }
40634
40635 }
40636
40637 }
40638
40639 this._effectiveWeight = weight;
40640 return weight;
40641
40642 },
40643
40644 _updateTimeScale: function ( time ) {
40645
40646 var timeScale = 0;
40647
40648 if ( ! this.paused ) {
40649
40650 timeScale = this.timeScale;
40651
40652 var interpolant = this._timeScaleInterpolant;
40653
40654 if ( interpolant !== null ) {
40655
40656 var interpolantValue = interpolant.evaluate( time )[ 0 ];
40657
40658 timeScale *= interpolantValue;
40659
40660 if ( time > interpolant.parameterPositions[ 1 ] ) {
40661
40662 this.stopWarping();
40663
40664 if ( timeScale === 0 ) {
40665
40666 // motion has halted, pause
40667 this.paused = true;
40668
40669 } else {
40670
40671 // warp done - apply final time scale
40672 this.timeScale = timeScale;
40673
40674 }
40675
40676 }
40677
40678 }
40679
40680 }
40681
40682 this._effectiveTimeScale = timeScale;
40683 return timeScale;
40684
40685 },
40686
40687 _updateTime: function ( deltaTime ) {
40688
40689 var time = this.time + deltaTime;
40690
40691 if ( deltaTime === 0 ) return time;
40692
40693 var duration = this._clip.duration,
40694
40695 loop = this.loop,
40696 loopCount = this._loopCount;
40697
40698 if ( loop === LoopOnce ) {
40699
40700 if ( loopCount === - 1 ) {
40701
40702 // just started
40703
40704 this._loopCount = 0;
40705 this._setEndings( true, true, false );
40706
40707 }
40708
40709 handle_stop: {
40710
40711 if ( time >= duration ) {
40712
40713 time = duration;
40714
40715 } else if ( time < 0 ) {
40716
40717 time = 0;
40718
40719 } else break handle_stop;
40720
40721 if ( this.clampWhenFinished ) this.paused = true;
40722 else this.enabled = false;
40723
40724 this._mixer.dispatchEvent( {
40725 type: 'finished', action: this,
40726 direction: deltaTime < 0 ? - 1 : 1
40727 } );
40728
40729 }
40730
40731 } else { // repetitive Repeat or PingPong
40732
40733 var pingPong = ( loop === LoopPingPong );
40734
40735 if ( loopCount === - 1 ) {
40736
40737 // just started
40738
40739 if ( deltaTime >= 0 ) {
40740
40741 loopCount = 0;
40742
40743 this._setEndings( true, this.repetitions === 0, pingPong );
40744
40745 } else {
40746
40747 // when looping in reverse direction, the initial
40748 // transition through zero counts as a repetition,
40749 // so leave loopCount at -1
40750
40751 this._setEndings( this.repetitions === 0, true, pingPong );
40752
40753 }
40754
40755 }
40756
40757 if ( time >= duration || time < 0 ) {
40758
40759 // wrap around
40760
40761 var loopDelta = Math.floor( time / duration ); // signed
40762 time -= duration * loopDelta;
40763
40764 loopCount += Math.abs( loopDelta );
40765
40766 var pending = this.repetitions - loopCount;
40767
40768 if ( pending <= 0 ) {
40769
40770 // have to stop (switch state, clamp time, fire event)
40771
40772 if ( this.clampWhenFinished ) this.paused = true;
40773 else this.enabled = false;
40774
40775 time = deltaTime > 0 ? duration : 0;
40776
40777 this._mixer.dispatchEvent( {
40778 type: 'finished', action: this,
40779 direction: deltaTime > 0 ? 1 : - 1
40780 } );
40781
40782 } else {
40783
40784 // keep running
40785
40786 if ( pending === 1 ) {
40787
40788 // entering the last round
40789
40790 var atStart = deltaTime < 0;
40791 this._setEndings( atStart, ! atStart, pingPong );
40792
40793 } else {
40794
40795 this._setEndings( false, false, pingPong );
40796
40797 }
40798
40799 this._loopCount = loopCount;
40800
40801 this._mixer.dispatchEvent( {
40802 type: 'loop', action: this, loopDelta: loopDelta
40803 } );
40804
40805 }
40806
40807 }
40808
40809 if ( pingPong && ( loopCount & 1 ) === 1 ) {
40810
40811 // invert time for the "pong round"
40812
40813 this.time = time;
40814 return duration - time;
40815
40816 }
40817
40818 }
40819
40820 this.time = time;
40821 return time;
40822
40823 },
40824
40825 _setEndings: function ( atStart, atEnd, pingPong ) {
40826
40827 var settings = this._interpolantSettings;
40828
40829 if ( pingPong ) {
40830
40831 settings.endingStart = ZeroSlopeEnding;
40832 settings.endingEnd = ZeroSlopeEnding;
40833
40834 } else {
40835
40836 // assuming for LoopOnce atStart == atEnd == true
40837
40838 if ( atStart ) {
40839
40840 settings.endingStart = this.zeroSlopeAtStart ? ZeroSlopeEnding : ZeroCurvatureEnding;
40841
40842 } else {
40843
40844 settings.endingStart = WrapAroundEnding;
40845
40846 }
40847
40848 if ( atEnd ) {
40849
40850 settings.endingEnd = this.zeroSlopeAtEnd ? ZeroSlopeEnding : ZeroCurvatureEnding;
40851
40852 } else {
40853
40854 settings.endingEnd = WrapAroundEnding;
40855
40856 }
40857
40858 }
40859
40860 },
40861
40862 _scheduleFading: function ( duration, weightNow, weightThen ) {
40863
40864 var mixer = this._mixer, now = mixer.time,
40865 interpolant = this._weightInterpolant;
40866
40867 if ( interpolant === null ) {
40868
40869 interpolant = mixer._lendControlInterpolant();
40870 this._weightInterpolant = interpolant;
40871
40872 }
40873
40874 var times = interpolant.parameterPositions,
40875 values = interpolant.sampleValues;
40876
40877 times[ 0 ] = now; values[ 0 ] = weightNow;
40878 times[ 1 ] = now + duration; values[ 1 ] = weightThen;
40879
40880 return this;
40881
40882 }
40883
40884 } );
40885
40886 /**
40887 *
40888 * Player for AnimationClips.
40889 *
40890 *
40891 * @author Ben Houston / http://clara.io/
40892 * @author David Sarno / http://lighthaus.us/
40893 * @author tschw
40894 */
40895
40896 function AnimationMixer( root ) {
40897
40898 this._root = root;
40899 this._initMemoryManager();
40900 this._accuIndex = 0;
40901
40902 this.time = 0;
40903
40904 this.timeScale = 1.0;
40905
40906 }
40907
40908 AnimationMixer.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
40909
40910 constructor: AnimationMixer,
40911
40912 _bindAction: function ( action, prototypeAction ) {
40913
40914 var root = action._localRoot || this._root,
40915 tracks = action._clip.tracks,
40916 nTracks = tracks.length,
40917 bindings = action._propertyBindings,
40918 interpolants = action._interpolants,
40919 rootUuid = root.uuid,
40920 bindingsByRoot = this._bindingsByRootAndName,
40921 bindingsByName = bindingsByRoot[ rootUuid ];
40922
40923 if ( bindingsByName === undefined ) {
40924
40925 bindingsByName = {};
40926 bindingsByRoot[ rootUuid ] = bindingsByName;
40927
40928 }
40929
40930 for ( var i = 0; i !== nTracks; ++ i ) {
40931
40932 var track = tracks[ i ],
40933 trackName = track.name,
40934 binding = bindingsByName[ trackName ];
40935
40936 if ( binding !== undefined ) {
40937
40938 bindings[ i ] = binding;
40939
40940 } else {
40941
40942 binding = bindings[ i ];
40943
40944 if ( binding !== undefined ) {
40945
40946 // existing binding, make sure the cache knows
40947
40948 if ( binding._cacheIndex === null ) {
40949
40950 ++ binding.referenceCount;
40951 this._addInactiveBinding( binding, rootUuid, trackName );
40952
40953 }
40954
40955 continue;
40956
40957 }
40958
40959 var path = prototypeAction && prototypeAction.
40960 _propertyBindings[ i ].binding.parsedPath;
40961
40962 binding = new PropertyMixer(
40963 PropertyBinding.create( root, trackName, path ),
40964 track.ValueTypeName, track.getValueSize() );
40965
40966 ++ binding.referenceCount;
40967 this._addInactiveBinding( binding, rootUuid, trackName );
40968
40969 bindings[ i ] = binding;
40970
40971 }
40972
40973 interpolants[ i ].resultBuffer = binding.buffer;
40974
40975 }
40976
40977 },
40978
40979 _activateAction: function ( action ) {
40980
40981 if ( ! this._isActiveAction( action ) ) {
40982
40983 if ( action._cacheIndex === null ) {
40984
40985 // this action has been forgotten by the cache, but the user
40986 // appears to be still using it -> rebind
40987
40988 var rootUuid = ( action._localRoot || this._root ).uuid,
40989 clipUuid = action._clip.uuid,
40990 actionsForClip = this._actionsByClip[ clipUuid ];
40991
40992 this._bindAction( action,
40993 actionsForClip && actionsForClip.knownActions[ 0 ] );
40994
40995 this._addInactiveAction( action, clipUuid, rootUuid );
40996
40997 }
40998
40999 var bindings = action._propertyBindings;
41000
41001 // increment reference counts / sort out state
41002 for ( var i = 0, n = bindings.length; i !== n; ++ i ) {
41003
41004 var binding = bindings[ i ];
41005
41006 if ( binding.useCount ++ === 0 ) {
41007
41008 this._lendBinding( binding );
41009 binding.saveOriginalState();
41010
41011 }
41012
41013 }
41014
41015 this._lendAction( action );
41016
41017 }
41018
41019 },
41020
41021 _deactivateAction: function ( action ) {
41022
41023 if ( this._isActiveAction( action ) ) {
41024
41025 var bindings = action._propertyBindings;
41026
41027 // decrement reference counts / sort out state
41028 for ( var i = 0, n = bindings.length; i !== n; ++ i ) {
41029
41030 var binding = bindings[ i ];
41031
41032 if ( -- binding.useCount === 0 ) {
41033
41034 binding.restoreOriginalState();
41035 this._takeBackBinding( binding );
41036
41037 }
41038
41039 }
41040
41041 this._takeBackAction( action );
41042
41043 }
41044
41045 },
41046
41047 // Memory manager
41048
41049 _initMemoryManager: function () {
41050
41051 this._actions = []; // 'nActiveActions' followed by inactive ones
41052 this._nActiveActions = 0;
41053
41054 this._actionsByClip = {};
41055 // inside:
41056 // {
41057 // knownActions: Array< AnimationAction > - used as prototypes
41058 // actionByRoot: AnimationAction - lookup
41059 // }
41060
41061
41062 this._bindings = []; // 'nActiveBindings' followed by inactive ones
41063 this._nActiveBindings = 0;
41064
41065 this._bindingsByRootAndName = {}; // inside: Map< name, PropertyMixer >
41066
41067
41068 this._controlInterpolants = []; // same game as above
41069 this._nActiveControlInterpolants = 0;
41070
41071 var scope = this;
41072
41073 this.stats = {
41074
41075 actions: {
41076 get total() {
41077
41078 return scope._actions.length;
41079
41080 },
41081 get inUse() {
41082
41083 return scope._nActiveActions;
41084
41085 }
41086 },
41087 bindings: {
41088 get total() {
41089
41090 return scope._bindings.length;
41091
41092 },
41093 get inUse() {
41094
41095 return scope._nActiveBindings;
41096
41097 }
41098 },
41099 controlInterpolants: {
41100 get total() {
41101
41102 return scope._controlInterpolants.length;
41103
41104 },
41105 get inUse() {
41106
41107 return scope._nActiveControlInterpolants;
41108
41109 }
41110 }
41111
41112 };
41113
41114 },
41115
41116 // Memory management for AnimationAction objects
41117
41118 _isActiveAction: function ( action ) {
41119
41120 var index = action._cacheIndex;
41121 return index !== null && index < this._nActiveActions;
41122
41123 },
41124
41125 _addInactiveAction: function ( action, clipUuid, rootUuid ) {
41126
41127 var actions = this._actions,
41128 actionsByClip = this._actionsByClip,
41129 actionsForClip = actionsByClip[ clipUuid ];
41130
41131 if ( actionsForClip === undefined ) {
41132
41133 actionsForClip = {
41134
41135 knownActions: [ action ],
41136 actionByRoot: {}
41137
41138 };
41139
41140 action._byClipCacheIndex = 0;
41141
41142 actionsByClip[ clipUuid ] = actionsForClip;
41143
41144 } else {
41145
41146 var knownActions = actionsForClip.knownActions;
41147
41148 action._byClipCacheIndex = knownActions.length;
41149 knownActions.push( action );
41150
41151 }
41152
41153 action._cacheIndex = actions.length;
41154 actions.push( action );
41155
41156 actionsForClip.actionByRoot[ rootUuid ] = action;
41157
41158 },
41159
41160 _removeInactiveAction: function ( action ) {
41161
41162 var actions = this._actions,
41163 lastInactiveAction = actions[ actions.length - 1 ],
41164 cacheIndex = action._cacheIndex;
41165
41166 lastInactiveAction._cacheIndex = cacheIndex;
41167 actions[ cacheIndex ] = lastInactiveAction;
41168 actions.pop();
41169
41170 action._cacheIndex = null;
41171
41172
41173 var clipUuid = action._clip.uuid,
41174 actionsByClip = this._actionsByClip,
41175 actionsForClip = actionsByClip[ clipUuid ],
41176 knownActionsForClip = actionsForClip.knownActions,
41177
41178 lastKnownAction =
41179 knownActionsForClip[ knownActionsForClip.length - 1 ],
41180
41181 byClipCacheIndex = action._byClipCacheIndex;
41182
41183 lastKnownAction._byClipCacheIndex = byClipCacheIndex;
41184 knownActionsForClip[ byClipCacheIndex ] = lastKnownAction;
41185 knownActionsForClip.pop();
41186
41187 action._byClipCacheIndex = null;
41188
41189
41190 var actionByRoot = actionsForClip.actionByRoot,
41191 rootUuid = ( action._localRoot || this._root ).uuid;
41192
41193 delete actionByRoot[ rootUuid ];
41194
41195 if ( knownActionsForClip.length === 0 ) {
41196
41197 delete actionsByClip[ clipUuid ];
41198
41199 }
41200
41201 this._removeInactiveBindingsForAction( action );
41202
41203 },
41204
41205 _removeInactiveBindingsForAction: function ( action ) {
41206
41207 var bindings = action._propertyBindings;
41208 for ( var i = 0, n = bindings.length; i !== n; ++ i ) {
41209
41210 var binding = bindings[ i ];
41211
41212 if ( -- binding.referenceCount === 0 ) {
41213
41214 this._removeInactiveBinding( binding );
41215
41216 }
41217
41218 }
41219
41220 },
41221
41222 _lendAction: function ( action ) {
41223
41224 // [ active actions | inactive actions ]
41225 // [ active actions >| inactive actions ]
41226 // s a
41227 // <-swap->
41228 // a s
41229
41230 var actions = this._actions,
41231 prevIndex = action._cacheIndex,
41232
41233 lastActiveIndex = this._nActiveActions ++,
41234
41235 firstInactiveAction = actions[ lastActiveIndex ];
41236
41237 action._cacheIndex = lastActiveIndex;
41238 actions[ lastActiveIndex ] = action;
41239
41240 firstInactiveAction._cacheIndex = prevIndex;
41241 actions[ prevIndex ] = firstInactiveAction;
41242
41243 },
41244
41245 _takeBackAction: function ( action ) {
41246
41247 // [ active actions | inactive actions ]
41248 // [ active actions |< inactive actions ]
41249 // a s
41250 // <-swap->
41251 // s a
41252
41253 var actions = this._actions,
41254 prevIndex = action._cacheIndex,
41255
41256 firstInactiveIndex = -- this._nActiveActions,
41257
41258 lastActiveAction = actions[ firstInactiveIndex ];
41259
41260 action._cacheIndex = firstInactiveIndex;
41261 actions[ firstInactiveIndex ] = action;
41262
41263 lastActiveAction._cacheIndex = prevIndex;
41264 actions[ prevIndex ] = lastActiveAction;
41265
41266 },
41267
41268 // Memory management for PropertyMixer objects
41269
41270 _addInactiveBinding: function ( binding, rootUuid, trackName ) {
41271
41272 var bindingsByRoot = this._bindingsByRootAndName,
41273 bindingByName = bindingsByRoot[ rootUuid ],
41274
41275 bindings = this._bindings;
41276
41277 if ( bindingByName === undefined ) {
41278
41279 bindingByName = {};
41280 bindingsByRoot[ rootUuid ] = bindingByName;
41281
41282 }
41283
41284 bindingByName[ trackName ] = binding;
41285
41286 binding._cacheIndex = bindings.length;
41287 bindings.push( binding );
41288
41289 },
41290
41291 _removeInactiveBinding: function ( binding ) {
41292
41293 var bindings = this._bindings,
41294 propBinding = binding.binding,
41295 rootUuid = propBinding.rootNode.uuid,
41296 trackName = propBinding.path,
41297 bindingsByRoot = this._bindingsByRootAndName,
41298 bindingByName = bindingsByRoot[ rootUuid ],
41299
41300 lastInactiveBinding = bindings[ bindings.length - 1 ],
41301 cacheIndex = binding._cacheIndex;
41302
41303 lastInactiveBinding._cacheIndex = cacheIndex;
41304 bindings[ cacheIndex ] = lastInactiveBinding;
41305 bindings.pop();
41306
41307 delete bindingByName[ trackName ];
41308
41309 remove_empty_map: {
41310
41311 for ( var _ in bindingByName ) break remove_empty_map; // eslint-disable-line no-unused-vars
41312
41313 delete bindingsByRoot[ rootUuid ];
41314
41315 }
41316
41317 },
41318
41319 _lendBinding: function ( binding ) {
41320
41321 var bindings = this._bindings,
41322 prevIndex = binding._cacheIndex,
41323
41324 lastActiveIndex = this._nActiveBindings ++,
41325
41326 firstInactiveBinding = bindings[ lastActiveIndex ];
41327
41328 binding._cacheIndex = lastActiveIndex;
41329 bindings[ lastActiveIndex ] = binding;
41330
41331 firstInactiveBinding._cacheIndex = prevIndex;
41332 bindings[ prevIndex ] = firstInactiveBinding;
41333
41334 },
41335
41336 _takeBackBinding: function ( binding ) {
41337
41338 var bindings = this._bindings,
41339 prevIndex = binding._cacheIndex,
41340
41341 firstInactiveIndex = -- this._nActiveBindings,
41342
41343 lastActiveBinding = bindings[ firstInactiveIndex ];
41344
41345 binding._cacheIndex = firstInactiveIndex;
41346 bindings[ firstInactiveIndex ] = binding;
41347
41348 lastActiveBinding._cacheIndex = prevIndex;
41349 bindings[ prevIndex ] = lastActiveBinding;
41350
41351 },
41352
41353
41354 // Memory management of Interpolants for weight and time scale
41355
41356 _lendControlInterpolant: function () {
41357
41358 var interpolants = this._controlInterpolants,
41359 lastActiveIndex = this._nActiveControlInterpolants ++,
41360 interpolant = interpolants[ lastActiveIndex ];
41361
41362 if ( interpolant === undefined ) {
41363
41364 interpolant = new LinearInterpolant(
41365 new Float32Array( 2 ), new Float32Array( 2 ),
41366 1, this._controlInterpolantsResultBuffer );
41367
41368 interpolant.__cacheIndex = lastActiveIndex;
41369 interpolants[ lastActiveIndex ] = interpolant;
41370
41371 }
41372
41373 return interpolant;
41374
41375 },
41376
41377 _takeBackControlInterpolant: function ( interpolant ) {
41378
41379 var interpolants = this._controlInterpolants,
41380 prevIndex = interpolant.__cacheIndex,
41381
41382 firstInactiveIndex = -- this._nActiveControlInterpolants,
41383
41384 lastActiveInterpolant = interpolants[ firstInactiveIndex ];
41385
41386 interpolant.__cacheIndex = firstInactiveIndex;
41387 interpolants[ firstInactiveIndex ] = interpolant;
41388
41389 lastActiveInterpolant.__cacheIndex = prevIndex;
41390 interpolants[ prevIndex ] = lastActiveInterpolant;
41391
41392 },
41393
41394 _controlInterpolantsResultBuffer: new Float32Array( 1 ),
41395
41396 // return an action for a clip optionally using a custom root target
41397 // object (this method allocates a lot of dynamic memory in case a
41398 // previously unknown clip/root combination is specified)
41399 clipAction: function ( clip, optionalRoot ) {
41400
41401 var root = optionalRoot || this._root,
41402 rootUuid = root.uuid,
41403
41404 clipObject = typeof clip === 'string' ?
41405 AnimationClip.findByName( root, clip ) : clip,
41406
41407 clipUuid = clipObject !== null ? clipObject.uuid : clip,
41408
41409 actionsForClip = this._actionsByClip[ clipUuid ],
41410 prototypeAction = null;
41411
41412 if ( actionsForClip !== undefined ) {
41413
41414 var existingAction =
41415 actionsForClip.actionByRoot[ rootUuid ];
41416
41417 if ( existingAction !== undefined ) {
41418
41419 return existingAction;
41420
41421 }
41422
41423 // we know the clip, so we don't have to parse all
41424 // the bindings again but can just copy
41425 prototypeAction = actionsForClip.knownActions[ 0 ];
41426
41427 // also, take the clip from the prototype action
41428 if ( clipObject === null )
41429 clipObject = prototypeAction._clip;
41430
41431 }
41432
41433 // clip must be known when specified via string
41434 if ( clipObject === null ) return null;
41435
41436 // allocate all resources required to run it
41437 var newAction = new AnimationAction( this, clipObject, optionalRoot );
41438
41439 this._bindAction( newAction, prototypeAction );
41440
41441 // and make the action known to the memory manager
41442 this._addInactiveAction( newAction, clipUuid, rootUuid );
41443
41444 return newAction;
41445
41446 },
41447
41448 // get an existing action
41449 existingAction: function ( clip, optionalRoot ) {
41450
41451 var root = optionalRoot || this._root,
41452 rootUuid = root.uuid,
41453
41454 clipObject = typeof clip === 'string' ?
41455 AnimationClip.findByName( root, clip ) : clip,
41456
41457 clipUuid = clipObject ? clipObject.uuid : clip,
41458
41459 actionsForClip = this._actionsByClip[ clipUuid ];
41460
41461 if ( actionsForClip !== undefined ) {
41462
41463 return actionsForClip.actionByRoot[ rootUuid ] || null;
41464
41465 }
41466
41467 return null;
41468
41469 },
41470
41471 // deactivates all previously scheduled actions
41472 stopAllAction: function () {
41473
41474 var actions = this._actions,
41475 nActions = this._nActiveActions,
41476 bindings = this._bindings,
41477 nBindings = this._nActiveBindings;
41478
41479 this._nActiveActions = 0;
41480 this._nActiveBindings = 0;
41481
41482 for ( var i = 0; i !== nActions; ++ i ) {
41483
41484 actions[ i ].reset();
41485
41486 }
41487
41488 for ( var i = 0; i !== nBindings; ++ i ) {
41489
41490 bindings[ i ].useCount = 0;
41491
41492 }
41493
41494 return this;
41495
41496 },
41497
41498 // advance the time and update apply the animation
41499 update: function ( deltaTime ) {
41500
41501 deltaTime *= this.timeScale;
41502
41503 var actions = this._actions,
41504 nActions = this._nActiveActions,
41505
41506 time = this.time += deltaTime,
41507 timeDirection = Math.sign( deltaTime ),
41508
41509 accuIndex = this._accuIndex ^= 1;
41510
41511 // run active actions
41512
41513 for ( var i = 0; i !== nActions; ++ i ) {
41514
41515 var action = actions[ i ];
41516
41517 action._update( time, deltaTime, timeDirection, accuIndex );
41518
41519 }
41520
41521 // update scene graph
41522
41523 var bindings = this._bindings,
41524 nBindings = this._nActiveBindings;
41525
41526 for ( var i = 0; i !== nBindings; ++ i ) {
41527
41528 bindings[ i ].apply( accuIndex );
41529
41530 }
41531
41532 return this;
41533
41534 },
41535
41536 // return this mixer's root target object
41537 getRoot: function () {
41538
41539 return this._root;
41540
41541 },
41542
41543 // free all resources specific to a particular clip
41544 uncacheClip: function ( clip ) {
41545
41546 var actions = this._actions,
41547 clipUuid = clip.uuid,
41548 actionsByClip = this._actionsByClip,
41549 actionsForClip = actionsByClip[ clipUuid ];
41550
41551 if ( actionsForClip !== undefined ) {
41552
41553 // note: just calling _removeInactiveAction would mess up the
41554 // iteration state and also require updating the state we can
41555 // just throw away
41556
41557 var actionsToRemove = actionsForClip.knownActions;
41558
41559 for ( var i = 0, n = actionsToRemove.length; i !== n; ++ i ) {
41560
41561 var action = actionsToRemove[ i ];
41562
41563 this._deactivateAction( action );
41564
41565 var cacheIndex = action._cacheIndex,
41566 lastInactiveAction = actions[ actions.length - 1 ];
41567
41568 action._cacheIndex = null;
41569 action._byClipCacheIndex = null;
41570
41571 lastInactiveAction._cacheIndex = cacheIndex;
41572 actions[ cacheIndex ] = lastInactiveAction;
41573 actions.pop();
41574
41575 this._removeInactiveBindingsForAction( action );
41576
41577 }
41578
41579 delete actionsByClip[ clipUuid ];
41580
41581 }
41582
41583 },
41584
41585 // free all resources specific to a particular root target object
41586 uncacheRoot: function ( root ) {
41587
41588 var rootUuid = root.uuid,
41589 actionsByClip = this._actionsByClip;
41590
41591 for ( var clipUuid in actionsByClip ) {
41592
41593 var actionByRoot = actionsByClip[ clipUuid ].actionByRoot,
41594 action = actionByRoot[ rootUuid ];
41595
41596 if ( action !== undefined ) {
41597
41598 this._deactivateAction( action );
41599 this._removeInactiveAction( action );
41600
41601 }
41602
41603 }
41604
41605 var bindingsByRoot = this._bindingsByRootAndName,
41606 bindingByName = bindingsByRoot[ rootUuid ];
41607
41608 if ( bindingByName !== undefined ) {
41609
41610 for ( var trackName in bindingByName ) {
41611
41612 var binding = bindingByName[ trackName ];
41613 binding.restoreOriginalState();
41614 this._removeInactiveBinding( binding );
41615
41616 }
41617
41618 }
41619
41620 },
41621
41622 // remove a targeted clip from the cache
41623 uncacheAction: function ( clip, optionalRoot ) {
41624
41625 var action = this.existingAction( clip, optionalRoot );
41626
41627 if ( action !== null ) {
41628
41629 this._deactivateAction( action );
41630 this._removeInactiveAction( action );
41631
41632 }
41633
41634 }
41635
41636 } );
41637
41638 /**
41639 * @author mrdoob / http://mrdoob.com/
41640 */
41641
41642 function Uniform( value ) {
41643
41644 if ( typeof value === 'string' ) {
41645
41646 console.warn( 'THREE.Uniform: Type parameter is no longer needed.' );
41647 value = arguments[ 1 ];
41648
41649 }
41650
41651 this.value = value;
41652
41653 }
41654
41655 Uniform.prototype.clone = function () {
41656
41657 return new Uniform( this.value.clone === undefined ? this.value : this.value.clone() );
41658
41659 };
41660
41661 /**
41662 * @author benaadams / https://twitter.com/ben_a_adams
41663 */
41664
41665 function InstancedBufferGeometry() {
41666
41667 BufferGeometry.call( this );
41668
41669 this.type = 'InstancedBufferGeometry';
41670 this.maxInstancedCount = undefined;
41671
41672 }
41673
41674 InstancedBufferGeometry.prototype = Object.assign( Object.create( BufferGeometry.prototype ), {
41675
41676 constructor: InstancedBufferGeometry,
41677
41678 isInstancedBufferGeometry: true,
41679
41680 copy: function ( source ) {
41681
41682 BufferGeometry.prototype.copy.call( this, source );
41683
41684 this.maxInstancedCount = source.maxInstancedCount;
41685
41686 return this;
41687
41688 },
41689
41690 clone: function () {
41691
41692 return new this.constructor().copy( this );
41693
41694 }
41695
41696 } );
41697
41698 /**
41699 * @author benaadams / https://twitter.com/ben_a_adams
41700 */
41701
41702 function InterleavedBufferAttribute( interleavedBuffer, itemSize, offset, normalized ) {
41703
41704 this.data = interleavedBuffer;
41705 this.itemSize = itemSize;
41706 this.offset = offset;
41707
41708 this.normalized = normalized === true;
41709
41710 }
41711
41712 Object.defineProperties( InterleavedBufferAttribute.prototype, {
41713
41714 count: {
41715
41716 get: function () {
41717
41718 return this.data.count;
41719
41720 }
41721
41722 },
41723
41724 array: {
41725
41726 get: function () {
41727
41728 return this.data.array;
41729
41730 }
41731
41732 }
41733
41734 } );
41735
41736 Object.assign( InterleavedBufferAttribute.prototype, {
41737
41738 isInterleavedBufferAttribute: true,
41739
41740 setX: function ( index, x ) {
41741
41742 this.data.array[ index * this.data.stride + this.offset ] = x;
41743
41744 return this;
41745
41746 },
41747
41748 setY: function ( index, y ) {
41749
41750 this.data.array[ index * this.data.stride + this.offset + 1 ] = y;
41751
41752 return this;
41753
41754 },
41755
41756 setZ: function ( index, z ) {
41757
41758 this.data.array[ index * this.data.stride + this.offset + 2 ] = z;
41759
41760 return this;
41761
41762 },
41763
41764 setW: function ( index, w ) {
41765
41766 this.data.array[ index * this.data.stride + this.offset + 3 ] = w;
41767
41768 return this;
41769
41770 },
41771
41772 getX: function ( index ) {
41773
41774 return this.data.array[ index * this.data.stride + this.offset ];
41775
41776 },
41777
41778 getY: function ( index ) {
41779
41780 return this.data.array[ index * this.data.stride + this.offset + 1 ];
41781
41782 },
41783
41784 getZ: function ( index ) {
41785
41786 return this.data.array[ index * this.data.stride + this.offset + 2 ];
41787
41788 },
41789
41790 getW: function ( index ) {
41791
41792 return this.data.array[ index * this.data.stride + this.offset + 3 ];
41793
41794 },
41795
41796 setXY: function ( index, x, y ) {
41797
41798 index = index * this.data.stride + this.offset;
41799
41800 this.data.array[ index + 0 ] = x;
41801 this.data.array[ index + 1 ] = y;
41802
41803 return this;
41804
41805 },
41806
41807 setXYZ: function ( index, x, y, z ) {
41808
41809 index = index * this.data.stride + this.offset;
41810
41811 this.data.array[ index + 0 ] = x;
41812 this.data.array[ index + 1 ] = y;
41813 this.data.array[ index + 2 ] = z;
41814
41815 return this;
41816
41817 },
41818
41819 setXYZW: function ( index, x, y, z, w ) {
41820
41821 index = index * this.data.stride + this.offset;
41822
41823 this.data.array[ index + 0 ] = x;
41824 this.data.array[ index + 1 ] = y;
41825 this.data.array[ index + 2 ] = z;
41826 this.data.array[ index + 3 ] = w;
41827
41828 return this;
41829
41830 }
41831
41832 } );
41833
41834 /**
41835 * @author benaadams / https://twitter.com/ben_a_adams
41836 */
41837
41838 function InterleavedBuffer( array, stride ) {
41839
41840 this.array = array;
41841 this.stride = stride;
41842 this.count = array !== undefined ? array.length / stride : 0;
41843
41844 this.dynamic = false;
41845 this.updateRange = { offset: 0, count: - 1 };
41846
41847 this.version = 0;
41848
41849 }
41850
41851 Object.defineProperty( InterleavedBuffer.prototype, 'needsUpdate', {
41852
41853 set: function ( value ) {
41854
41855 if ( value === true ) this.version ++;
41856
41857 }
41858
41859 } );
41860
41861 Object.assign( InterleavedBuffer.prototype, {
41862
41863 isInterleavedBuffer: true,
41864
41865 onUploadCallback: function () {},
41866
41867 setArray: function ( array ) {
41868
41869 if ( Array.isArray( array ) ) {
41870
41871 throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' );
41872
41873 }
41874
41875 this.count = array !== undefined ? array.length / this.stride : 0;
41876 this.array = array;
41877
41878 return this;
41879
41880 },
41881
41882 setDynamic: function ( value ) {
41883
41884 this.dynamic = value;
41885
41886 return this;
41887
41888 },
41889
41890 copy: function ( source ) {
41891
41892 this.array = new source.array.constructor( source.array );
41893 this.count = source.count;
41894 this.stride = source.stride;
41895 this.dynamic = source.dynamic;
41896
41897 return this;
41898
41899 },
41900
41901 copyAt: function ( index1, attribute, index2 ) {
41902
41903 index1 *= this.stride;
41904 index2 *= attribute.stride;
41905
41906 for ( var i = 0, l = this.stride; i < l; i ++ ) {
41907
41908 this.array[ index1 + i ] = attribute.array[ index2 + i ];
41909
41910 }
41911
41912 return this;
41913
41914 },
41915
41916 set: function ( value, offset ) {
41917
41918 if ( offset === undefined ) offset = 0;
41919
41920 this.array.set( value, offset );
41921
41922 return this;
41923
41924 },
41925
41926 clone: function () {
41927
41928 return new this.constructor().copy( this );
41929
41930 },
41931
41932 onUpload: function ( callback ) {
41933
41934 this.onUploadCallback = callback;
41935
41936 return this;
41937
41938 }
41939
41940 } );
41941
41942 /**
41943 * @author benaadams / https://twitter.com/ben_a_adams
41944 */
41945
41946 function InstancedInterleavedBuffer( array, stride, meshPerAttribute ) {
41947
41948 InterleavedBuffer.call( this, array, stride );
41949
41950 this.meshPerAttribute = meshPerAttribute || 1;
41951
41952 }
41953
41954 InstancedInterleavedBuffer.prototype = Object.assign( Object.create( InterleavedBuffer.prototype ), {
41955
41956 constructor: InstancedInterleavedBuffer,
41957
41958 isInstancedInterleavedBuffer: true,
41959
41960 copy: function ( source ) {
41961
41962 InterleavedBuffer.prototype.copy.call( this, source );
41963
41964 this.meshPerAttribute = source.meshPerAttribute;
41965
41966 return this;
41967
41968 }
41969
41970 } );
41971
41972 /**
41973 * @author benaadams / https://twitter.com/ben_a_adams
41974 */
41975
41976 function InstancedBufferAttribute( array, itemSize, meshPerAttribute ) {
41977
41978 BufferAttribute.call( this, array, itemSize );
41979
41980 this.meshPerAttribute = meshPerAttribute || 1;
41981
41982 }
41983
41984 InstancedBufferAttribute.prototype = Object.assign( Object.create( BufferAttribute.prototype ), {
41985
41986 constructor: InstancedBufferAttribute,
41987
41988 isInstancedBufferAttribute: true,
41989
41990 copy: function ( source ) {
41991
41992 BufferAttribute.prototype.copy.call( this, source );
41993
41994 this.meshPerAttribute = source.meshPerAttribute;
41995
41996 return this;
41997
41998 }
41999
42000 } );
42001
42002 /**
42003 * @author mrdoob / http://mrdoob.com/
42004 * @author bhouston / http://clara.io/
42005 * @author stephomi / http://stephaneginier.com/
42006 */
42007
42008 function Raycaster( origin, direction, near, far ) {
42009
42010 this.ray = new Ray( origin, direction );
42011 // direction is assumed to be normalized (for accurate distance calculations)
42012
42013 this.near = near || 0;
42014 this.far = far || Infinity;
42015
42016 this.params = {
42017 Mesh: {},
42018 Line: {},
42019 LOD: {},
42020 Points: { threshold: 1 },
42021 Sprite: {}
42022 };
42023
42024 Object.defineProperties( this.params, {
42025 PointCloud: {
42026 get: function () {
42027
42028 console.warn( 'THREE.Raycaster: params.PointCloud has been renamed to params.Points.' );
42029 return this.Points;
42030
42031 }
42032 }
42033 } );
42034
42035 }
42036
42037 function ascSort( a, b ) {
42038
42039 return a.distance - b.distance;
42040
42041 }
42042
42043 function intersectObject( object, raycaster, intersects, recursive ) {
42044
42045 if ( object.visible === false ) return;
42046
42047 object.raycast( raycaster, intersects );
42048
42049 if ( recursive === true ) {
42050
42051 var children = object.children;
42052
42053 for ( var i = 0, l = children.length; i < l; i ++ ) {
42054
42055 intersectObject( children[ i ], raycaster, intersects, true );
42056
42057 }
42058
42059 }
42060
42061 }
42062
42063 Object.assign( Raycaster.prototype, {
42064
42065 linePrecision: 1,
42066
42067 set: function ( origin, direction ) {
42068
42069 // direction is assumed to be normalized (for accurate distance calculations)
42070
42071 this.ray.set( origin, direction );
42072
42073 },
42074
42075 setFromCamera: function ( coords, camera ) {
42076
42077 if ( ( camera && camera.isPerspectiveCamera ) ) {
42078
42079 this.ray.origin.setFromMatrixPosition( camera.matrixWorld );
42080 this.ray.direction.set( coords.x, coords.y, 0.5 ).unproject( camera ).sub( this.ray.origin ).normalize();
42081
42082 } else if ( ( camera && camera.isOrthographicCamera ) ) {
42083
42084 this.ray.origin.set( coords.x, coords.y, ( camera.near + camera.far ) / ( camera.near - camera.far ) ).unproject( camera ); // set origin in plane of camera
42085 this.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld );
42086
42087 } else {
42088
42089 console.error( 'THREE.Raycaster: Unsupported camera type.' );
42090
42091 }
42092
42093 },
42094
42095 intersectObject: function ( object, recursive, optionalTarget ) {
42096
42097 var intersects = optionalTarget || [];
42098
42099 intersectObject( object, this, intersects, recursive );
42100
42101 intersects.sort( ascSort );
42102
42103 return intersects;
42104
42105 },
42106
42107 intersectObjects: function ( objects, recursive, optionalTarget ) {
42108
42109 var intersects = optionalTarget || [];
42110
42111 if ( Array.isArray( objects ) === false ) {
42112
42113 console.warn( 'THREE.Raycaster.intersectObjects: objects is not an Array.' );
42114 return intersects;
42115
42116 }
42117
42118 for ( var i = 0, l = objects.length; i < l; i ++ ) {
42119
42120 intersectObject( objects[ i ], this, intersects, recursive );
42121
42122 }
42123
42124 intersects.sort( ascSort );
42125
42126 return intersects;
42127
42128 }
42129
42130 } );
42131
42132 /**
42133 * @author alteredq / http://alteredqualia.com/
42134 */
42135
42136 function Clock( autoStart ) {
42137
42138 this.autoStart = ( autoStart !== undefined ) ? autoStart : true;
42139
42140 this.startTime = 0;
42141 this.oldTime = 0;
42142 this.elapsedTime = 0;
42143
42144 this.running = false;
42145
42146 }
42147
42148 Object.assign( Clock.prototype, {
42149
42150 start: function () {
42151
42152 this.startTime = ( typeof performance === 'undefined' ? Date : performance ).now(); // see #10732
42153
42154 this.oldTime = this.startTime;
42155 this.elapsedTime = 0;
42156 this.running = true;
42157
42158 },
42159
42160 stop: function () {
42161
42162 this.getElapsedTime();
42163 this.running = false;
42164 this.autoStart = false;
42165
42166 },
42167
42168 getElapsedTime: function () {
42169
42170 this.getDelta();
42171 return this.elapsedTime;
42172
42173 },
42174
42175 getDelta: function () {
42176
42177 var diff = 0;
42178
42179 if ( this.autoStart && ! this.running ) {
42180
42181 this.start();
42182 return 0;
42183
42184 }
42185
42186 if ( this.running ) {
42187
42188 var newTime = ( typeof performance === 'undefined' ? Date : performance ).now();
42189
42190 diff = ( newTime - this.oldTime ) / 1000;
42191 this.oldTime = newTime;
42192
42193 this.elapsedTime += diff;
42194
42195 }
42196
42197 return diff;
42198
42199 }
42200
42201 } );
42202
42203 /**
42204 * @author bhouston / http://clara.io
42205 * @author WestLangley / http://github.com/WestLangley
42206 *
42207 * Ref: https://en.wikipedia.org/wiki/Spherical_coordinate_system
42208 *
42209 * The poles (phi) are at the positive and negative y axis.
42210 * The equator starts at positive z.
42211 */
42212
42213 function Spherical( radius, phi, theta ) {
42214
42215 this.radius = ( radius !== undefined ) ? radius : 1.0;
42216 this.phi = ( phi !== undefined ) ? phi : 0; // up / down towards top and bottom pole
42217 this.theta = ( theta !== undefined ) ? theta : 0; // around the equator of the sphere
42218
42219 return this;
42220
42221 }
42222
42223 Object.assign( Spherical.prototype, {
42224
42225 set: function ( radius, phi, theta ) {
42226
42227 this.radius = radius;
42228 this.phi = phi;
42229 this.theta = theta;
42230
42231 return this;
42232
42233 },
42234
42235 clone: function () {
42236
42237 return new this.constructor().copy( this );
42238
42239 },
42240
42241 copy: function ( other ) {
42242
42243 this.radius = other.radius;
42244 this.phi = other.phi;
42245 this.theta = other.theta;
42246
42247 return this;
42248
42249 },
42250
42251 // restrict phi to be betwee EPS and PI-EPS
42252 makeSafe: function () {
42253
42254 var EPS = 0.000001;
42255 this.phi = Math.max( EPS, Math.min( Math.PI - EPS, this.phi ) );
42256
42257 return this;
42258
42259 },
42260
42261 setFromVector3: function ( vec3 ) {
42262
42263 this.radius = vec3.length();
42264
42265 if ( this.radius === 0 ) {
42266
42267 this.theta = 0;
42268 this.phi = 0;
42269
42270 } else {
42271
42272 this.theta = Math.atan2( vec3.x, vec3.z ); // equator angle around y-up axis
42273 this.phi = Math.acos( _Math.clamp( vec3.y / this.radius, - 1, 1 ) ); // polar angle
42274
42275 }
42276
42277 return this;
42278
42279 }
42280
42281 } );
42282
42283 /**
42284 * @author Mugen87 / https://github.com/Mugen87
42285 *
42286 * Ref: https://en.wikipedia.org/wiki/Cylindrical_coordinate_system
42287 *
42288 */
42289
42290 function Cylindrical( radius, theta, y ) {
42291
42292 this.radius = ( radius !== undefined ) ? radius : 1.0; // distance from the origin to a point in the x-z plane
42293 this.theta = ( theta !== undefined ) ? theta : 0; // counterclockwise angle in the x-z plane measured in radians from the positive z-axis
42294 this.y = ( y !== undefined ) ? y : 0; // height above the x-z plane
42295
42296 return this;
42297
42298 }
42299
42300 Object.assign( Cylindrical.prototype, {
42301
42302 set: function ( radius, theta, y ) {
42303
42304 this.radius = radius;
42305 this.theta = theta;
42306 this.y = y;
42307
42308 return this;
42309
42310 },
42311
42312 clone: function () {
42313
42314 return new this.constructor().copy( this );
42315
42316 },
42317
42318 copy: function ( other ) {
42319
42320 this.radius = other.radius;
42321 this.theta = other.theta;
42322 this.y = other.y;
42323
42324 return this;
42325
42326 },
42327
42328 setFromVector3: function ( vec3 ) {
42329
42330 this.radius = Math.sqrt( vec3.x * vec3.x + vec3.z * vec3.z );
42331 this.theta = Math.atan2( vec3.x, vec3.z );
42332 this.y = vec3.y;
42333
42334 return this;
42335
42336 }
42337
42338 } );
42339
42340 /**
42341 * @author bhouston / http://clara.io
42342 */
42343
42344 function Box2( min, max ) {
42345
42346 this.min = ( min !== undefined ) ? min : new Vector2( + Infinity, + Infinity );
42347 this.max = ( max !== undefined ) ? max : new Vector2( - Infinity, - Infinity );
42348
42349 }
42350
42351 Object.assign( Box2.prototype, {
42352
42353 set: function ( min, max ) {
42354
42355 this.min.copy( min );
42356 this.max.copy( max );
42357
42358 return this;
42359
42360 },
42361
42362 setFromPoints: function ( points ) {
42363
42364 this.makeEmpty();
42365
42366 for ( var i = 0, il = points.length; i < il; i ++ ) {
42367
42368 this.expandByPoint( points[ i ] );
42369
42370 }
42371
42372 return this;
42373
42374 },
42375
42376 setFromCenterAndSize: function () {
42377
42378 var v1 = new Vector2();
42379
42380 return function setFromCenterAndSize( center, size ) {
42381
42382 var halfSize = v1.copy( size ).multiplyScalar( 0.5 );
42383 this.min.copy( center ).sub( halfSize );
42384 this.max.copy( center ).add( halfSize );
42385
42386 return this;
42387
42388 };
42389
42390 }(),
42391
42392 clone: function () {
42393
42394 return new this.constructor().copy( this );
42395
42396 },
42397
42398 copy: function ( box ) {
42399
42400 this.min.copy( box.min );
42401 this.max.copy( box.max );
42402
42403 return this;
42404
42405 },
42406
42407 makeEmpty: function () {
42408
42409 this.min.x = this.min.y = + Infinity;
42410 this.max.x = this.max.y = - Infinity;
42411
42412 return this;
42413
42414 },
42415
42416 isEmpty: function () {
42417
42418 // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
42419
42420 return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y );
42421
42422 },
42423
42424 getCenter: function ( target ) {
42425
42426 if ( target === undefined ) {
42427
42428 console.warn( 'THREE.Box2: .getCenter() target is now required' );
42429 target = new Vector2();
42430
42431 }
42432
42433 return this.isEmpty() ? target.set( 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 );
42434
42435 },
42436
42437 getSize: function ( target ) {
42438
42439 if ( target === undefined ) {
42440
42441 console.warn( 'THREE.Box2: .getSize() target is now required' );
42442 target = new Vector2();
42443
42444 }
42445
42446 return this.isEmpty() ? target.set( 0, 0 ) : target.subVectors( this.max, this.min );
42447
42448 },
42449
42450 expandByPoint: function ( point ) {
42451
42452 this.min.min( point );
42453 this.max.max( point );
42454
42455 return this;
42456
42457 },
42458
42459 expandByVector: function ( vector ) {
42460
42461 this.min.sub( vector );
42462 this.max.add( vector );
42463
42464 return this;
42465
42466 },
42467
42468 expandByScalar: function ( scalar ) {
42469
42470 this.min.addScalar( - scalar );
42471 this.max.addScalar( scalar );
42472
42473 return this;
42474
42475 },
42476
42477 containsPoint: function ( point ) {
42478
42479 return point.x < this.min.x || point.x > this.max.x ||
42480 point.y < this.min.y || point.y > this.max.y ? false : true;
42481
42482 },
42483
42484 containsBox: function ( box ) {
42485
42486 return this.min.x <= box.min.x && box.max.x <= this.max.x &&
42487 this.min.y <= box.min.y && box.max.y <= this.max.y;
42488
42489 },
42490
42491 getParameter: function ( point, target ) {
42492
42493 // This can potentially have a divide by zero if the box
42494 // has a size dimension of 0.
42495
42496 if ( target === undefined ) {
42497
42498 console.warn( 'THREE.Box2: .getParameter() target is now required' );
42499 target = new Vector2();
42500
42501 }
42502
42503 return target.set(
42504 ( point.x - this.min.x ) / ( this.max.x - this.min.x ),
42505 ( point.y - this.min.y ) / ( this.max.y - this.min.y )
42506 );
42507
42508 },
42509
42510 intersectsBox: function ( box ) {
42511
42512 // using 4 splitting planes to rule out intersections
42513
42514 return box.max.x < this.min.x || box.min.x > this.max.x ||
42515 box.max.y < this.min.y || box.min.y > this.max.y ? false : true;
42516
42517 },
42518
42519 clampPoint: function ( point, target ) {
42520
42521 if ( target === undefined ) {
42522
42523 console.warn( 'THREE.Box2: .clampPoint() target is now required' );
42524 target = new Vector2();
42525
42526 }
42527
42528 return target.copy( point ).clamp( this.min, this.max );
42529
42530 },
42531
42532 distanceToPoint: function () {
42533
42534 var v1 = new Vector2();
42535
42536 return function distanceToPoint( point ) {
42537
42538 var clampedPoint = v1.copy( point ).clamp( this.min, this.max );
42539 return clampedPoint.sub( point ).length();
42540
42541 };
42542
42543 }(),
42544
42545 intersect: function ( box ) {
42546
42547 this.min.max( box.min );
42548 this.max.min( box.max );
42549
42550 return this;
42551
42552 },
42553
42554 union: function ( box ) {
42555
42556 this.min.min( box.min );
42557 this.max.max( box.max );
42558
42559 return this;
42560
42561 },
42562
42563 translate: function ( offset ) {
42564
42565 this.min.add( offset );
42566 this.max.add( offset );
42567
42568 return this;
42569
42570 },
42571
42572 equals: function ( box ) {
42573
42574 return box.min.equals( this.min ) && box.max.equals( this.max );
42575
42576 }
42577
42578 } );
42579
42580 /**
42581 * @author alteredq / http://alteredqualia.com/
42582 */
42583
42584 function ImmediateRenderObject( material ) {
42585
42586 Object3D.call( this );
42587
42588 this.material = material;
42589 this.render = function ( /* renderCallback */ ) {};
42590
42591 }
42592
42593 ImmediateRenderObject.prototype = Object.create( Object3D.prototype );
42594 ImmediateRenderObject.prototype.constructor = ImmediateRenderObject;
42595
42596 ImmediateRenderObject.prototype.isImmediateRenderObject = true;
42597
42598 /**
42599 * @author mrdoob / http://mrdoob.com/
42600 * @author WestLangley / http://github.com/WestLangley
42601 */
42602
42603 function VertexNormalsHelper( object, size, hex, linewidth ) {
42604
42605 this.object = object;
42606
42607 this.size = ( size !== undefined ) ? size : 1;
42608
42609 var color = ( hex !== undefined ) ? hex : 0xff0000;
42610
42611 var width = ( linewidth !== undefined ) ? linewidth : 1;
42612
42613 //
42614
42615 var nNormals = 0;
42616
42617 var objGeometry = this.object.geometry;
42618
42619 if ( objGeometry && objGeometry.isGeometry ) {
42620
42621 nNormals = objGeometry.faces.length * 3;
42622
42623 } else if ( objGeometry && objGeometry.isBufferGeometry ) {
42624
42625 nNormals = objGeometry.attributes.normal.count;
42626
42627 }
42628
42629 //
42630
42631 var geometry = new BufferGeometry();
42632
42633 var positions = new Float32BufferAttribute( nNormals * 2 * 3, 3 );
42634
42635 geometry.addAttribute( 'position', positions );
42636
42637 LineSegments.call( this, geometry, new LineBasicMaterial( { color: color, linewidth: width } ) );
42638
42639 //
42640
42641 this.matrixAutoUpdate = false;
42642
42643 this.update();
42644
42645 }
42646
42647 VertexNormalsHelper.prototype = Object.create( LineSegments.prototype );
42648 VertexNormalsHelper.prototype.constructor = VertexNormalsHelper;
42649
42650 VertexNormalsHelper.prototype.update = ( function () {
42651
42652 var v1 = new Vector3();
42653 var v2 = new Vector3();
42654 var normalMatrix = new Matrix3();
42655
42656 return function update() {
42657
42658 var keys = [ 'a', 'b', 'c' ];
42659
42660 this.object.updateMatrixWorld( true );
42661
42662 normalMatrix.getNormalMatrix( this.object.matrixWorld );
42663
42664 var matrixWorld = this.object.matrixWorld;
42665
42666 var position = this.geometry.attributes.position;
42667
42668 //
42669
42670 var objGeometry = this.object.geometry;
42671
42672 if ( objGeometry && objGeometry.isGeometry ) {
42673
42674 var vertices = objGeometry.vertices;
42675
42676 var faces = objGeometry.faces;
42677
42678 var idx = 0;
42679
42680 for ( var i = 0, l = faces.length; i < l; i ++ ) {
42681
42682 var face = faces[ i ];
42683
42684 for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {
42685
42686 var vertex = vertices[ face[ keys[ j ] ] ];
42687
42688 var normal = face.vertexNormals[ j ];
42689
42690 v1.copy( vertex ).applyMatrix4( matrixWorld );
42691
42692 v2.copy( normal ).applyMatrix3( normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 );
42693
42694 position.setXYZ( idx, v1.x, v1.y, v1.z );
42695
42696 idx = idx + 1;
42697
42698 position.setXYZ( idx, v2.x, v2.y, v2.z );
42699
42700 idx = idx + 1;
42701
42702 }
42703
42704 }
42705
42706 } else if ( objGeometry && objGeometry.isBufferGeometry ) {
42707
42708 var objPos = objGeometry.attributes.position;
42709
42710 var objNorm = objGeometry.attributes.normal;
42711
42712 var idx = 0;
42713
42714 // for simplicity, ignore index and drawcalls, and render every normal
42715
42716 for ( var j = 0, jl = objPos.count; j < jl; j ++ ) {
42717
42718 v1.set( objPos.getX( j ), objPos.getY( j ), objPos.getZ( j ) ).applyMatrix4( matrixWorld );
42719
42720 v2.set( objNorm.getX( j ), objNorm.getY( j ), objNorm.getZ( j ) );
42721
42722 v2.applyMatrix3( normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 );
42723
42724 position.setXYZ( idx, v1.x, v1.y, v1.z );
42725
42726 idx = idx + 1;
42727
42728 position.setXYZ( idx, v2.x, v2.y, v2.z );
42729
42730 idx = idx + 1;
42731
42732 }
42733
42734 }
42735
42736 position.needsUpdate = true;
42737
42738 };
42739
42740 }() );
42741
42742 /**
42743 * @author alteredq / http://alteredqualia.com/
42744 * @author mrdoob / http://mrdoob.com/
42745 * @author WestLangley / http://github.com/WestLangley
42746 */
42747
42748 function SpotLightHelper( light, color ) {
42749
42750 Object3D.call( this );
42751
42752 this.light = light;
42753 this.light.updateMatrixWorld();
42754
42755 this.matrix = light.matrixWorld;
42756 this.matrixAutoUpdate = false;
42757
42758 this.color = color;
42759
42760 var geometry = new BufferGeometry();
42761
42762 var positions = [
42763 0, 0, 0, 0, 0, 1,
42764 0, 0, 0, 1, 0, 1,
42765 0, 0, 0, - 1, 0, 1,
42766 0, 0, 0, 0, 1, 1,
42767 0, 0, 0, 0, - 1, 1
42768 ];
42769
42770 for ( var i = 0, j = 1, l = 32; i < l; i ++, j ++ ) {
42771
42772 var p1 = ( i / l ) * Math.PI * 2;
42773 var p2 = ( j / l ) * Math.PI * 2;
42774
42775 positions.push(
42776 Math.cos( p1 ), Math.sin( p1 ), 1,
42777 Math.cos( p2 ), Math.sin( p2 ), 1
42778 );
42779
42780 }
42781
42782 geometry.addAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
42783
42784 var material = new LineBasicMaterial( { fog: false } );
42785
42786 this.cone = new LineSegments( geometry, material );
42787 this.add( this.cone );
42788
42789 this.update();
42790
42791 }
42792
42793 SpotLightHelper.prototype = Object.create( Object3D.prototype );
42794 SpotLightHelper.prototype.constructor = SpotLightHelper;
42795
42796 SpotLightHelper.prototype.dispose = function () {
42797
42798 this.cone.geometry.dispose();
42799 this.cone.material.dispose();
42800
42801 };
42802
42803 SpotLightHelper.prototype.update = function () {
42804
42805 var vector = new Vector3();
42806 var vector2 = new Vector3();
42807
42808 return function update() {
42809
42810 this.light.updateMatrixWorld();
42811
42812 var coneLength = this.light.distance ? this.light.distance : 1000;
42813 var coneWidth = coneLength * Math.tan( this.light.angle );
42814
42815 this.cone.scale.set( coneWidth, coneWidth, coneLength );
42816
42817 vector.setFromMatrixPosition( this.light.matrixWorld );
42818 vector2.setFromMatrixPosition( this.light.target.matrixWorld );
42819
42820 this.cone.lookAt( vector2.sub( vector ) );
42821
42822 if ( this.color !== undefined ) {
42823
42824 this.cone.material.color.set( this.color );
42825
42826 } else {
42827
42828 this.cone.material.color.copy( this.light.color );
42829
42830 }
42831
42832 };
42833
42834 }();
42835
42836 /**
42837 * @author Sean Griffin / http://twitter.com/sgrif
42838 * @author Michael Guerrero / http://realitymeltdown.com
42839 * @author mrdoob / http://mrdoob.com/
42840 * @author ikerr / http://verold.com
42841 * @author Mugen87 / https://github.com/Mugen87
42842 */
42843
42844 function getBoneList( object ) {
42845
42846 var boneList = [];
42847
42848 if ( object && object.isBone ) {
42849
42850 boneList.push( object );
42851
42852 }
42853
42854 for ( var i = 0; i < object.children.length; i ++ ) {
42855
42856 boneList.push.apply( boneList, getBoneList( object.children[ i ] ) );
42857
42858 }
42859
42860 return boneList;
42861
42862 }
42863
42864 function SkeletonHelper( object ) {
42865
42866 var bones = getBoneList( object );
42867
42868 var geometry = new BufferGeometry();
42869
42870 var vertices = [];
42871 var colors = [];
42872
42873 var color1 = new Color( 0, 0, 1 );
42874 var color2 = new Color( 0, 1, 0 );
42875
42876 for ( var i = 0; i < bones.length; i ++ ) {
42877
42878 var bone = bones[ i ];
42879
42880 if ( bone.parent && bone.parent.isBone ) {
42881
42882 vertices.push( 0, 0, 0 );
42883 vertices.push( 0, 0, 0 );
42884 colors.push( color1.r, color1.g, color1.b );
42885 colors.push( color2.r, color2.g, color2.b );
42886
42887 }
42888
42889 }
42890
42891 geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
42892 geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
42893
42894 var material = new LineBasicMaterial( { vertexColors: VertexColors, depthTest: false, depthWrite: false, transparent: true } );
42895
42896 LineSegments.call( this, geometry, material );
42897
42898 this.root = object;
42899 this.bones = bones;
42900
42901 this.matrix = object.matrixWorld;
42902 this.matrixAutoUpdate = false;
42903
42904 }
42905
42906 SkeletonHelper.prototype = Object.create( LineSegments.prototype );
42907 SkeletonHelper.prototype.constructor = SkeletonHelper;
42908
42909 SkeletonHelper.prototype.updateMatrixWorld = function () {
42910
42911 var vector = new Vector3();
42912
42913 var boneMatrix = new Matrix4();
42914 var matrixWorldInv = new Matrix4();
42915
42916 return function updateMatrixWorld( force ) {
42917
42918 var bones = this.bones;
42919
42920 var geometry = this.geometry;
42921 var position = geometry.getAttribute( 'position' );
42922
42923 matrixWorldInv.getInverse( this.root.matrixWorld );
42924
42925 for ( var i = 0, j = 0; i < bones.length; i ++ ) {
42926
42927 var bone = bones[ i ];
42928
42929 if ( bone.parent && bone.parent.isBone ) {
42930
42931 boneMatrix.multiplyMatrices( matrixWorldInv, bone.matrixWorld );
42932 vector.setFromMatrixPosition( boneMatrix );
42933 position.setXYZ( j, vector.x, vector.y, vector.z );
42934
42935 boneMatrix.multiplyMatrices( matrixWorldInv, bone.parent.matrixWorld );
42936 vector.setFromMatrixPosition( boneMatrix );
42937 position.setXYZ( j + 1, vector.x, vector.y, vector.z );
42938
42939 j += 2;
42940
42941 }
42942
42943 }
42944
42945 geometry.getAttribute( 'position' ).needsUpdate = true;
42946
42947 Object3D.prototype.updateMatrixWorld.call( this, force );
42948
42949 };
42950
42951 }();
42952
42953 /**
42954 * @author alteredq / http://alteredqualia.com/
42955 * @author mrdoob / http://mrdoob.com/
42956 */
42957
42958 function PointLightHelper( light, sphereSize, color ) {
42959
42960 this.light = light;
42961 this.light.updateMatrixWorld();
42962
42963 this.color = color;
42964
42965 var geometry = new SphereBufferGeometry( sphereSize, 4, 2 );
42966 var material = new MeshBasicMaterial( { wireframe: true, fog: false } );
42967
42968 Mesh.call( this, geometry, material );
42969
42970 this.matrix = this.light.matrixWorld;
42971 this.matrixAutoUpdate = false;
42972
42973 this.update();
42974
42975
42976 /*
42977 var distanceGeometry = new THREE.IcosahedronGeometry( 1, 2 );
42978 var distanceMaterial = new THREE.MeshBasicMaterial( { color: hexColor, fog: false, wireframe: true, opacity: 0.1, transparent: true } );
42979
42980 this.lightSphere = new THREE.Mesh( bulbGeometry, bulbMaterial );
42981 this.lightDistance = new THREE.Mesh( distanceGeometry, distanceMaterial );
42982
42983 var d = light.distance;
42984
42985 if ( d === 0.0 ) {
42986
42987 this.lightDistance.visible = false;
42988
42989 } else {
42990
42991 this.lightDistance.scale.set( d, d, d );
42992
42993 }
42994
42995 this.add( this.lightDistance );
42996 */
42997
42998 }
42999
43000 PointLightHelper.prototype = Object.create( Mesh.prototype );
43001 PointLightHelper.prototype.constructor = PointLightHelper;
43002
43003 PointLightHelper.prototype.dispose = function () {
43004
43005 this.geometry.dispose();
43006 this.material.dispose();
43007
43008 };
43009
43010 PointLightHelper.prototype.update = function () {
43011
43012 if ( this.color !== undefined ) {
43013
43014 this.material.color.set( this.color );
43015
43016 } else {
43017
43018 this.material.color.copy( this.light.color );
43019
43020 }
43021
43022 /*
43023 var d = this.light.distance;
43024
43025 if ( d === 0.0 ) {
43026
43027 this.lightDistance.visible = false;
43028
43029 } else {
43030
43031 this.lightDistance.visible = true;
43032 this.lightDistance.scale.set( d, d, d );
43033
43034 }
43035 */
43036
43037 };
43038
43039 /**
43040 * @author abelnation / http://github.com/abelnation
43041 * @author Mugen87 / http://github.com/Mugen87
43042 * @author WestLangley / http://github.com/WestLangley
43043 */
43044
43045 function RectAreaLightHelper( light, color ) {
43046
43047 Object3D.call( this );
43048
43049 this.light = light;
43050 this.light.updateMatrixWorld();
43051
43052 this.matrix = light.matrixWorld;
43053 this.matrixAutoUpdate = false;
43054
43055 this.color = color;
43056
43057 var material = new LineBasicMaterial( { fog: false } );
43058
43059 var geometry = new BufferGeometry();
43060
43061 geometry.addAttribute( 'position', new BufferAttribute( new Float32Array( 5 * 3 ), 3 ) );
43062
43063 this.line = new Line( geometry, material );
43064 this.add( this.line );
43065
43066
43067 this.update();
43068
43069 }
43070
43071 RectAreaLightHelper.prototype = Object.create( Object3D.prototype );
43072 RectAreaLightHelper.prototype.constructor = RectAreaLightHelper;
43073
43074 RectAreaLightHelper.prototype.dispose = function () {
43075
43076 this.children[ 0 ].geometry.dispose();
43077 this.children[ 0 ].material.dispose();
43078
43079 };
43080
43081 RectAreaLightHelper.prototype.update = function () {
43082
43083 // calculate new dimensions of the helper
43084
43085 var hx = this.light.width * 0.5;
43086 var hy = this.light.height * 0.5;
43087
43088 var position = this.line.geometry.attributes.position;
43089 var array = position.array;
43090
43091 // update vertices
43092
43093 array[ 0 ] = hx; array[ 1 ] = - hy; array[ 2 ] = 0;
43094 array[ 3 ] = hx; array[ 4 ] = hy; array[ 5 ] = 0;
43095 array[ 6 ] = - hx; array[ 7 ] = hy; array[ 8 ] = 0;
43096 array[ 9 ] = - hx; array[ 10 ] = - hy; array[ 11 ] = 0;
43097 array[ 12 ] = hx; array[ 13 ] = - hy; array[ 14 ] = 0;
43098
43099 position.needsUpdate = true;
43100
43101 if ( this.color !== undefined ) {
43102
43103 this.line.material.color.set( this.color );
43104
43105 } else {
43106
43107 this.line.material.color.copy( this.light.color );
43108
43109 }
43110
43111 };
43112
43113 /**
43114 * @author alteredq / http://alteredqualia.com/
43115 * @author mrdoob / http://mrdoob.com/
43116 * @author Mugen87 / https://github.com/Mugen87
43117 */
43118
43119 function HemisphereLightHelper( light, size, color ) {
43120
43121 Object3D.call( this );
43122
43123 this.light = light;
43124 this.light.updateMatrixWorld();
43125
43126 this.matrix = light.matrixWorld;
43127 this.matrixAutoUpdate = false;
43128
43129 this.color = color;
43130
43131 var geometry = new OctahedronBufferGeometry( size );
43132 geometry.rotateY( Math.PI * 0.5 );
43133
43134 this.material = new MeshBasicMaterial( { wireframe: true, fog: false } );
43135 if ( this.color === undefined ) this.material.vertexColors = VertexColors;
43136
43137 var position = geometry.getAttribute( 'position' );
43138 var colors = new Float32Array( position.count * 3 );
43139
43140 geometry.addAttribute( 'color', new BufferAttribute( colors, 3 ) );
43141
43142 this.add( new Mesh( geometry, this.material ) );
43143
43144 this.update();
43145
43146 }
43147
43148 HemisphereLightHelper.prototype = Object.create( Object3D.prototype );
43149 HemisphereLightHelper.prototype.constructor = HemisphereLightHelper;
43150
43151 HemisphereLightHelper.prototype.dispose = function () {
43152
43153 this.children[ 0 ].geometry.dispose();
43154 this.children[ 0 ].material.dispose();
43155
43156 };
43157
43158 HemisphereLightHelper.prototype.update = function () {
43159
43160 var vector = new Vector3();
43161
43162 var color1 = new Color();
43163 var color2 = new Color();
43164
43165 return function update() {
43166
43167 var mesh = this.children[ 0 ];
43168
43169 if ( this.color !== undefined ) {
43170
43171 this.material.color.set( this.color );
43172
43173 } else {
43174
43175 var colors = mesh.geometry.getAttribute( 'color' );
43176
43177 color1.copy( this.light.color );
43178 color2.copy( this.light.groundColor );
43179
43180 for ( var i = 0, l = colors.count; i < l; i ++ ) {
43181
43182 var color = ( i < ( l / 2 ) ) ? color1 : color2;
43183
43184 colors.setXYZ( i, color.r, color.g, color.b );
43185
43186 }
43187
43188 colors.needsUpdate = true;
43189
43190 }
43191
43192 mesh.lookAt( vector.setFromMatrixPosition( this.light.matrixWorld ).negate() );
43193
43194 };
43195
43196 }();
43197
43198 /**
43199 * @author mrdoob / http://mrdoob.com/
43200 */
43201
43202 function GridHelper( size, divisions, color1, color2 ) {
43203
43204 size = size || 10;
43205 divisions = divisions || 10;
43206 color1 = new Color( color1 !== undefined ? color1 : 0x444444 );
43207 color2 = new Color( color2 !== undefined ? color2 : 0x888888 );
43208
43209 var center = divisions / 2;
43210 var step = size / divisions;
43211 var halfSize = size / 2;
43212
43213 var vertices = [], colors = [];
43214
43215 for ( var i = 0, j = 0, k = - halfSize; i <= divisions; i ++, k += step ) {
43216
43217 vertices.push( - halfSize, 0, k, halfSize, 0, k );
43218 vertices.push( k, 0, - halfSize, k, 0, halfSize );
43219
43220 var color = i === center ? color1 : color2;
43221
43222 color.toArray( colors, j ); j += 3;
43223 color.toArray( colors, j ); j += 3;
43224 color.toArray( colors, j ); j += 3;
43225 color.toArray( colors, j ); j += 3;
43226
43227 }
43228
43229 var geometry = new BufferGeometry();
43230 geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
43231 geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
43232
43233 var material = new LineBasicMaterial( { vertexColors: VertexColors } );
43234
43235 LineSegments.call( this, geometry, material );
43236
43237 }
43238
43239 GridHelper.prototype = Object.create( LineSegments.prototype );
43240 GridHelper.prototype.constructor = GridHelper;
43241
43242 /**
43243 * @author mrdoob / http://mrdoob.com/
43244 * @author Mugen87 / http://github.com/Mugen87
43245 * @author Hectate / http://www.github.com/Hectate
43246 */
43247
43248 function PolarGridHelper( radius, radials, circles, divisions, color1, color2 ) {
43249
43250 radius = radius || 10;
43251 radials = radials || 16;
43252 circles = circles || 8;
43253 divisions = divisions || 64;
43254 color1 = new Color( color1 !== undefined ? color1 : 0x444444 );
43255 color2 = new Color( color2 !== undefined ? color2 : 0x888888 );
43256
43257 var vertices = [];
43258 var colors = [];
43259
43260 var x, z;
43261 var v, i, j, r, color;
43262
43263 // create the radials
43264
43265 for ( i = 0; i <= radials; i ++ ) {
43266
43267 v = ( i / radials ) * ( Math.PI * 2 );
43268
43269 x = Math.sin( v ) * radius;
43270 z = Math.cos( v ) * radius;
43271
43272 vertices.push( 0, 0, 0 );
43273 vertices.push( x, 0, z );
43274
43275 color = ( i & 1 ) ? color1 : color2;
43276
43277 colors.push( color.r, color.g, color.b );
43278 colors.push( color.r, color.g, color.b );
43279
43280 }
43281
43282 // create the circles
43283
43284 for ( i = 0; i <= circles; i ++ ) {
43285
43286 color = ( i & 1 ) ? color1 : color2;
43287
43288 r = radius - ( radius / circles * i );
43289
43290 for ( j = 0; j < divisions; j ++ ) {
43291
43292 // first vertex
43293
43294 v = ( j / divisions ) * ( Math.PI * 2 );
43295
43296 x = Math.sin( v ) * r;
43297 z = Math.cos( v ) * r;
43298
43299 vertices.push( x, 0, z );
43300 colors.push( color.r, color.g, color.b );
43301
43302 // second vertex
43303
43304 v = ( ( j + 1 ) / divisions ) * ( Math.PI * 2 );
43305
43306 x = Math.sin( v ) * r;
43307 z = Math.cos( v ) * r;
43308
43309 vertices.push( x, 0, z );
43310 colors.push( color.r, color.g, color.b );
43311
43312 }
43313
43314 }
43315
43316 var geometry = new BufferGeometry();
43317 geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
43318 geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
43319
43320 var material = new LineBasicMaterial( { vertexColors: VertexColors } );
43321
43322 LineSegments.call( this, geometry, material );
43323
43324 }
43325
43326 PolarGridHelper.prototype = Object.create( LineSegments.prototype );
43327 PolarGridHelper.prototype.constructor = PolarGridHelper;
43328
43329 /**
43330 * @author mrdoob / http://mrdoob.com/
43331 * @author WestLangley / http://github.com/WestLangley
43332 */
43333
43334 function FaceNormalsHelper( object, size, hex, linewidth ) {
43335
43336 // FaceNormalsHelper only supports THREE.Geometry
43337
43338 this.object = object;
43339
43340 this.size = ( size !== undefined ) ? size : 1;
43341
43342 var color = ( hex !== undefined ) ? hex : 0xffff00;
43343
43344 var width = ( linewidth !== undefined ) ? linewidth : 1;
43345
43346 //
43347
43348 var nNormals = 0;
43349
43350 var objGeometry = this.object.geometry;
43351
43352 if ( objGeometry && objGeometry.isGeometry ) {
43353
43354 nNormals = objGeometry.faces.length;
43355
43356 } else {
43357
43358 console.warn( 'THREE.FaceNormalsHelper: only THREE.Geometry is supported. Use THREE.VertexNormalsHelper, instead.' );
43359
43360 }
43361
43362 //
43363
43364 var geometry = new BufferGeometry();
43365
43366 var positions = new Float32BufferAttribute( nNormals * 2 * 3, 3 );
43367
43368 geometry.addAttribute( 'position', positions );
43369
43370 LineSegments.call( this, geometry, new LineBasicMaterial( { color: color, linewidth: width } ) );
43371
43372 //
43373
43374 this.matrixAutoUpdate = false;
43375 this.update();
43376
43377 }
43378
43379 FaceNormalsHelper.prototype = Object.create( LineSegments.prototype );
43380 FaceNormalsHelper.prototype.constructor = FaceNormalsHelper;
43381
43382 FaceNormalsHelper.prototype.update = ( function () {
43383
43384 var v1 = new Vector3();
43385 var v2 = new Vector3();
43386 var normalMatrix = new Matrix3();
43387
43388 return function update() {
43389
43390 this.object.updateMatrixWorld( true );
43391
43392 normalMatrix.getNormalMatrix( this.object.matrixWorld );
43393
43394 var matrixWorld = this.object.matrixWorld;
43395
43396 var position = this.geometry.attributes.position;
43397
43398 //
43399
43400 var objGeometry = this.object.geometry;
43401
43402 var vertices = objGeometry.vertices;
43403
43404 var faces = objGeometry.faces;
43405
43406 var idx = 0;
43407
43408 for ( var i = 0, l = faces.length; i < l; i ++ ) {
43409
43410 var face = faces[ i ];
43411
43412 var normal = face.normal;
43413
43414 v1.copy( vertices[ face.a ] )
43415 .add( vertices[ face.b ] )
43416 .add( vertices[ face.c ] )
43417 .divideScalar( 3 )
43418 .applyMatrix4( matrixWorld );
43419
43420 v2.copy( normal ).applyMatrix3( normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 );
43421
43422 position.setXYZ( idx, v1.x, v1.y, v1.z );
43423
43424 idx = idx + 1;
43425
43426 position.setXYZ( idx, v2.x, v2.y, v2.z );
43427
43428 idx = idx + 1;
43429
43430 }
43431
43432 position.needsUpdate = true;
43433
43434 };
43435
43436 }() );
43437
43438 /**
43439 * @author alteredq / http://alteredqualia.com/
43440 * @author mrdoob / http://mrdoob.com/
43441 * @author WestLangley / http://github.com/WestLangley
43442 */
43443
43444 function DirectionalLightHelper( light, size, color ) {
43445
43446 Object3D.call( this );
43447
43448 this.light = light;
43449 this.light.updateMatrixWorld();
43450
43451 this.matrix = light.matrixWorld;
43452 this.matrixAutoUpdate = false;
43453
43454 this.color = color;
43455
43456 if ( size === undefined ) size = 1;
43457
43458 var geometry = new BufferGeometry();
43459 geometry.addAttribute( 'position', new Float32BufferAttribute( [
43460 - size, size, 0,
43461 size, size, 0,
43462 size, - size, 0,
43463 - size, - size, 0,
43464 - size, size, 0
43465 ], 3 ) );
43466
43467 var material = new LineBasicMaterial( { fog: false } );
43468
43469 this.lightPlane = new Line( geometry, material );
43470 this.add( this.lightPlane );
43471
43472 geometry = new BufferGeometry();
43473 geometry.addAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 0, 1 ], 3 ) );
43474
43475 this.targetLine = new Line( geometry, material );
43476 this.add( this.targetLine );
43477
43478 this.update();
43479
43480 }
43481
43482 DirectionalLightHelper.prototype = Object.create( Object3D.prototype );
43483 DirectionalLightHelper.prototype.constructor = DirectionalLightHelper;
43484
43485 DirectionalLightHelper.prototype.dispose = function () {
43486
43487 this.lightPlane.geometry.dispose();
43488 this.lightPlane.material.dispose();
43489 this.targetLine.geometry.dispose();
43490 this.targetLine.material.dispose();
43491
43492 };
43493
43494 DirectionalLightHelper.prototype.update = function () {
43495
43496 var v1 = new Vector3();
43497 var v2 = new Vector3();
43498 var v3 = new Vector3();
43499
43500 return function update() {
43501
43502 v1.setFromMatrixPosition( this.light.matrixWorld );
43503 v2.setFromMatrixPosition( this.light.target.matrixWorld );
43504 v3.subVectors( v2, v1 );
43505
43506 this.lightPlane.lookAt( v3 );
43507
43508 if ( this.color !== undefined ) {
43509
43510 this.lightPlane.material.color.set( this.color );
43511 this.targetLine.material.color.set( this.color );
43512
43513 } else {
43514
43515 this.lightPlane.material.color.copy( this.light.color );
43516 this.targetLine.material.color.copy( this.light.color );
43517
43518 }
43519
43520 this.targetLine.lookAt( v3 );
43521 this.targetLine.scale.z = v3.length();
43522
43523 };
43524
43525 }();
43526
43527 /**
43528 * @author alteredq / http://alteredqualia.com/
43529 * @author Mugen87 / https://github.com/Mugen87
43530 *
43531 * - shows frustum, line of sight and up of the camera
43532 * - suitable for fast updates
43533 * - based on frustum visualization in lightgl.js shadowmap example
43534 * http://evanw.github.com/lightgl.js/tests/shadowmap.html
43535 */
43536
43537 function CameraHelper( camera ) {
43538
43539 var geometry = new BufferGeometry();
43540 var material = new LineBasicMaterial( { color: 0xffffff, vertexColors: FaceColors } );
43541
43542 var vertices = [];
43543 var colors = [];
43544
43545 var pointMap = {};
43546
43547 // colors
43548
43549 var colorFrustum = new Color( 0xffaa00 );
43550 var colorCone = new Color( 0xff0000 );
43551 var colorUp = new Color( 0x00aaff );
43552 var colorTarget = new Color( 0xffffff );
43553 var colorCross = new Color( 0x333333 );
43554
43555 // near
43556
43557 addLine( 'n1', 'n2', colorFrustum );
43558 addLine( 'n2', 'n4', colorFrustum );
43559 addLine( 'n4', 'n3', colorFrustum );
43560 addLine( 'n3', 'n1', colorFrustum );
43561
43562 // far
43563
43564 addLine( 'f1', 'f2', colorFrustum );
43565 addLine( 'f2', 'f4', colorFrustum );
43566 addLine( 'f4', 'f3', colorFrustum );
43567 addLine( 'f3', 'f1', colorFrustum );
43568
43569 // sides
43570
43571 addLine( 'n1', 'f1', colorFrustum );
43572 addLine( 'n2', 'f2', colorFrustum );
43573 addLine( 'n3', 'f3', colorFrustum );
43574 addLine( 'n4', 'f4', colorFrustum );
43575
43576 // cone
43577
43578 addLine( 'p', 'n1', colorCone );
43579 addLine( 'p', 'n2', colorCone );
43580 addLine( 'p', 'n3', colorCone );
43581 addLine( 'p', 'n4', colorCone );
43582
43583 // up
43584
43585 addLine( 'u1', 'u2', colorUp );
43586 addLine( 'u2', 'u3', colorUp );
43587 addLine( 'u3', 'u1', colorUp );
43588
43589 // target
43590
43591 addLine( 'c', 't', colorTarget );
43592 addLine( 'p', 'c', colorCross );
43593
43594 // cross
43595
43596 addLine( 'cn1', 'cn2', colorCross );
43597 addLine( 'cn3', 'cn4', colorCross );
43598
43599 addLine( 'cf1', 'cf2', colorCross );
43600 addLine( 'cf3', 'cf4', colorCross );
43601
43602 function addLine( a, b, color ) {
43603
43604 addPoint( a, color );
43605 addPoint( b, color );
43606
43607 }
43608
43609 function addPoint( id, color ) {
43610
43611 vertices.push( 0, 0, 0 );
43612 colors.push( color.r, color.g, color.b );
43613
43614 if ( pointMap[ id ] === undefined ) {
43615
43616 pointMap[ id ] = [];
43617
43618 }
43619
43620 pointMap[ id ].push( ( vertices.length / 3 ) - 1 );
43621
43622 }
43623
43624 geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
43625 geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
43626
43627 LineSegments.call( this, geometry, material );
43628
43629 this.camera = camera;
43630 if ( this.camera.updateProjectionMatrix ) this.camera.updateProjectionMatrix();
43631
43632 this.matrix = camera.matrixWorld;
43633 this.matrixAutoUpdate = false;
43634
43635 this.pointMap = pointMap;
43636
43637 this.update();
43638
43639 }
43640
43641 CameraHelper.prototype = Object.create( LineSegments.prototype );
43642 CameraHelper.prototype.constructor = CameraHelper;
43643
43644 CameraHelper.prototype.update = function () {
43645
43646 var geometry, pointMap;
43647
43648 var vector = new Vector3();
43649 var camera = new Camera();
43650
43651 function setPoint( point, x, y, z ) {
43652
43653 vector.set( x, y, z ).unproject( camera );
43654
43655 var points = pointMap[ point ];
43656
43657 if ( points !== undefined ) {
43658
43659 var position = geometry.getAttribute( 'position' );
43660
43661 for ( var i = 0, l = points.length; i < l; i ++ ) {
43662
43663 position.setXYZ( points[ i ], vector.x, vector.y, vector.z );
43664
43665 }
43666
43667 }
43668
43669 }
43670
43671 return function update() {
43672
43673 geometry = this.geometry;
43674 pointMap = this.pointMap;
43675
43676 var w = 1, h = 1;
43677
43678 // we need just camera projection matrix
43679 // world matrix must be identity
43680
43681 camera.projectionMatrix.copy( this.camera.projectionMatrix );
43682
43683 // center / target
43684
43685 setPoint( 'c', 0, 0, - 1 );
43686 setPoint( 't', 0, 0, 1 );
43687
43688 // near
43689
43690 setPoint( 'n1', - w, - h, - 1 );
43691 setPoint( 'n2', w, - h, - 1 );
43692 setPoint( 'n3', - w, h, - 1 );
43693 setPoint( 'n4', w, h, - 1 );
43694
43695 // far
43696
43697 setPoint( 'f1', - w, - h, 1 );
43698 setPoint( 'f2', w, - h, 1 );
43699 setPoint( 'f3', - w, h, 1 );
43700 setPoint( 'f4', w, h, 1 );
43701
43702 // up
43703
43704 setPoint( 'u1', w * 0.7, h * 1.1, - 1 );
43705 setPoint( 'u2', - w * 0.7, h * 1.1, - 1 );
43706 setPoint( 'u3', 0, h * 2, - 1 );
43707
43708 // cross
43709
43710 setPoint( 'cf1', - w, 0, 1 );
43711 setPoint( 'cf2', w, 0, 1 );
43712 setPoint( 'cf3', 0, - h, 1 );
43713 setPoint( 'cf4', 0, h, 1 );
43714
43715 setPoint( 'cn1', - w, 0, - 1 );
43716 setPoint( 'cn2', w, 0, - 1 );
43717 setPoint( 'cn3', 0, - h, - 1 );
43718 setPoint( 'cn4', 0, h, - 1 );
43719
43720 geometry.getAttribute( 'position' ).needsUpdate = true;
43721
43722 };
43723
43724 }();
43725
43726 /**
43727 * @author mrdoob / http://mrdoob.com/
43728 * @author Mugen87 / http://github.com/Mugen87
43729 */
43730
43731 function BoxHelper( object, color ) {
43732
43733 this.object = object;
43734
43735 if ( color === undefined ) color = 0xffff00;
43736
43737 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 ] );
43738 var positions = new Float32Array( 8 * 3 );
43739
43740 var geometry = new BufferGeometry();
43741 geometry.setIndex( new BufferAttribute( indices, 1 ) );
43742 geometry.addAttribute( 'position', new BufferAttribute( positions, 3 ) );
43743
43744 LineSegments.call( this, geometry, new LineBasicMaterial( { color: color } ) );
43745
43746 this.matrixAutoUpdate = false;
43747
43748 this.update();
43749
43750 }
43751
43752 BoxHelper.prototype = Object.create( LineSegments.prototype );
43753 BoxHelper.prototype.constructor = BoxHelper;
43754
43755 BoxHelper.prototype.update = ( function () {
43756
43757 var box = new Box3();
43758
43759 return function update( object ) {
43760
43761 if ( object !== undefined ) {
43762
43763 console.warn( 'THREE.BoxHelper: .update() has no longer arguments.' );
43764
43765 }
43766
43767 if ( this.object !== undefined ) {
43768
43769 box.setFromObject( this.object );
43770
43771 }
43772
43773 if ( box.isEmpty() ) return;
43774
43775 var min = box.min;
43776 var max = box.max;
43777
43778 /*
43779 5____4
43780 1/___0/|
43781 | 6__|_7
43782 2/___3/
43783
43784 0: max.x, max.y, max.z
43785 1: min.x, max.y, max.z
43786 2: min.x, min.y, max.z
43787 3: max.x, min.y, max.z
43788 4: max.x, max.y, min.z
43789 5: min.x, max.y, min.z
43790 6: min.x, min.y, min.z
43791 7: max.x, min.y, min.z
43792 */
43793
43794 var position = this.geometry.attributes.position;
43795 var array = position.array;
43796
43797 array[ 0 ] = max.x; array[ 1 ] = max.y; array[ 2 ] = max.z;
43798 array[ 3 ] = min.x; array[ 4 ] = max.y; array[ 5 ] = max.z;
43799 array[ 6 ] = min.x; array[ 7 ] = min.y; array[ 8 ] = max.z;
43800 array[ 9 ] = max.x; array[ 10 ] = min.y; array[ 11 ] = max.z;
43801 array[ 12 ] = max.x; array[ 13 ] = max.y; array[ 14 ] = min.z;
43802 array[ 15 ] = min.x; array[ 16 ] = max.y; array[ 17 ] = min.z;
43803 array[ 18 ] = min.x; array[ 19 ] = min.y; array[ 20 ] = min.z;
43804 array[ 21 ] = max.x; array[ 22 ] = min.y; array[ 23 ] = min.z;
43805
43806 position.needsUpdate = true;
43807
43808 this.geometry.computeBoundingSphere();
43809
43810 };
43811
43812 } )();
43813
43814 BoxHelper.prototype.setFromObject = function ( object ) {
43815
43816 this.object = object;
43817 this.update();
43818
43819 return this;
43820
43821 };
43822
43823 /**
43824 * @author WestLangley / http://github.com/WestLangley
43825 */
43826
43827 function Box3Helper( box, hex ) {
43828
43829 this.type = 'Box3Helper';
43830
43831 this.box = box;
43832
43833 var color = ( hex !== undefined ) ? hex : 0xffff00;
43834
43835 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 ] );
43836
43837 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 ];
43838
43839 var geometry = new BufferGeometry();
43840
43841 geometry.setIndex( new BufferAttribute( indices, 1 ) );
43842
43843 geometry.addAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
43844
43845 LineSegments.call( this, geometry, new LineBasicMaterial( { color: color } ) );
43846
43847 this.geometry.computeBoundingSphere();
43848
43849 }
43850
43851 Box3Helper.prototype = Object.create( LineSegments.prototype );
43852 Box3Helper.prototype.constructor = Box3Helper;
43853
43854 Box3Helper.prototype.updateMatrixWorld = function ( force ) {
43855
43856 var box = this.box;
43857
43858 if ( box.isEmpty() ) return;
43859
43860 box.getCenter( this.position );
43861
43862 box.getSize( this.scale );
43863
43864 this.scale.multiplyScalar( 0.5 );
43865
43866 Object3D.prototype.updateMatrixWorld.call( this, force );
43867
43868 };
43869
43870 /**
43871 * @author WestLangley / http://github.com/WestLangley
43872 */
43873
43874 function PlaneHelper( plane, size, hex ) {
43875
43876 this.type = 'PlaneHelper';
43877
43878 this.plane = plane;
43879
43880 this.size = ( size === undefined ) ? 1 : size;
43881
43882 var color = ( hex !== undefined ) ? hex : 0xffff00;
43883
43884 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 ];
43885
43886 var geometry = new BufferGeometry();
43887 geometry.addAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
43888 geometry.computeBoundingSphere();
43889
43890 Line.call( this, geometry, new LineBasicMaterial( { color: color } ) );
43891
43892 //
43893
43894 var positions2 = [ 1, 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, 1, 1, - 1, - 1, 1, 1, - 1, 1 ];
43895
43896 var geometry2 = new BufferGeometry();
43897 geometry2.addAttribute( 'position', new Float32BufferAttribute( positions2, 3 ) );
43898 geometry2.computeBoundingSphere();
43899
43900 this.add( new Mesh( geometry2, new MeshBasicMaterial( { color: color, opacity: 0.2, transparent: true, depthWrite: false } ) ) );
43901
43902 }
43903
43904 PlaneHelper.prototype = Object.create( Line.prototype );
43905 PlaneHelper.prototype.constructor = PlaneHelper;
43906
43907 PlaneHelper.prototype.updateMatrixWorld = function ( force ) {
43908
43909 var scale = - this.plane.constant;
43910
43911 if ( Math.abs( scale ) < 1e-8 ) scale = 1e-8; // sign does not matter
43912
43913 this.scale.set( 0.5 * this.size, 0.5 * this.size, scale );
43914
43915 this.lookAt( this.plane.normal );
43916
43917 Object3D.prototype.updateMatrixWorld.call( this, force );
43918
43919 };
43920
43921 /**
43922 * @author WestLangley / http://github.com/WestLangley
43923 * @author zz85 / http://github.com/zz85
43924 * @author bhouston / http://clara.io
43925 *
43926 * Creates an arrow for visualizing directions
43927 *
43928 * Parameters:
43929 * dir - Vector3
43930 * origin - Vector3
43931 * length - Number
43932 * color - color in hex value
43933 * headLength - Number
43934 * headWidth - Number
43935 */
43936
43937 var lineGeometry;
43938 var coneGeometry;
43939
43940 function ArrowHelper( dir, origin, length, color, headLength, headWidth ) {
43941
43942 // dir is assumed to be normalized
43943
43944 Object3D.call( this );
43945
43946 if ( color === undefined ) color = 0xffff00;
43947 if ( length === undefined ) length = 1;
43948 if ( headLength === undefined ) headLength = 0.2 * length;
43949 if ( headWidth === undefined ) headWidth = 0.2 * headLength;
43950
43951 if ( lineGeometry === undefined ) {
43952
43953 lineGeometry = new BufferGeometry();
43954 lineGeometry.addAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 1, 0 ], 3 ) );
43955
43956 coneGeometry = new CylinderBufferGeometry( 0, 0.5, 1, 5, 1 );
43957 coneGeometry.translate( 0, - 0.5, 0 );
43958
43959 }
43960
43961 this.position.copy( origin );
43962
43963 this.line = new Line( lineGeometry, new LineBasicMaterial( { color: color } ) );
43964 this.line.matrixAutoUpdate = false;
43965 this.add( this.line );
43966
43967 this.cone = new Mesh( coneGeometry, new MeshBasicMaterial( { color: color } ) );
43968 this.cone.matrixAutoUpdate = false;
43969 this.add( this.cone );
43970
43971 this.setDirection( dir );
43972 this.setLength( length, headLength, headWidth );
43973
43974 }
43975
43976 ArrowHelper.prototype = Object.create( Object3D.prototype );
43977 ArrowHelper.prototype.constructor = ArrowHelper;
43978
43979 ArrowHelper.prototype.setDirection = ( function () {
43980
43981 var axis = new Vector3();
43982 var radians;
43983
43984 return function setDirection( dir ) {
43985
43986 // dir is assumed to be normalized
43987
43988 if ( dir.y > 0.99999 ) {
43989
43990 this.quaternion.set( 0, 0, 0, 1 );
43991
43992 } else if ( dir.y < - 0.99999 ) {
43993
43994 this.quaternion.set( 1, 0, 0, 0 );
43995
43996 } else {
43997
43998 axis.set( dir.z, 0, - dir.x ).normalize();
43999
44000 radians = Math.acos( dir.y );
44001
44002 this.quaternion.setFromAxisAngle( axis, radians );
44003
44004 }
44005
44006 };
44007
44008 }() );
44009
44010 ArrowHelper.prototype.setLength = function ( length, headLength, headWidth ) {
44011
44012 if ( headLength === undefined ) headLength = 0.2 * length;
44013 if ( headWidth === undefined ) headWidth = 0.2 * headLength;
44014
44015 this.line.scale.set( 1, Math.max( 0, length - headLength ), 1 );
44016 this.line.updateMatrix();
44017
44018 this.cone.scale.set( headWidth, headLength, headWidth );
44019 this.cone.position.y = length;
44020 this.cone.updateMatrix();
44021
44022 };
44023
44024 ArrowHelper.prototype.setColor = function ( color ) {
44025
44026 this.line.material.color.copy( color );
44027 this.cone.material.color.copy( color );
44028
44029 };
44030
44031 /**
44032 * @author sroucheray / http://sroucheray.org/
44033 * @author mrdoob / http://mrdoob.com/
44034 */
44035
44036 function AxesHelper( size ) {
44037
44038 size = size || 1;
44039
44040 var vertices = [
44041 0, 0, 0, size, 0, 0,
44042 0, 0, 0, 0, size, 0,
44043 0, 0, 0, 0, 0, size
44044 ];
44045
44046 var colors = [
44047 1, 0, 0, 1, 0.6, 0,
44048 0, 1, 0, 0.6, 1, 0,
44049 0, 0, 1, 0, 0.6, 1
44050 ];
44051
44052 var geometry = new BufferGeometry();
44053 geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
44054 geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
44055
44056 var material = new LineBasicMaterial( { vertexColors: VertexColors } );
44057
44058 LineSegments.call( this, geometry, material );
44059
44060 }
44061
44062 AxesHelper.prototype = Object.create( LineSegments.prototype );
44063 AxesHelper.prototype.constructor = AxesHelper;
44064
44065 /**
44066 * @author mrdoob / http://mrdoob.com/
44067 */
44068
44069 function Face4( a, b, c, d, normal, color, materialIndex ) {
44070
44071 console.warn( 'THREE.Face4 has been removed. A THREE.Face3 will be created instead.' );
44072 return new Face3( a, b, c, normal, color, materialIndex );
44073
44074 }
44075
44076 var LineStrip = 0;
44077
44078 var LinePieces = 1;
44079
44080 function MeshFaceMaterial( materials ) {
44081
44082 console.warn( 'THREE.MeshFaceMaterial has been removed. Use an Array instead.' );
44083 return materials;
44084
44085 }
44086
44087 function MultiMaterial( materials ) {
44088
44089 if ( materials === undefined ) materials = [];
44090
44091 console.warn( 'THREE.MultiMaterial has been removed. Use an Array instead.' );
44092 materials.isMultiMaterial = true;
44093 materials.materials = materials;
44094 materials.clone = function () {
44095
44096 return materials.slice();
44097
44098 };
44099 return materials;
44100
44101 }
44102
44103 function PointCloud( geometry, material ) {
44104
44105 console.warn( 'THREE.PointCloud has been renamed to THREE.Points.' );
44106 return new Points( geometry, material );
44107
44108 }
44109
44110 function Particle( material ) {
44111
44112 console.warn( 'THREE.Particle has been renamed to THREE.Sprite.' );
44113 return new Sprite( material );
44114
44115 }
44116
44117 function ParticleSystem( geometry, material ) {
44118
44119 console.warn( 'THREE.ParticleSystem has been renamed to THREE.Points.' );
44120 return new Points( geometry, material );
44121
44122 }
44123
44124 function PointCloudMaterial( parameters ) {
44125
44126 console.warn( 'THREE.PointCloudMaterial has been renamed to THREE.PointsMaterial.' );
44127 return new PointsMaterial( parameters );
44128
44129 }
44130
44131 function ParticleBasicMaterial( parameters ) {
44132
44133 console.warn( 'THREE.ParticleBasicMaterial has been renamed to THREE.PointsMaterial.' );
44134 return new PointsMaterial( parameters );
44135
44136 }
44137
44138 function ParticleSystemMaterial( parameters ) {
44139
44140 console.warn( 'THREE.ParticleSystemMaterial has been renamed to THREE.PointsMaterial.' );
44141 return new PointsMaterial( parameters );
44142
44143 }
44144
44145 function Vertex( x, y, z ) {
44146
44147 console.warn( 'THREE.Vertex has been removed. Use THREE.Vector3 instead.' );
44148 return new Vector3( x, y, z );
44149
44150 }
44151
44152 //
44153
44154 function DynamicBufferAttribute( array, itemSize ) {
44155
44156 console.warn( 'THREE.DynamicBufferAttribute has been removed. Use new THREE.BufferAttribute().setDynamic( true ) instead.' );
44157 return new BufferAttribute( array, itemSize ).setDynamic( true );
44158
44159 }
44160
44161 function Int8Attribute( array, itemSize ) {
44162
44163 console.warn( 'THREE.Int8Attribute has been removed. Use new THREE.Int8BufferAttribute() instead.' );
44164 return new Int8BufferAttribute( array, itemSize );
44165
44166 }
44167
44168 function Uint8Attribute( array, itemSize ) {
44169
44170 console.warn( 'THREE.Uint8Attribute has been removed. Use new THREE.Uint8BufferAttribute() instead.' );
44171 return new Uint8BufferAttribute( array, itemSize );
44172
44173 }
44174
44175 function Uint8ClampedAttribute( array, itemSize ) {
44176
44177 console.warn( 'THREE.Uint8ClampedAttribute has been removed. Use new THREE.Uint8ClampedBufferAttribute() instead.' );
44178 return new Uint8ClampedBufferAttribute( array, itemSize );
44179
44180 }
44181
44182 function Int16Attribute( array, itemSize ) {
44183
44184 console.warn( 'THREE.Int16Attribute has been removed. Use new THREE.Int16BufferAttribute() instead.' );
44185 return new Int16BufferAttribute( array, itemSize );
44186
44187 }
44188
44189 function Uint16Attribute( array, itemSize ) {
44190
44191 console.warn( 'THREE.Uint16Attribute has been removed. Use new THREE.Uint16BufferAttribute() instead.' );
44192 return new Uint16BufferAttribute( array, itemSize );
44193
44194 }
44195
44196 function Int32Attribute( array, itemSize ) {
44197
44198 console.warn( 'THREE.Int32Attribute has been removed. Use new THREE.Int32BufferAttribute() instead.' );
44199 return new Int32BufferAttribute( array, itemSize );
44200
44201 }
44202
44203 function Uint32Attribute( array, itemSize ) {
44204
44205 console.warn( 'THREE.Uint32Attribute has been removed. Use new THREE.Uint32BufferAttribute() instead.' );
44206 return new Uint32BufferAttribute( array, itemSize );
44207
44208 }
44209
44210 function Float32Attribute( array, itemSize ) {
44211
44212 console.warn( 'THREE.Float32Attribute has been removed. Use new THREE.Float32BufferAttribute() instead.' );
44213 return new Float32BufferAttribute( array, itemSize );
44214
44215 }
44216
44217 function Float64Attribute( array, itemSize ) {
44218
44219 console.warn( 'THREE.Float64Attribute has been removed. Use new THREE.Float64BufferAttribute() instead.' );
44220 return new Float64BufferAttribute( array, itemSize );
44221
44222 }
44223
44224 //
44225
44226 Curve.create = function ( construct, getPoint ) {
44227
44228 console.log( 'THREE.Curve.create() has been deprecated' );
44229
44230 construct.prototype = Object.create( Curve.prototype );
44231 construct.prototype.constructor = construct;
44232 construct.prototype.getPoint = getPoint;
44233
44234 return construct;
44235
44236 };
44237
44238 //
44239
44240 Object.assign( CurvePath.prototype, {
44241
44242 createPointsGeometry: function ( divisions ) {
44243
44244 console.warn( 'THREE.CurvePath: .createPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' );
44245
44246 // generate geometry from path points (for Line or Points objects)
44247
44248 var pts = this.getPoints( divisions );
44249 return this.createGeometry( pts );
44250
44251 },
44252
44253 createSpacedPointsGeometry: function ( divisions ) {
44254
44255 console.warn( 'THREE.CurvePath: .createSpacedPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' );
44256
44257 // generate geometry from equidistant sampling along the path
44258
44259 var pts = this.getSpacedPoints( divisions );
44260 return this.createGeometry( pts );
44261
44262 },
44263
44264 createGeometry: function ( points ) {
44265
44266 console.warn( 'THREE.CurvePath: .createGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' );
44267
44268 var geometry = new Geometry();
44269
44270 for ( var i = 0, l = points.length; i < l; i ++ ) {
44271
44272 var point = points[ i ];
44273 geometry.vertices.push( new Vector3( point.x, point.y, point.z || 0 ) );
44274
44275 }
44276
44277 return geometry;
44278
44279 }
44280
44281 } );
44282
44283 //
44284
44285 Object.assign( Path.prototype, {
44286
44287 fromPoints: function ( points ) {
44288
44289 console.warn( 'THREE.Path: .fromPoints() has been renamed to .setFromPoints().' );
44290 this.setFromPoints( points );
44291
44292 }
44293
44294 } );
44295
44296 //
44297
44298 function ClosedSplineCurve3( points ) {
44299
44300 console.warn( 'THREE.ClosedSplineCurve3 has been deprecated. Use THREE.CatmullRomCurve3 instead.' );
44301
44302 CatmullRomCurve3.call( this, points );
44303 this.type = 'catmullrom';
44304 this.closed = true;
44305
44306 }
44307
44308 ClosedSplineCurve3.prototype = Object.create( CatmullRomCurve3.prototype );
44309
44310 //
44311
44312 function SplineCurve3( points ) {
44313
44314 console.warn( 'THREE.SplineCurve3 has been deprecated. Use THREE.CatmullRomCurve3 instead.' );
44315
44316 CatmullRomCurve3.call( this, points );
44317 this.type = 'catmullrom';
44318
44319 }
44320
44321 SplineCurve3.prototype = Object.create( CatmullRomCurve3.prototype );
44322
44323 //
44324
44325 function Spline( points ) {
44326
44327 console.warn( 'THREE.Spline has been removed. Use THREE.CatmullRomCurve3 instead.' );
44328
44329 CatmullRomCurve3.call( this, points );
44330 this.type = 'catmullrom';
44331
44332 }
44333
44334 Spline.prototype = Object.create( CatmullRomCurve3.prototype );
44335
44336 Object.assign( Spline.prototype, {
44337
44338 initFromArray: function ( /* a */ ) {
44339
44340 console.error( 'THREE.Spline: .initFromArray() has been removed.' );
44341
44342 },
44343 getControlPointsArray: function ( /* optionalTarget */ ) {
44344
44345 console.error( 'THREE.Spline: .getControlPointsArray() has been removed.' );
44346
44347 },
44348 reparametrizeByArcLength: function ( /* samplingCoef */ ) {
44349
44350 console.error( 'THREE.Spline: .reparametrizeByArcLength() has been removed.' );
44351
44352 }
44353
44354 } );
44355
44356 //
44357
44358 function AxisHelper( size ) {
44359
44360 console.warn( 'THREE.AxisHelper has been renamed to THREE.AxesHelper.' );
44361 return new AxesHelper( size );
44362
44363 }
44364
44365 function BoundingBoxHelper( object, color ) {
44366
44367 console.warn( 'THREE.BoundingBoxHelper has been deprecated. Creating a THREE.BoxHelper instead.' );
44368 return new BoxHelper( object, color );
44369
44370 }
44371
44372 function EdgesHelper( object, hex ) {
44373
44374 console.warn( 'THREE.EdgesHelper has been removed. Use THREE.EdgesGeometry instead.' );
44375 return new LineSegments( new EdgesGeometry( object.geometry ), new LineBasicMaterial( { color: hex !== undefined ? hex : 0xffffff } ) );
44376
44377 }
44378
44379 GridHelper.prototype.setColors = function () {
44380
44381 console.error( 'THREE.GridHelper: setColors() has been deprecated, pass them in the constructor instead.' );
44382
44383 };
44384
44385 SkeletonHelper.prototype.update = function () {
44386
44387 console.error( 'THREE.SkeletonHelper: update() no longer needs to be called.' );
44388
44389 };
44390
44391 function WireframeHelper( object, hex ) {
44392
44393 console.warn( 'THREE.WireframeHelper has been removed. Use THREE.WireframeGeometry instead.' );
44394 return new LineSegments( new WireframeGeometry( object.geometry ), new LineBasicMaterial( { color: hex !== undefined ? hex : 0xffffff } ) );
44395
44396 }
44397
44398 //
44399
44400 Object.assign( Loader.prototype, {
44401
44402 extractUrlBase: function ( url ) {
44403
44404 console.warn( 'THREE.Loader: .extractUrlBase() has been deprecated. Use THREE.LoaderUtils.extractUrlBase() instead.' );
44405 return LoaderUtils.extractUrlBase( url );
44406
44407 }
44408
44409 } );
44410
44411 function XHRLoader( manager ) {
44412
44413 console.warn( 'THREE.XHRLoader has been renamed to THREE.FileLoader.' );
44414 return new FileLoader( manager );
44415
44416 }
44417
44418 function BinaryTextureLoader( manager ) {
44419
44420 console.warn( 'THREE.BinaryTextureLoader has been renamed to THREE.DataTextureLoader.' );
44421 return new DataTextureLoader( manager );
44422
44423 }
44424
44425 //
44426
44427 Object.assign( Box2.prototype, {
44428
44429 center: function ( optionalTarget ) {
44430
44431 console.warn( 'THREE.Box2: .center() has been renamed to .getCenter().' );
44432 return this.getCenter( optionalTarget );
44433
44434 },
44435 empty: function () {
44436
44437 console.warn( 'THREE.Box2: .empty() has been renamed to .isEmpty().' );
44438 return this.isEmpty();
44439
44440 },
44441 isIntersectionBox: function ( box ) {
44442
44443 console.warn( 'THREE.Box2: .isIntersectionBox() has been renamed to .intersectsBox().' );
44444 return this.intersectsBox( box );
44445
44446 },
44447 size: function ( optionalTarget ) {
44448
44449 console.warn( 'THREE.Box2: .size() has been renamed to .getSize().' );
44450 return this.getSize( optionalTarget );
44451
44452 }
44453 } );
44454
44455 Object.assign( Box3.prototype, {
44456
44457 center: function ( optionalTarget ) {
44458
44459 console.warn( 'THREE.Box3: .center() has been renamed to .getCenter().' );
44460 return this.getCenter( optionalTarget );
44461
44462 },
44463 empty: function () {
44464
44465 console.warn( 'THREE.Box3: .empty() has been renamed to .isEmpty().' );
44466 return this.isEmpty();
44467
44468 },
44469 isIntersectionBox: function ( box ) {
44470
44471 console.warn( 'THREE.Box3: .isIntersectionBox() has been renamed to .intersectsBox().' );
44472 return this.intersectsBox( box );
44473
44474 },
44475 isIntersectionSphere: function ( sphere ) {
44476
44477 console.warn( 'THREE.Box3: .isIntersectionSphere() has been renamed to .intersectsSphere().' );
44478 return this.intersectsSphere( sphere );
44479
44480 },
44481 size: function ( optionalTarget ) {
44482
44483 console.warn( 'THREE.Box3: .size() has been renamed to .getSize().' );
44484 return this.getSize( optionalTarget );
44485
44486 }
44487 } );
44488
44489 Line3.prototype.center = function ( optionalTarget ) {
44490
44491 console.warn( 'THREE.Line3: .center() has been renamed to .getCenter().' );
44492 return this.getCenter( optionalTarget );
44493
44494 };
44495
44496 Object.assign( _Math, {
44497
44498 random16: function () {
44499
44500 console.warn( 'THREE.Math: .random16() has been deprecated. Use Math.random() instead.' );
44501 return Math.random();
44502
44503 },
44504
44505 nearestPowerOfTwo: function ( value ) {
44506
44507 console.warn( 'THREE.Math: .nearestPowerOfTwo() has been renamed to .floorPowerOfTwo().' );
44508 return _Math.floorPowerOfTwo( value );
44509
44510 },
44511
44512 nextPowerOfTwo: function ( value ) {
44513
44514 console.warn( 'THREE.Math: .nextPowerOfTwo() has been renamed to .ceilPowerOfTwo().' );
44515 return _Math.ceilPowerOfTwo( value );
44516
44517 }
44518
44519 } );
44520
44521 Object.assign( Matrix3.prototype, {
44522
44523 flattenToArrayOffset: function ( array, offset ) {
44524
44525 console.warn( "THREE.Matrix3: .flattenToArrayOffset() has been deprecated. Use .toArray() instead." );
44526 return this.toArray( array, offset );
44527
44528 },
44529 multiplyVector3: function ( vector ) {
44530
44531 console.warn( 'THREE.Matrix3: .multiplyVector3() has been removed. Use vector.applyMatrix3( matrix ) instead.' );
44532 return vector.applyMatrix3( this );
44533
44534 },
44535 multiplyVector3Array: function ( /* a */ ) {
44536
44537 console.error( 'THREE.Matrix3: .multiplyVector3Array() has been removed.' );
44538
44539 },
44540 applyToBuffer: function ( buffer /*, offset, length */ ) {
44541
44542 console.warn( 'THREE.Matrix3: .applyToBuffer() has been removed. Use matrix.applyToBufferAttribute( attribute ) instead.' );
44543 return this.applyToBufferAttribute( buffer );
44544
44545 },
44546 applyToVector3Array: function ( /* array, offset, length */ ) {
44547
44548 console.error( 'THREE.Matrix3: .applyToVector3Array() has been removed.' );
44549
44550 }
44551
44552 } );
44553
44554 Object.assign( Matrix4.prototype, {
44555
44556 extractPosition: function ( m ) {
44557
44558 console.warn( 'THREE.Matrix4: .extractPosition() has been renamed to .copyPosition().' );
44559 return this.copyPosition( m );
44560
44561 },
44562 flattenToArrayOffset: function ( array, offset ) {
44563
44564 console.warn( "THREE.Matrix4: .flattenToArrayOffset() has been deprecated. Use .toArray() instead." );
44565 return this.toArray( array, offset );
44566
44567 },
44568 getPosition: function () {
44569
44570 var v1;
44571
44572 return function getPosition() {
44573
44574 if ( v1 === undefined ) v1 = new Vector3();
44575 console.warn( 'THREE.Matrix4: .getPosition() has been removed. Use Vector3.setFromMatrixPosition( matrix ) instead.' );
44576 return v1.setFromMatrixColumn( this, 3 );
44577
44578 };
44579
44580 }(),
44581 setRotationFromQuaternion: function ( q ) {
44582
44583 console.warn( 'THREE.Matrix4: .setRotationFromQuaternion() has been renamed to .makeRotationFromQuaternion().' );
44584 return this.makeRotationFromQuaternion( q );
44585
44586 },
44587 multiplyToArray: function () {
44588
44589 console.warn( 'THREE.Matrix4: .multiplyToArray() has been removed.' );
44590
44591 },
44592 multiplyVector3: function ( vector ) {
44593
44594 console.warn( 'THREE.Matrix4: .multiplyVector3() has been removed. Use vector.applyMatrix4( matrix ) instead.' );
44595 return vector.applyMatrix4( this );
44596
44597 },
44598 multiplyVector4: function ( vector ) {
44599
44600 console.warn( 'THREE.Matrix4: .multiplyVector4() has been removed. Use vector.applyMatrix4( matrix ) instead.' );
44601 return vector.applyMatrix4( this );
44602
44603 },
44604 multiplyVector3Array: function ( /* a */ ) {
44605
44606 console.error( 'THREE.Matrix4: .multiplyVector3Array() has been removed.' );
44607
44608 },
44609 rotateAxis: function ( v ) {
44610
44611 console.warn( 'THREE.Matrix4: .rotateAxis() has been removed. Use Vector3.transformDirection( matrix ) instead.' );
44612 v.transformDirection( this );
44613
44614 },
44615 crossVector: function ( vector ) {
44616
44617 console.warn( 'THREE.Matrix4: .crossVector() has been removed. Use vector.applyMatrix4( matrix ) instead.' );
44618 return vector.applyMatrix4( this );
44619
44620 },
44621 translate: function () {
44622
44623 console.error( 'THREE.Matrix4: .translate() has been removed.' );
44624
44625 },
44626 rotateX: function () {
44627
44628 console.error( 'THREE.Matrix4: .rotateX() has been removed.' );
44629
44630 },
44631 rotateY: function () {
44632
44633 console.error( 'THREE.Matrix4: .rotateY() has been removed.' );
44634
44635 },
44636 rotateZ: function () {
44637
44638 console.error( 'THREE.Matrix4: .rotateZ() has been removed.' );
44639
44640 },
44641 rotateByAxis: function () {
44642
44643 console.error( 'THREE.Matrix4: .rotateByAxis() has been removed.' );
44644
44645 },
44646 applyToBuffer: function ( buffer /*, offset, length */ ) {
44647
44648 console.warn( 'THREE.Matrix4: .applyToBuffer() has been removed. Use matrix.applyToBufferAttribute( attribute ) instead.' );
44649 return this.applyToBufferAttribute( buffer );
44650
44651 },
44652 applyToVector3Array: function ( /* array, offset, length */ ) {
44653
44654 console.error( 'THREE.Matrix4: .applyToVector3Array() has been removed.' );
44655
44656 },
44657 makeFrustum: function ( left, right, bottom, top, near, far ) {
44658
44659 console.warn( 'THREE.Matrix4: .makeFrustum() has been removed. Use .makePerspective( left, right, top, bottom, near, far ) instead.' );
44660 return this.makePerspective( left, right, top, bottom, near, far );
44661
44662 }
44663
44664 } );
44665
44666 Plane.prototype.isIntersectionLine = function ( line ) {
44667
44668 console.warn( 'THREE.Plane: .isIntersectionLine() has been renamed to .intersectsLine().' );
44669 return this.intersectsLine( line );
44670
44671 };
44672
44673 Quaternion.prototype.multiplyVector3 = function ( vector ) {
44674
44675 console.warn( 'THREE.Quaternion: .multiplyVector3() has been removed. Use is now vector.applyQuaternion( quaternion ) instead.' );
44676 return vector.applyQuaternion( this );
44677
44678 };
44679
44680 Object.assign( Ray.prototype, {
44681
44682 isIntersectionBox: function ( box ) {
44683
44684 console.warn( 'THREE.Ray: .isIntersectionBox() has been renamed to .intersectsBox().' );
44685 return this.intersectsBox( box );
44686
44687 },
44688 isIntersectionPlane: function ( plane ) {
44689
44690 console.warn( 'THREE.Ray: .isIntersectionPlane() has been renamed to .intersectsPlane().' );
44691 return this.intersectsPlane( plane );
44692
44693 },
44694 isIntersectionSphere: function ( sphere ) {
44695
44696 console.warn( 'THREE.Ray: .isIntersectionSphere() has been renamed to .intersectsSphere().' );
44697 return this.intersectsSphere( sphere );
44698
44699 }
44700
44701 } );
44702
44703 Object.assign( Triangle.prototype, {
44704
44705 area: function () {
44706
44707 console.warn( 'THREE.Triangle: .area() has been renamed to .getArea().' );
44708 return this.getArea();
44709
44710 },
44711 barycoordFromPoint: function ( point, target ) {
44712
44713 console.warn( 'THREE.Triangle: .barycoordFromPoint() has been renamed to .getBarycoord().' );
44714 return this.getBarycoord( point, target );
44715
44716 },
44717 midpoint: function ( target ) {
44718
44719 console.warn( 'THREE.Triangle: .midpoint() has been renamed to .getMidpoint().' );
44720 return this.getMidpoint( target );
44721
44722 },
44723 normal: function ( target ) {
44724
44725 console.warn( 'THREE.Triangle: .normal() has been renamed to .getNormal().' );
44726 return this.getNormal( target );
44727
44728 },
44729 plane: function ( target ) {
44730
44731 console.warn( 'THREE.Triangle: .plane() has been renamed to .getPlane().' );
44732 return this.getPlane( target );
44733
44734 }
44735
44736 } );
44737
44738 Object.assign( Triangle, {
44739
44740 barycoordFromPoint: function ( point, a, b, c, target ) {
44741
44742 console.warn( 'THREE.Triangle: .barycoordFromPoint() has been renamed to .getBarycoord().' );
44743 return Triangle.getBarycoord( point, a, b, c, target );
44744
44745 },
44746 normal: function ( a, b, c, target ) {
44747
44748 console.warn( 'THREE.Triangle: .normal() has been renamed to .getNormal().' );
44749 return Triangle.getNormal( a, b, c, target );
44750
44751 }
44752
44753 } );
44754
44755 Object.assign( Shape.prototype, {
44756
44757 extractAllPoints: function ( divisions ) {
44758
44759 console.warn( 'THREE.Shape: .extractAllPoints() has been removed. Use .extractPoints() instead.' );
44760 return this.extractPoints( divisions );
44761
44762 },
44763 extrude: function ( options ) {
44764
44765 console.warn( 'THREE.Shape: .extrude() has been removed. Use ExtrudeGeometry() instead.' );
44766 return new ExtrudeGeometry( this, options );
44767
44768 },
44769 makeGeometry: function ( options ) {
44770
44771 console.warn( 'THREE.Shape: .makeGeometry() has been removed. Use ShapeGeometry() instead.' );
44772 return new ShapeGeometry( this, options );
44773
44774 }
44775
44776 } );
44777
44778 Object.assign( Vector2.prototype, {
44779
44780 fromAttribute: function ( attribute, index, offset ) {
44781
44782 console.warn( 'THREE.Vector2: .fromAttribute() has been renamed to .fromBufferAttribute().' );
44783 return this.fromBufferAttribute( attribute, index, offset );
44784
44785 },
44786 distanceToManhattan: function ( v ) {
44787
44788 console.warn( 'THREE.Vector2: .distanceToManhattan() has been renamed to .manhattanDistanceTo().' );
44789 return this.manhattanDistanceTo( v );
44790
44791 },
44792 lengthManhattan: function () {
44793
44794 console.warn( 'THREE.Vector2: .lengthManhattan() has been renamed to .manhattanLength().' );
44795 return this.manhattanLength();
44796
44797 }
44798
44799 } );
44800
44801 Object.assign( Vector3.prototype, {
44802
44803 setEulerFromRotationMatrix: function () {
44804
44805 console.error( 'THREE.Vector3: .setEulerFromRotationMatrix() has been removed. Use Euler.setFromRotationMatrix() instead.' );
44806
44807 },
44808 setEulerFromQuaternion: function () {
44809
44810 console.error( 'THREE.Vector3: .setEulerFromQuaternion() has been removed. Use Euler.setFromQuaternion() instead.' );
44811
44812 },
44813 getPositionFromMatrix: function ( m ) {
44814
44815 console.warn( 'THREE.Vector3: .getPositionFromMatrix() has been renamed to .setFromMatrixPosition().' );
44816 return this.setFromMatrixPosition( m );
44817
44818 },
44819 getScaleFromMatrix: function ( m ) {
44820
44821 console.warn( 'THREE.Vector3: .getScaleFromMatrix() has been renamed to .setFromMatrixScale().' );
44822 return this.setFromMatrixScale( m );
44823
44824 },
44825 getColumnFromMatrix: function ( index, matrix ) {
44826
44827 console.warn( 'THREE.Vector3: .getColumnFromMatrix() has been renamed to .setFromMatrixColumn().' );
44828 return this.setFromMatrixColumn( matrix, index );
44829
44830 },
44831 applyProjection: function ( m ) {
44832
44833 console.warn( 'THREE.Vector3: .applyProjection() has been removed. Use .applyMatrix4( m ) instead.' );
44834 return this.applyMatrix4( m );
44835
44836 },
44837 fromAttribute: function ( attribute, index, offset ) {
44838
44839 console.warn( 'THREE.Vector3: .fromAttribute() has been renamed to .fromBufferAttribute().' );
44840 return this.fromBufferAttribute( attribute, index, offset );
44841
44842 },
44843 distanceToManhattan: function ( v ) {
44844
44845 console.warn( 'THREE.Vector3: .distanceToManhattan() has been renamed to .manhattanDistanceTo().' );
44846 return this.manhattanDistanceTo( v );
44847
44848 },
44849 lengthManhattan: function () {
44850
44851 console.warn( 'THREE.Vector3: .lengthManhattan() has been renamed to .manhattanLength().' );
44852 return this.manhattanLength();
44853
44854 }
44855
44856 } );
44857
44858 Object.assign( Vector4.prototype, {
44859
44860 fromAttribute: function ( attribute, index, offset ) {
44861
44862 console.warn( 'THREE.Vector4: .fromAttribute() has been renamed to .fromBufferAttribute().' );
44863 return this.fromBufferAttribute( attribute, index, offset );
44864
44865 },
44866 lengthManhattan: function () {
44867
44868 console.warn( 'THREE.Vector4: .lengthManhattan() has been renamed to .manhattanLength().' );
44869 return this.manhattanLength();
44870
44871 }
44872
44873 } );
44874
44875 //
44876
44877 Object.assign( Geometry.prototype, {
44878
44879 computeTangents: function () {
44880
44881 console.error( 'THREE.Geometry: .computeTangents() has been removed.' );
44882
44883 },
44884 computeLineDistances: function () {
44885
44886 console.error( 'THREE.Geometry: .computeLineDistances() has been removed. Use THREE.Line.computeLineDistances() instead.' );
44887
44888 }
44889
44890 } );
44891
44892 Object.assign( Object3D.prototype, {
44893
44894 getChildByName: function ( name ) {
44895
44896 console.warn( 'THREE.Object3D: .getChildByName() has been renamed to .getObjectByName().' );
44897 return this.getObjectByName( name );
44898
44899 },
44900 renderDepth: function () {
44901
44902 console.warn( 'THREE.Object3D: .renderDepth has been removed. Use .renderOrder, instead.' );
44903
44904 },
44905 translate: function ( distance, axis ) {
44906
44907 console.warn( 'THREE.Object3D: .translate() has been removed. Use .translateOnAxis( axis, distance ) instead.' );
44908 return this.translateOnAxis( axis, distance );
44909
44910 },
44911 getWorldRotation: function () {
44912
44913 console.error( 'THREE.Object3D: .getWorldRotation() has been removed. Use THREE.Object3D.getWorldQuaternion( target ) instead.' );
44914
44915 }
44916
44917 } );
44918
44919 Object.defineProperties( Object3D.prototype, {
44920
44921 eulerOrder: {
44922 get: function () {
44923
44924 console.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' );
44925 return this.rotation.order;
44926
44927 },
44928 set: function ( value ) {
44929
44930 console.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' );
44931 this.rotation.order = value;
44932
44933 }
44934 },
44935 useQuaternion: {
44936 get: function () {
44937
44938 console.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' );
44939
44940 },
44941 set: function () {
44942
44943 console.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' );
44944
44945 }
44946 }
44947
44948 } );
44949
44950 Object.defineProperties( LOD.prototype, {
44951
44952 objects: {
44953 get: function () {
44954
44955 console.warn( 'THREE.LOD: .objects has been renamed to .levels.' );
44956 return this.levels;
44957
44958 }
44959 }
44960
44961 } );
44962
44963 Object.defineProperty( Skeleton.prototype, 'useVertexTexture', {
44964
44965 get: function () {
44966
44967 console.warn( 'THREE.Skeleton: useVertexTexture has been removed.' );
44968
44969 },
44970 set: function () {
44971
44972 console.warn( 'THREE.Skeleton: useVertexTexture has been removed.' );
44973
44974 }
44975
44976 } );
44977
44978 Object.defineProperty( Curve.prototype, '__arcLengthDivisions', {
44979
44980 get: function () {
44981
44982 console.warn( 'THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.' );
44983 return this.arcLengthDivisions;
44984
44985 },
44986 set: function ( value ) {
44987
44988 console.warn( 'THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.' );
44989 this.arcLengthDivisions = value;
44990
44991 }
44992
44993 } );
44994
44995 //
44996
44997 PerspectiveCamera.prototype.setLens = function ( focalLength, filmGauge ) {
44998
44999 console.warn( "THREE.PerspectiveCamera.setLens is deprecated. " +
45000 "Use .setFocalLength and .filmGauge for a photographic setup." );
45001
45002 if ( filmGauge !== undefined ) this.filmGauge = filmGauge;
45003 this.setFocalLength( focalLength );
45004
45005 };
45006
45007 //
45008
45009 Object.defineProperties( Light.prototype, {
45010 onlyShadow: {
45011 set: function () {
45012
45013 console.warn( 'THREE.Light: .onlyShadow has been removed.' );
45014
45015 }
45016 },
45017 shadowCameraFov: {
45018 set: function ( value ) {
45019
45020 console.warn( 'THREE.Light: .shadowCameraFov is now .shadow.camera.fov.' );
45021 this.shadow.camera.fov = value;
45022
45023 }
45024 },
45025 shadowCameraLeft: {
45026 set: function ( value ) {
45027
45028 console.warn( 'THREE.Light: .shadowCameraLeft is now .shadow.camera.left.' );
45029 this.shadow.camera.left = value;
45030
45031 }
45032 },
45033 shadowCameraRight: {
45034 set: function ( value ) {
45035
45036 console.warn( 'THREE.Light: .shadowCameraRight is now .shadow.camera.right.' );
45037 this.shadow.camera.right = value;
45038
45039 }
45040 },
45041 shadowCameraTop: {
45042 set: function ( value ) {
45043
45044 console.warn( 'THREE.Light: .shadowCameraTop is now .shadow.camera.top.' );
45045 this.shadow.camera.top = value;
45046
45047 }
45048 },
45049 shadowCameraBottom: {
45050 set: function ( value ) {
45051
45052 console.warn( 'THREE.Light: .shadowCameraBottom is now .shadow.camera.bottom.' );
45053 this.shadow.camera.bottom = value;
45054
45055 }
45056 },
45057 shadowCameraNear: {
45058 set: function ( value ) {
45059
45060 console.warn( 'THREE.Light: .shadowCameraNear is now .shadow.camera.near.' );
45061 this.shadow.camera.near = value;
45062
45063 }
45064 },
45065 shadowCameraFar: {
45066 set: function ( value ) {
45067
45068 console.warn( 'THREE.Light: .shadowCameraFar is now .shadow.camera.far.' );
45069 this.shadow.camera.far = value;
45070
45071 }
45072 },
45073 shadowCameraVisible: {
45074 set: function () {
45075
45076 console.warn( 'THREE.Light: .shadowCameraVisible has been removed. Use new THREE.CameraHelper( light.shadow.camera ) instead.' );
45077
45078 }
45079 },
45080 shadowBias: {
45081 set: function ( value ) {
45082
45083 console.warn( 'THREE.Light: .shadowBias is now .shadow.bias.' );
45084 this.shadow.bias = value;
45085
45086 }
45087 },
45088 shadowDarkness: {
45089 set: function () {
45090
45091 console.warn( 'THREE.Light: .shadowDarkness has been removed.' );
45092
45093 }
45094 },
45095 shadowMapWidth: {
45096 set: function ( value ) {
45097
45098 console.warn( 'THREE.Light: .shadowMapWidth is now .shadow.mapSize.width.' );
45099 this.shadow.mapSize.width = value;
45100
45101 }
45102 },
45103 shadowMapHeight: {
45104 set: function ( value ) {
45105
45106 console.warn( 'THREE.Light: .shadowMapHeight is now .shadow.mapSize.height.' );
45107 this.shadow.mapSize.height = value;
45108
45109 }
45110 }
45111 } );
45112
45113 //
45114
45115 Object.defineProperties( BufferAttribute.prototype, {
45116
45117 length: {
45118 get: function () {
45119
45120 console.warn( 'THREE.BufferAttribute: .length has been deprecated. Use .count instead.' );
45121 return this.array.length;
45122
45123 }
45124 },
45125 copyIndicesArray: function ( /* indices */ ) {
45126
45127 console.error( 'THREE.BufferAttribute: .copyIndicesArray() has been removed.' );
45128
45129 }
45130
45131 } );
45132
45133 Object.assign( BufferGeometry.prototype, {
45134
45135 addIndex: function ( index ) {
45136
45137 console.warn( 'THREE.BufferGeometry: .addIndex() has been renamed to .setIndex().' );
45138 this.setIndex( index );
45139
45140 },
45141 addDrawCall: function ( start, count, indexOffset ) {
45142
45143 if ( indexOffset !== undefined ) {
45144
45145 console.warn( 'THREE.BufferGeometry: .addDrawCall() no longer supports indexOffset.' );
45146
45147 }
45148 console.warn( 'THREE.BufferGeometry: .addDrawCall() is now .addGroup().' );
45149 this.addGroup( start, count );
45150
45151 },
45152 clearDrawCalls: function () {
45153
45154 console.warn( 'THREE.BufferGeometry: .clearDrawCalls() is now .clearGroups().' );
45155 this.clearGroups();
45156
45157 },
45158 computeTangents: function () {
45159
45160 console.warn( 'THREE.BufferGeometry: .computeTangents() has been removed.' );
45161
45162 },
45163 computeOffsets: function () {
45164
45165 console.warn( 'THREE.BufferGeometry: .computeOffsets() has been removed.' );
45166
45167 }
45168
45169 } );
45170
45171 Object.defineProperties( BufferGeometry.prototype, {
45172
45173 drawcalls: {
45174 get: function () {
45175
45176 console.error( 'THREE.BufferGeometry: .drawcalls has been renamed to .groups.' );
45177 return this.groups;
45178
45179 }
45180 },
45181 offsets: {
45182 get: function () {
45183
45184 console.warn( 'THREE.BufferGeometry: .offsets has been renamed to .groups.' );
45185 return this.groups;
45186
45187 }
45188 }
45189
45190 } );
45191
45192 //
45193
45194 Object.assign( ExtrudeBufferGeometry.prototype, {
45195
45196 getArrays: function () {
45197
45198 console.error( 'THREE.ExtrudeBufferGeometry: .getArrays() has been removed.' );
45199
45200 },
45201
45202 addShapeList: function () {
45203
45204 console.error( 'THREE.ExtrudeBufferGeometry: .addShapeList() has been removed.' );
45205
45206 },
45207
45208 addShape: function () {
45209
45210 console.error( 'THREE.ExtrudeBufferGeometry: .addShape() has been removed.' );
45211
45212 }
45213
45214 } );
45215
45216 //
45217
45218 Object.defineProperties( Uniform.prototype, {
45219
45220 dynamic: {
45221 set: function () {
45222
45223 console.warn( 'THREE.Uniform: .dynamic has been removed. Use object.onBeforeRender() instead.' );
45224
45225 }
45226 },
45227 onUpdate: {
45228 value: function () {
45229
45230 console.warn( 'THREE.Uniform: .onUpdate() has been removed. Use object.onBeforeRender() instead.' );
45231 return this;
45232
45233 }
45234 }
45235
45236 } );
45237
45238 //
45239
45240 Object.defineProperties( Material.prototype, {
45241
45242 wrapAround: {
45243 get: function () {
45244
45245 console.warn( 'THREE.Material: .wrapAround has been removed.' );
45246
45247 },
45248 set: function () {
45249
45250 console.warn( 'THREE.Material: .wrapAround has been removed.' );
45251
45252 }
45253 },
45254 wrapRGB: {
45255 get: function () {
45256
45257 console.warn( 'THREE.Material: .wrapRGB has been removed.' );
45258 return new Color();
45259
45260 }
45261 },
45262
45263 shading: {
45264 get: function () {
45265
45266 console.error( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );
45267
45268 },
45269 set: function ( value ) {
45270
45271 console.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );
45272 this.flatShading = ( value === FlatShading );
45273
45274 }
45275 }
45276
45277 } );
45278
45279 Object.defineProperties( MeshPhongMaterial.prototype, {
45280
45281 metal: {
45282 get: function () {
45283
45284 console.warn( 'THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead.' );
45285 return false;
45286
45287 },
45288 set: function () {
45289
45290 console.warn( 'THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead' );
45291
45292 }
45293 }
45294
45295 } );
45296
45297 Object.defineProperties( ShaderMaterial.prototype, {
45298
45299 derivatives: {
45300 get: function () {
45301
45302 console.warn( 'THREE.ShaderMaterial: .derivatives has been moved to .extensions.derivatives.' );
45303 return this.extensions.derivatives;
45304
45305 },
45306 set: function ( value ) {
45307
45308 console.warn( 'THREE. ShaderMaterial: .derivatives has been moved to .extensions.derivatives.' );
45309 this.extensions.derivatives = value;
45310
45311 }
45312 }
45313
45314 } );
45315
45316 //
45317
45318 Object.assign( WebGLRenderer.prototype, {
45319
45320 getCurrentRenderTarget: function () {
45321
45322 console.warn( 'THREE.WebGLRenderer: .getCurrentRenderTarget() is now .getRenderTarget().' );
45323 return this.getRenderTarget();
45324
45325 },
45326
45327 getMaxAnisotropy: function () {
45328
45329 console.warn( 'THREE.WebGLRenderer: .getMaxAnisotropy() is now .capabilities.getMaxAnisotropy().' );
45330 return this.capabilities.getMaxAnisotropy();
45331
45332 },
45333
45334 getPrecision: function () {
45335
45336 console.warn( 'THREE.WebGLRenderer: .getPrecision() is now .capabilities.precision.' );
45337 return this.capabilities.precision;
45338
45339 },
45340
45341 resetGLState: function () {
45342
45343 console.warn( 'THREE.WebGLRenderer: .resetGLState() is now .state.reset().' );
45344 return this.state.reset();
45345
45346 },
45347
45348 supportsFloatTextures: function () {
45349
45350 console.warn( 'THREE.WebGLRenderer: .supportsFloatTextures() is now .extensions.get( \'OES_texture_float\' ).' );
45351 return this.extensions.get( 'OES_texture_float' );
45352
45353 },
45354 supportsHalfFloatTextures: function () {
45355
45356 console.warn( 'THREE.WebGLRenderer: .supportsHalfFloatTextures() is now .extensions.get( \'OES_texture_half_float\' ).' );
45357 return this.extensions.get( 'OES_texture_half_float' );
45358
45359 },
45360 supportsStandardDerivatives: function () {
45361
45362 console.warn( 'THREE.WebGLRenderer: .supportsStandardDerivatives() is now .extensions.get( \'OES_standard_derivatives\' ).' );
45363 return this.extensions.get( 'OES_standard_derivatives' );
45364
45365 },
45366 supportsCompressedTextureS3TC: function () {
45367
45368 console.warn( 'THREE.WebGLRenderer: .supportsCompressedTextureS3TC() is now .extensions.get( \'WEBGL_compressed_texture_s3tc\' ).' );
45369 return this.extensions.get( 'WEBGL_compressed_texture_s3tc' );
45370
45371 },
45372 supportsCompressedTexturePVRTC: function () {
45373
45374 console.warn( 'THREE.WebGLRenderer: .supportsCompressedTexturePVRTC() is now .extensions.get( \'WEBGL_compressed_texture_pvrtc\' ).' );
45375 return this.extensions.get( 'WEBGL_compressed_texture_pvrtc' );
45376
45377 },
45378 supportsBlendMinMax: function () {
45379
45380 console.warn( 'THREE.WebGLRenderer: .supportsBlendMinMax() is now .extensions.get( \'EXT_blend_minmax\' ).' );
45381 return this.extensions.get( 'EXT_blend_minmax' );
45382
45383 },
45384 supportsVertexTextures: function () {
45385
45386 console.warn( 'THREE.WebGLRenderer: .supportsVertexTextures() is now .capabilities.vertexTextures.' );
45387 return this.capabilities.vertexTextures;
45388
45389 },
45390 supportsInstancedArrays: function () {
45391
45392 console.warn( 'THREE.WebGLRenderer: .supportsInstancedArrays() is now .extensions.get( \'ANGLE_instanced_arrays\' ).' );
45393 return this.extensions.get( 'ANGLE_instanced_arrays' );
45394
45395 },
45396 enableScissorTest: function ( boolean ) {
45397
45398 console.warn( 'THREE.WebGLRenderer: .enableScissorTest() is now .setScissorTest().' );
45399 this.setScissorTest( boolean );
45400
45401 },
45402 initMaterial: function () {
45403
45404 console.warn( 'THREE.WebGLRenderer: .initMaterial() has been removed.' );
45405
45406 },
45407 addPrePlugin: function () {
45408
45409 console.warn( 'THREE.WebGLRenderer: .addPrePlugin() has been removed.' );
45410
45411 },
45412 addPostPlugin: function () {
45413
45414 console.warn( 'THREE.WebGLRenderer: .addPostPlugin() has been removed.' );
45415
45416 },
45417 updateShadowMap: function () {
45418
45419 console.warn( 'THREE.WebGLRenderer: .updateShadowMap() has been removed.' );
45420
45421 },
45422 setFaceCulling: function () {
45423
45424 console.warn( 'THREE.WebGLRenderer: .setFaceCulling() has been removed.' );
45425
45426 }
45427
45428 } );
45429
45430 Object.defineProperties( WebGLRenderer.prototype, {
45431
45432 shadowMapEnabled: {
45433 get: function () {
45434
45435 return this.shadowMap.enabled;
45436
45437 },
45438 set: function ( value ) {
45439
45440 console.warn( 'THREE.WebGLRenderer: .shadowMapEnabled is now .shadowMap.enabled.' );
45441 this.shadowMap.enabled = value;
45442
45443 }
45444 },
45445 shadowMapType: {
45446 get: function () {
45447
45448 return this.shadowMap.type;
45449
45450 },
45451 set: function ( value ) {
45452
45453 console.warn( 'THREE.WebGLRenderer: .shadowMapType is now .shadowMap.type.' );
45454 this.shadowMap.type = value;
45455
45456 }
45457 },
45458 shadowMapCullFace: {
45459 get: function () {
45460
45461 console.warn( 'THREE.WebGLRenderer: .shadowMapCullFace has been removed. Set Material.shadowSide instead.' );
45462 return undefined;
45463
45464 },
45465 set: function ( /* value */ ) {
45466
45467 console.warn( 'THREE.WebGLRenderer: .shadowMapCullFace has been removed. Set Material.shadowSide instead.' );
45468
45469 }
45470 }
45471 } );
45472
45473 Object.defineProperties( WebGLShadowMap.prototype, {
45474
45475 cullFace: {
45476 get: function () {
45477
45478 console.warn( 'THREE.WebGLRenderer: .shadowMap.cullFace has been removed. Set Material.shadowSide instead.' );
45479 return undefined;
45480
45481 },
45482 set: function ( /* cullFace */ ) {
45483
45484 console.warn( 'THREE.WebGLRenderer: .shadowMap.cullFace has been removed. Set Material.shadowSide instead.' );
45485
45486 }
45487 },
45488 renderReverseSided: {
45489 get: function () {
45490
45491 console.warn( 'THREE.WebGLRenderer: .shadowMap.renderReverseSided has been removed. Set Material.shadowSide instead.' );
45492 return undefined;
45493
45494 },
45495 set: function () {
45496
45497 console.warn( 'THREE.WebGLRenderer: .shadowMap.renderReverseSided has been removed. Set Material.shadowSide instead.' );
45498
45499 }
45500 },
45501 renderSingleSided: {
45502 get: function () {
45503
45504 console.warn( 'THREE.WebGLRenderer: .shadowMap.renderSingleSided has been removed. Set Material.shadowSide instead.' );
45505 return undefined;
45506
45507 },
45508 set: function () {
45509
45510 console.warn( 'THREE.WebGLRenderer: .shadowMap.renderSingleSided has been removed. Set Material.shadowSide instead.' );
45511
45512 }
45513 }
45514
45515 } );
45516
45517 //
45518
45519 Object.defineProperties( WebGLRenderTarget.prototype, {
45520
45521 wrapS: {
45522 get: function () {
45523
45524 console.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' );
45525 return this.texture.wrapS;
45526
45527 },
45528 set: function ( value ) {
45529
45530 console.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' );
45531 this.texture.wrapS = value;
45532
45533 }
45534 },
45535 wrapT: {
45536 get: function () {
45537
45538 console.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' );
45539 return this.texture.wrapT;
45540
45541 },
45542 set: function ( value ) {
45543
45544 console.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' );
45545 this.texture.wrapT = value;
45546
45547 }
45548 },
45549 magFilter: {
45550 get: function () {
45551
45552 console.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' );
45553 return this.texture.magFilter;
45554
45555 },
45556 set: function ( value ) {
45557
45558 console.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' );
45559 this.texture.magFilter = value;
45560
45561 }
45562 },
45563 minFilter: {
45564 get: function () {
45565
45566 console.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' );
45567 return this.texture.minFilter;
45568
45569 },
45570 set: function ( value ) {
45571
45572 console.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' );
45573 this.texture.minFilter = value;
45574
45575 }
45576 },
45577 anisotropy: {
45578 get: function () {
45579
45580 console.warn( 'THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.' );
45581 return this.texture.anisotropy;
45582
45583 },
45584 set: function ( value ) {
45585
45586 console.warn( 'THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.' );
45587 this.texture.anisotropy = value;
45588
45589 }
45590 },
45591 offset: {
45592 get: function () {
45593
45594 console.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' );
45595 return this.texture.offset;
45596
45597 },
45598 set: function ( value ) {
45599
45600 console.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' );
45601 this.texture.offset = value;
45602
45603 }
45604 },
45605 repeat: {
45606 get: function () {
45607
45608 console.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' );
45609 return this.texture.repeat;
45610
45611 },
45612 set: function ( value ) {
45613
45614 console.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' );
45615 this.texture.repeat = value;
45616
45617 }
45618 },
45619 format: {
45620 get: function () {
45621
45622 console.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' );
45623 return this.texture.format;
45624
45625 },
45626 set: function ( value ) {
45627
45628 console.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' );
45629 this.texture.format = value;
45630
45631 }
45632 },
45633 type: {
45634 get: function () {
45635
45636 console.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' );
45637 return this.texture.type;
45638
45639 },
45640 set: function ( value ) {
45641
45642 console.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' );
45643 this.texture.type = value;
45644
45645 }
45646 },
45647 generateMipmaps: {
45648 get: function () {
45649
45650 console.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' );
45651 return this.texture.generateMipmaps;
45652
45653 },
45654 set: function ( value ) {
45655
45656 console.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' );
45657 this.texture.generateMipmaps = value;
45658
45659 }
45660 }
45661
45662 } );
45663
45664 //
45665
45666 Object.defineProperties( WebVRManager.prototype, {
45667
45668 standing: {
45669 set: function ( /* value */ ) {
45670
45671 console.warn( 'THREE.WebVRManager: .standing has been removed.' );
45672
45673 }
45674 }
45675
45676 } );
45677
45678 //
45679
45680 Audio.prototype.load = function ( file ) {
45681
45682 console.warn( 'THREE.Audio: .load has been deprecated. Use THREE.AudioLoader instead.' );
45683 var scope = this;
45684 var audioLoader = new AudioLoader();
45685 audioLoader.load( file, function ( buffer ) {
45686
45687 scope.setBuffer( buffer );
45688
45689 } );
45690 return this;
45691
45692 };
45693
45694 AudioAnalyser.prototype.getData = function () {
45695
45696 console.warn( 'THREE.AudioAnalyser: .getData() is now .getFrequencyData().' );
45697 return this.getFrequencyData();
45698
45699 };
45700
45701 //
45702
45703 CubeCamera.prototype.updateCubeMap = function ( renderer, scene ) {
45704
45705 console.warn( 'THREE.CubeCamera: .updateCubeMap() is now .update().' );
45706 return this.update( renderer, scene );
45707
45708 };
45709
45710 //
45711
45712 var GeometryUtils = {
45713
45714 merge: function ( geometry1, geometry2, materialIndexOffset ) {
45715
45716 console.warn( 'THREE.GeometryUtils: .merge() has been moved to Geometry. Use geometry.merge( geometry2, matrix, materialIndexOffset ) instead.' );
45717 var matrix;
45718
45719 if ( geometry2.isMesh ) {
45720
45721 geometry2.matrixAutoUpdate && geometry2.updateMatrix();
45722
45723 matrix = geometry2.matrix;
45724 geometry2 = geometry2.geometry;
45725
45726 }
45727
45728 geometry1.merge( geometry2, matrix, materialIndexOffset );
45729
45730 },
45731
45732 center: function ( geometry ) {
45733
45734 console.warn( 'THREE.GeometryUtils: .center() has been moved to Geometry. Use geometry.center() instead.' );
45735 return geometry.center();
45736
45737 }
45738
45739 };
45740
45741 var ImageUtils = {
45742
45743 crossOrigin: undefined,
45744
45745 loadTexture: function ( url, mapping, onLoad, onError ) {
45746
45747 console.warn( 'THREE.ImageUtils.loadTexture has been deprecated. Use THREE.TextureLoader() instead.' );
45748
45749 var loader = new TextureLoader();
45750 loader.setCrossOrigin( this.crossOrigin );
45751
45752 var texture = loader.load( url, onLoad, undefined, onError );
45753
45754 if ( mapping ) texture.mapping = mapping;
45755
45756 return texture;
45757
45758 },
45759
45760 loadTextureCube: function ( urls, mapping, onLoad, onError ) {
45761
45762 console.warn( 'THREE.ImageUtils.loadTextureCube has been deprecated. Use THREE.CubeTextureLoader() instead.' );
45763
45764 var loader = new CubeTextureLoader();
45765 loader.setCrossOrigin( this.crossOrigin );
45766
45767 var texture = loader.load( urls, onLoad, undefined, onError );
45768
45769 if ( mapping ) texture.mapping = mapping;
45770
45771 return texture;
45772
45773 },
45774
45775 loadCompressedTexture: function () {
45776
45777 console.error( 'THREE.ImageUtils.loadCompressedTexture has been removed. Use THREE.DDSLoader instead.' );
45778
45779 },
45780
45781 loadCompressedTextureCube: function () {
45782
45783 console.error( 'THREE.ImageUtils.loadCompressedTextureCube has been removed. Use THREE.DDSLoader instead.' );
45784
45785 }
45786
45787 };
45788
45789 //
45790
45791 function Projector() {
45792
45793 console.error( 'THREE.Projector has been moved to /examples/js/renderers/Projector.js.' );
45794
45795 this.projectVector = function ( vector, camera ) {
45796
45797 console.warn( 'THREE.Projector: .projectVector() is now vector.project().' );
45798 vector.project( camera );
45799
45800 };
45801
45802 this.unprojectVector = function ( vector, camera ) {
45803
45804 console.warn( 'THREE.Projector: .unprojectVector() is now vector.unproject().' );
45805 vector.unproject( camera );
45806
45807 };
45808
45809 this.pickingRay = function () {
45810
45811 console.error( 'THREE.Projector: .pickingRay() is now raycaster.setFromCamera().' );
45812
45813 };
45814
45815 }
45816
45817 //
45818
45819 function CanvasRenderer() {
45820
45821 console.error( 'THREE.CanvasRenderer has been moved to /examples/js/renderers/CanvasRenderer.js' );
45822
45823 this.domElement = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
45824 this.clear = function () {};
45825 this.render = function () {};
45826 this.setClearColor = function () {};
45827 this.setSize = function () {};
45828
45829 }
45830
45831 //
45832
45833 var SceneUtils = {
45834
45835 createMultiMaterialObject: function ( /* geometry, materials */ ) {
45836
45837 console.error( 'THREE.SceneUtils has been moved to /examples/js/utils/SceneUtils.js' );
45838
45839 },
45840
45841 detach: function ( /* child, parent, scene */ ) {
45842
45843 console.error( 'THREE.SceneUtils has been moved to /examples/js/utils/SceneUtils.js' );
45844
45845 },
45846
45847 attach: function ( /* child, scene, parent */ ) {
45848
45849 console.error( 'THREE.SceneUtils has been moved to /examples/js/utils/SceneUtils.js' );
45850
45851 }
45852
45853 };
45854
45855 //
45856
45857 function LensFlare() {
45858
45859 console.error( 'THREE.LensFlare has been moved to /examples/js/objects/Lensflare.js' );
45860
45861 }
45862
45863 exports.WebGLRenderTargetCube = WebGLRenderTargetCube;
45864 exports.WebGLRenderTarget = WebGLRenderTarget;
45865 exports.WebGLRenderer = WebGLRenderer;
45866 exports.ShaderLib = ShaderLib;
45867 exports.UniformsLib = UniformsLib;
45868 exports.UniformsUtils = UniformsUtils;
45869 exports.ShaderChunk = ShaderChunk;
45870 exports.FogExp2 = FogExp2;
45871 exports.Fog = Fog;
45872 exports.Scene = Scene;
45873 exports.Sprite = Sprite;
45874 exports.LOD = LOD;
45875 exports.SkinnedMesh = SkinnedMesh;
45876 exports.Skeleton = Skeleton;
45877 exports.Bone = Bone;
45878 exports.Mesh = Mesh;
45879 exports.LineSegments = LineSegments;
45880 exports.LineLoop = LineLoop;
45881 exports.Line = Line;
45882 exports.Points = Points;
45883 exports.Group = Group;
45884 exports.VideoTexture = VideoTexture;
45885 exports.DataTexture = DataTexture;
45886 exports.CompressedTexture = CompressedTexture;
45887 exports.CubeTexture = CubeTexture;
45888 exports.CanvasTexture = CanvasTexture;
45889 exports.DepthTexture = DepthTexture;
45890 exports.Texture = Texture;
45891 exports.CompressedTextureLoader = CompressedTextureLoader;
45892 exports.DataTextureLoader = DataTextureLoader;
45893 exports.CubeTextureLoader = CubeTextureLoader;
45894 exports.TextureLoader = TextureLoader;
45895 exports.ObjectLoader = ObjectLoader;
45896 exports.MaterialLoader = MaterialLoader;
45897 exports.BufferGeometryLoader = BufferGeometryLoader;
45898 exports.DefaultLoadingManager = DefaultLoadingManager;
45899 exports.LoadingManager = LoadingManager;
45900 exports.JSONLoader = JSONLoader;
45901 exports.ImageLoader = ImageLoader;
45902 exports.ImageBitmapLoader = ImageBitmapLoader;
45903 exports.FontLoader = FontLoader;
45904 exports.FileLoader = FileLoader;
45905 exports.Loader = Loader;
45906 exports.LoaderUtils = LoaderUtils;
45907 exports.Cache = Cache;
45908 exports.AudioLoader = AudioLoader;
45909 exports.SpotLightShadow = SpotLightShadow;
45910 exports.SpotLight = SpotLight;
45911 exports.PointLight = PointLight;
45912 exports.RectAreaLight = RectAreaLight;
45913 exports.HemisphereLight = HemisphereLight;
45914 exports.DirectionalLightShadow = DirectionalLightShadow;
45915 exports.DirectionalLight = DirectionalLight;
45916 exports.AmbientLight = AmbientLight;
45917 exports.LightShadow = LightShadow;
45918 exports.Light = Light;
45919 exports.StereoCamera = StereoCamera;
45920 exports.PerspectiveCamera = PerspectiveCamera;
45921 exports.OrthographicCamera = OrthographicCamera;
45922 exports.CubeCamera = CubeCamera;
45923 exports.ArrayCamera = ArrayCamera;
45924 exports.Camera = Camera;
45925 exports.AudioListener = AudioListener;
45926 exports.PositionalAudio = PositionalAudio;
45927 exports.AudioContext = AudioContext;
45928 exports.AudioAnalyser = AudioAnalyser;
45929 exports.Audio = Audio;
45930 exports.VectorKeyframeTrack = VectorKeyframeTrack;
45931 exports.StringKeyframeTrack = StringKeyframeTrack;
45932 exports.QuaternionKeyframeTrack = QuaternionKeyframeTrack;
45933 exports.NumberKeyframeTrack = NumberKeyframeTrack;
45934 exports.ColorKeyframeTrack = ColorKeyframeTrack;
45935 exports.BooleanKeyframeTrack = BooleanKeyframeTrack;
45936 exports.PropertyMixer = PropertyMixer;
45937 exports.PropertyBinding = PropertyBinding;
45938 exports.KeyframeTrack = KeyframeTrack;
45939 exports.AnimationUtils = AnimationUtils;
45940 exports.AnimationObjectGroup = AnimationObjectGroup;
45941 exports.AnimationMixer = AnimationMixer;
45942 exports.AnimationClip = AnimationClip;
45943 exports.Uniform = Uniform;
45944 exports.InstancedBufferGeometry = InstancedBufferGeometry;
45945 exports.BufferGeometry = BufferGeometry;
45946 exports.Geometry = Geometry;
45947 exports.InterleavedBufferAttribute = InterleavedBufferAttribute;
45948 exports.InstancedInterleavedBuffer = InstancedInterleavedBuffer;
45949 exports.InterleavedBuffer = InterleavedBuffer;
45950 exports.InstancedBufferAttribute = InstancedBufferAttribute;
45951 exports.Face3 = Face3;
45952 exports.Object3D = Object3D;
45953 exports.Raycaster = Raycaster;
45954 exports.Layers = Layers;
45955 exports.EventDispatcher = EventDispatcher;
45956 exports.Clock = Clock;
45957 exports.QuaternionLinearInterpolant = QuaternionLinearInterpolant;
45958 exports.LinearInterpolant = LinearInterpolant;
45959 exports.DiscreteInterpolant = DiscreteInterpolant;
45960 exports.CubicInterpolant = CubicInterpolant;
45961 exports.Interpolant = Interpolant;
45962 exports.Triangle = Triangle;
45963 exports.Math = _Math;
45964 exports.Spherical = Spherical;
45965 exports.Cylindrical = Cylindrical;
45966 exports.Plane = Plane;
45967 exports.Frustum = Frustum;
45968 exports.Sphere = Sphere;
45969 exports.Ray = Ray;
45970 exports.Matrix4 = Matrix4;
45971 exports.Matrix3 = Matrix3;
45972 exports.Box3 = Box3;
45973 exports.Box2 = Box2;
45974 exports.Line3 = Line3;
45975 exports.Euler = Euler;
45976 exports.Vector4 = Vector4;
45977 exports.Vector3 = Vector3;
45978 exports.Vector2 = Vector2;
45979 exports.Quaternion = Quaternion;
45980 exports.Color = Color;
45981 exports.ImmediateRenderObject = ImmediateRenderObject;
45982 exports.VertexNormalsHelper = VertexNormalsHelper;
45983 exports.SpotLightHelper = SpotLightHelper;
45984 exports.SkeletonHelper = SkeletonHelper;
45985 exports.PointLightHelper = PointLightHelper;
45986 exports.RectAreaLightHelper = RectAreaLightHelper;
45987 exports.HemisphereLightHelper = HemisphereLightHelper;
45988 exports.GridHelper = GridHelper;
45989 exports.PolarGridHelper = PolarGridHelper;
45990 exports.FaceNormalsHelper = FaceNormalsHelper;
45991 exports.DirectionalLightHelper = DirectionalLightHelper;
45992 exports.CameraHelper = CameraHelper;
45993 exports.BoxHelper = BoxHelper;
45994 exports.Box3Helper = Box3Helper;
45995 exports.PlaneHelper = PlaneHelper;
45996 exports.ArrowHelper = ArrowHelper;
45997 exports.AxesHelper = AxesHelper;
45998 exports.Shape = Shape;
45999 exports.Path = Path;
46000 exports.ShapePath = ShapePath;
46001 exports.Font = Font;
46002 exports.CurvePath = CurvePath;
46003 exports.Curve = Curve;
46004 exports.ShapeUtils = ShapeUtils;
46005 exports.WebGLUtils = WebGLUtils;
46006 exports.WireframeGeometry = WireframeGeometry;
46007 exports.ParametricGeometry = ParametricGeometry;
46008 exports.ParametricBufferGeometry = ParametricBufferGeometry;
46009 exports.TetrahedronGeometry = TetrahedronGeometry;
46010 exports.TetrahedronBufferGeometry = TetrahedronBufferGeometry;
46011 exports.OctahedronGeometry = OctahedronGeometry;
46012 exports.OctahedronBufferGeometry = OctahedronBufferGeometry;
46013 exports.IcosahedronGeometry = IcosahedronGeometry;
46014 exports.IcosahedronBufferGeometry = IcosahedronBufferGeometry;
46015 exports.DodecahedronGeometry = DodecahedronGeometry;
46016 exports.DodecahedronBufferGeometry = DodecahedronBufferGeometry;
46017 exports.PolyhedronGeometry = PolyhedronGeometry;
46018 exports.PolyhedronBufferGeometry = PolyhedronBufferGeometry;
46019 exports.TubeGeometry = TubeGeometry;
46020 exports.TubeBufferGeometry = TubeBufferGeometry;
46021 exports.TorusKnotGeometry = TorusKnotGeometry;
46022 exports.TorusKnotBufferGeometry = TorusKnotBufferGeometry;
46023 exports.TorusGeometry = TorusGeometry;
46024 exports.TorusBufferGeometry = TorusBufferGeometry;
46025 exports.TextGeometry = TextGeometry;
46026 exports.TextBufferGeometry = TextBufferGeometry;
46027 exports.SphereGeometry = SphereGeometry;
46028 exports.SphereBufferGeometry = SphereBufferGeometry;
46029 exports.RingGeometry = RingGeometry;
46030 exports.RingBufferGeometry = RingBufferGeometry;
46031 exports.PlaneGeometry = PlaneGeometry;
46032 exports.PlaneBufferGeometry = PlaneBufferGeometry;
46033 exports.LatheGeometry = LatheGeometry;
46034 exports.LatheBufferGeometry = LatheBufferGeometry;
46035 exports.ShapeGeometry = ShapeGeometry;
46036 exports.ShapeBufferGeometry = ShapeBufferGeometry;
46037 exports.ExtrudeGeometry = ExtrudeGeometry;
46038 exports.ExtrudeBufferGeometry = ExtrudeBufferGeometry;
46039 exports.EdgesGeometry = EdgesGeometry;
46040 exports.ConeGeometry = ConeGeometry;
46041 exports.ConeBufferGeometry = ConeBufferGeometry;
46042 exports.CylinderGeometry = CylinderGeometry;
46043 exports.CylinderBufferGeometry = CylinderBufferGeometry;
46044 exports.CircleGeometry = CircleGeometry;
46045 exports.CircleBufferGeometry = CircleBufferGeometry;
46046 exports.BoxGeometry = BoxGeometry;
46047 exports.BoxBufferGeometry = BoxBufferGeometry;
46048 exports.ShadowMaterial = ShadowMaterial;
46049 exports.SpriteMaterial = SpriteMaterial;
46050 exports.RawShaderMaterial = RawShaderMaterial;
46051 exports.ShaderMaterial = ShaderMaterial;
46052 exports.PointsMaterial = PointsMaterial;
46053 exports.MeshPhysicalMaterial = MeshPhysicalMaterial;
46054 exports.MeshStandardMaterial = MeshStandardMaterial;
46055 exports.MeshPhongMaterial = MeshPhongMaterial;
46056 exports.MeshToonMaterial = MeshToonMaterial;
46057 exports.MeshNormalMaterial = MeshNormalMaterial;
46058 exports.MeshLambertMaterial = MeshLambertMaterial;
46059 exports.MeshDepthMaterial = MeshDepthMaterial;
46060 exports.MeshDistanceMaterial = MeshDistanceMaterial;
46061 exports.MeshBasicMaterial = MeshBasicMaterial;
46062 exports.LineDashedMaterial = LineDashedMaterial;
46063 exports.LineBasicMaterial = LineBasicMaterial;
46064 exports.Material = Material;
46065 exports.Float64BufferAttribute = Float64BufferAttribute;
46066 exports.Float32BufferAttribute = Float32BufferAttribute;
46067 exports.Uint32BufferAttribute = Uint32BufferAttribute;
46068 exports.Int32BufferAttribute = Int32BufferAttribute;
46069 exports.Uint16BufferAttribute = Uint16BufferAttribute;
46070 exports.Int16BufferAttribute = Int16BufferAttribute;
46071 exports.Uint8ClampedBufferAttribute = Uint8ClampedBufferAttribute;
46072 exports.Uint8BufferAttribute = Uint8BufferAttribute;
46073 exports.Int8BufferAttribute = Int8BufferAttribute;
46074 exports.BufferAttribute = BufferAttribute;
46075 exports.ArcCurve = ArcCurve;
46076 exports.CatmullRomCurve3 = CatmullRomCurve3;
46077 exports.CubicBezierCurve = CubicBezierCurve;
46078 exports.CubicBezierCurve3 = CubicBezierCurve3;
46079 exports.EllipseCurve = EllipseCurve;
46080 exports.LineCurve = LineCurve;
46081 exports.LineCurve3 = LineCurve3;
46082 exports.QuadraticBezierCurve = QuadraticBezierCurve;
46083 exports.QuadraticBezierCurve3 = QuadraticBezierCurve3;
46084 exports.SplineCurve = SplineCurve;
46085 exports.REVISION = REVISION;
46086 exports.MOUSE = MOUSE;
46087 exports.CullFaceNone = CullFaceNone;
46088 exports.CullFaceBack = CullFaceBack;
46089 exports.CullFaceFront = CullFaceFront;
46090 exports.CullFaceFrontBack = CullFaceFrontBack;
46091 exports.FrontFaceDirectionCW = FrontFaceDirectionCW;
46092 exports.FrontFaceDirectionCCW = FrontFaceDirectionCCW;
46093 exports.BasicShadowMap = BasicShadowMap;
46094 exports.PCFShadowMap = PCFShadowMap;
46095 exports.PCFSoftShadowMap = PCFSoftShadowMap;
46096 exports.FrontSide = FrontSide;
46097 exports.BackSide = BackSide;
46098 exports.DoubleSide = DoubleSide;
46099 exports.FlatShading = FlatShading;
46100 exports.SmoothShading = SmoothShading;
46101 exports.NoColors = NoColors;
46102 exports.FaceColors = FaceColors;
46103 exports.VertexColors = VertexColors;
46104 exports.NoBlending = NoBlending;
46105 exports.NormalBlending = NormalBlending;
46106 exports.AdditiveBlending = AdditiveBlending;
46107 exports.SubtractiveBlending = SubtractiveBlending;
46108 exports.MultiplyBlending = MultiplyBlending;
46109 exports.CustomBlending = CustomBlending;
46110 exports.AddEquation = AddEquation;
46111 exports.SubtractEquation = SubtractEquation;
46112 exports.ReverseSubtractEquation = ReverseSubtractEquation;
46113 exports.MinEquation = MinEquation;
46114 exports.MaxEquation = MaxEquation;
46115 exports.ZeroFactor = ZeroFactor;
46116 exports.OneFactor = OneFactor;
46117 exports.SrcColorFactor = SrcColorFactor;
46118 exports.OneMinusSrcColorFactor = OneMinusSrcColorFactor;
46119 exports.SrcAlphaFactor = SrcAlphaFactor;
46120 exports.OneMinusSrcAlphaFactor = OneMinusSrcAlphaFactor;
46121 exports.DstAlphaFactor = DstAlphaFactor;
46122 exports.OneMinusDstAlphaFactor = OneMinusDstAlphaFactor;
46123 exports.DstColorFactor = DstColorFactor;
46124 exports.OneMinusDstColorFactor = OneMinusDstColorFactor;
46125 exports.SrcAlphaSaturateFactor = SrcAlphaSaturateFactor;
46126 exports.NeverDepth = NeverDepth;
46127 exports.AlwaysDepth = AlwaysDepth;
46128 exports.LessDepth = LessDepth;
46129 exports.LessEqualDepth = LessEqualDepth;
46130 exports.EqualDepth = EqualDepth;
46131 exports.GreaterEqualDepth = GreaterEqualDepth;
46132 exports.GreaterDepth = GreaterDepth;
46133 exports.NotEqualDepth = NotEqualDepth;
46134 exports.MultiplyOperation = MultiplyOperation;
46135 exports.MixOperation = MixOperation;
46136 exports.AddOperation = AddOperation;
46137 exports.NoToneMapping = NoToneMapping;
46138 exports.LinearToneMapping = LinearToneMapping;
46139 exports.ReinhardToneMapping = ReinhardToneMapping;
46140 exports.Uncharted2ToneMapping = Uncharted2ToneMapping;
46141 exports.CineonToneMapping = CineonToneMapping;
46142 exports.UVMapping = UVMapping;
46143 exports.CubeReflectionMapping = CubeReflectionMapping;
46144 exports.CubeRefractionMapping = CubeRefractionMapping;
46145 exports.EquirectangularReflectionMapping = EquirectangularReflectionMapping;
46146 exports.EquirectangularRefractionMapping = EquirectangularRefractionMapping;
46147 exports.SphericalReflectionMapping = SphericalReflectionMapping;
46148 exports.CubeUVReflectionMapping = CubeUVReflectionMapping;
46149 exports.CubeUVRefractionMapping = CubeUVRefractionMapping;
46150 exports.RepeatWrapping = RepeatWrapping;
46151 exports.ClampToEdgeWrapping = ClampToEdgeWrapping;
46152 exports.MirroredRepeatWrapping = MirroredRepeatWrapping;
46153 exports.NearestFilter = NearestFilter;
46154 exports.NearestMipMapNearestFilter = NearestMipMapNearestFilter;
46155 exports.NearestMipMapLinearFilter = NearestMipMapLinearFilter;
46156 exports.LinearFilter = LinearFilter;
46157 exports.LinearMipMapNearestFilter = LinearMipMapNearestFilter;
46158 exports.LinearMipMapLinearFilter = LinearMipMapLinearFilter;
46159 exports.UnsignedByteType = UnsignedByteType;
46160 exports.ByteType = ByteType;
46161 exports.ShortType = ShortType;
46162 exports.UnsignedShortType = UnsignedShortType;
46163 exports.IntType = IntType;
46164 exports.UnsignedIntType = UnsignedIntType;
46165 exports.FloatType = FloatType;
46166 exports.HalfFloatType = HalfFloatType;
46167 exports.UnsignedShort4444Type = UnsignedShort4444Type;
46168 exports.UnsignedShort5551Type = UnsignedShort5551Type;
46169 exports.UnsignedShort565Type = UnsignedShort565Type;
46170 exports.UnsignedInt248Type = UnsignedInt248Type;
46171 exports.AlphaFormat = AlphaFormat;
46172 exports.RGBFormat = RGBFormat;
46173 exports.RGBAFormat = RGBAFormat;
46174 exports.LuminanceFormat = LuminanceFormat;
46175 exports.LuminanceAlphaFormat = LuminanceAlphaFormat;
46176 exports.RGBEFormat = RGBEFormat;
46177 exports.DepthFormat = DepthFormat;
46178 exports.DepthStencilFormat = DepthStencilFormat;
46179 exports.RGB_S3TC_DXT1_Format = RGB_S3TC_DXT1_Format;
46180 exports.RGBA_S3TC_DXT1_Format = RGBA_S3TC_DXT1_Format;
46181 exports.RGBA_S3TC_DXT3_Format = RGBA_S3TC_DXT3_Format;
46182 exports.RGBA_S3TC_DXT5_Format = RGBA_S3TC_DXT5_Format;
46183 exports.RGB_PVRTC_4BPPV1_Format = RGB_PVRTC_4BPPV1_Format;
46184 exports.RGB_PVRTC_2BPPV1_Format = RGB_PVRTC_2BPPV1_Format;
46185 exports.RGBA_PVRTC_4BPPV1_Format = RGBA_PVRTC_4BPPV1_Format;
46186 exports.RGBA_PVRTC_2BPPV1_Format = RGBA_PVRTC_2BPPV1_Format;
46187 exports.RGB_ETC1_Format = RGB_ETC1_Format;
46188 exports.RGBA_ASTC_4x4_Format = RGBA_ASTC_4x4_Format;
46189 exports.RGBA_ASTC_5x4_Format = RGBA_ASTC_5x4_Format;
46190 exports.RGBA_ASTC_5x5_Format = RGBA_ASTC_5x5_Format;
46191 exports.RGBA_ASTC_6x5_Format = RGBA_ASTC_6x5_Format;
46192 exports.RGBA_ASTC_6x6_Format = RGBA_ASTC_6x6_Format;
46193 exports.RGBA_ASTC_8x5_Format = RGBA_ASTC_8x5_Format;
46194 exports.RGBA_ASTC_8x6_Format = RGBA_ASTC_8x6_Format;
46195 exports.RGBA_ASTC_8x8_Format = RGBA_ASTC_8x8_Format;
46196 exports.RGBA_ASTC_10x5_Format = RGBA_ASTC_10x5_Format;
46197 exports.RGBA_ASTC_10x6_Format = RGBA_ASTC_10x6_Format;
46198 exports.RGBA_ASTC_10x8_Format = RGBA_ASTC_10x8_Format;
46199 exports.RGBA_ASTC_10x10_Format = RGBA_ASTC_10x10_Format;
46200 exports.RGBA_ASTC_12x10_Format = RGBA_ASTC_12x10_Format;
46201 exports.RGBA_ASTC_12x12_Format = RGBA_ASTC_12x12_Format;
46202 exports.LoopOnce = LoopOnce;
46203 exports.LoopRepeat = LoopRepeat;
46204 exports.LoopPingPong = LoopPingPong;
46205 exports.InterpolateDiscrete = InterpolateDiscrete;
46206 exports.InterpolateLinear = InterpolateLinear;
46207 exports.InterpolateSmooth = InterpolateSmooth;
46208 exports.ZeroCurvatureEnding = ZeroCurvatureEnding;
46209 exports.ZeroSlopeEnding = ZeroSlopeEnding;
46210 exports.WrapAroundEnding = WrapAroundEnding;
46211 exports.TrianglesDrawMode = TrianglesDrawMode;
46212 exports.TriangleStripDrawMode = TriangleStripDrawMode;
46213 exports.TriangleFanDrawMode = TriangleFanDrawMode;
46214 exports.LinearEncoding = LinearEncoding;
46215 exports.sRGBEncoding = sRGBEncoding;
46216 exports.GammaEncoding = GammaEncoding;
46217 exports.RGBEEncoding = RGBEEncoding;
46218 exports.LogLuvEncoding = LogLuvEncoding;
46219 exports.RGBM7Encoding = RGBM7Encoding;
46220 exports.RGBM16Encoding = RGBM16Encoding;
46221 exports.RGBDEncoding = RGBDEncoding;
46222 exports.BasicDepthPacking = BasicDepthPacking;
46223 exports.RGBADepthPacking = RGBADepthPacking;
46224 exports.CubeGeometry = BoxGeometry;
46225 exports.Face4 = Face4;
46226 exports.LineStrip = LineStrip;
46227 exports.LinePieces = LinePieces;
46228 exports.MeshFaceMaterial = MeshFaceMaterial;
46229 exports.MultiMaterial = MultiMaterial;
46230 exports.PointCloud = PointCloud;
46231 exports.Particle = Particle;
46232 exports.ParticleSystem = ParticleSystem;
46233 exports.PointCloudMaterial = PointCloudMaterial;
46234 exports.ParticleBasicMaterial = ParticleBasicMaterial;
46235 exports.ParticleSystemMaterial = ParticleSystemMaterial;
46236 exports.Vertex = Vertex;
46237 exports.DynamicBufferAttribute = DynamicBufferAttribute;
46238 exports.Int8Attribute = Int8Attribute;
46239 exports.Uint8Attribute = Uint8Attribute;
46240 exports.Uint8ClampedAttribute = Uint8ClampedAttribute;
46241 exports.Int16Attribute = Int16Attribute;
46242 exports.Uint16Attribute = Uint16Attribute;
46243 exports.Int32Attribute = Int32Attribute;
46244 exports.Uint32Attribute = Uint32Attribute;
46245 exports.Float32Attribute = Float32Attribute;
46246 exports.Float64Attribute = Float64Attribute;
46247 exports.ClosedSplineCurve3 = ClosedSplineCurve3;
46248 exports.SplineCurve3 = SplineCurve3;
46249 exports.Spline = Spline;
46250 exports.AxisHelper = AxisHelper;
46251 exports.BoundingBoxHelper = BoundingBoxHelper;
46252 exports.EdgesHelper = EdgesHelper;
46253 exports.WireframeHelper = WireframeHelper;
46254 exports.XHRLoader = XHRLoader;
46255 exports.BinaryTextureLoader = BinaryTextureLoader;
46256 exports.GeometryUtils = GeometryUtils;
46257 exports.ImageUtils = ImageUtils;
46258 exports.Projector = Projector;
46259 exports.CanvasRenderer = CanvasRenderer;
46260 exports.SceneUtils = SceneUtils;
46261 exports.LensFlare = LensFlare;
46262
46263 Object.defineProperty(exports, '__esModule', { value: true });
46264
46265})));