otsdaq_utilities  v2_05_02_indev
three.js
1 (function (global, factory) {
2  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
3  typeof define === 'function' && define.amd ? define(['exports'], factory) :
4  (global = global || self, 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 
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 = '102';
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 ACESFilmicToneMapping = 5;
246 
247  var UVMapping = 300;
248  var CubeReflectionMapping = 301;
249  var CubeRefractionMapping = 302;
250  var EquirectangularReflectionMapping = 303;
251  var EquirectangularRefractionMapping = 304;
252  var SphericalReflectionMapping = 305;
253  var CubeUVReflectionMapping = 306;
254  var CubeUVRefractionMapping = 307;
255  var RepeatWrapping = 1000;
256  var ClampToEdgeWrapping = 1001;
257  var MirroredRepeatWrapping = 1002;
258  var NearestFilter = 1003;
259  var NearestMipMapNearestFilter = 1004;
260  var NearestMipMapLinearFilter = 1005;
261  var LinearFilter = 1006;
262  var LinearMipMapNearestFilter = 1007;
263  var LinearMipMapLinearFilter = 1008;
264  var UnsignedByteType = 1009;
265  var ByteType = 1010;
266  var ShortType = 1011;
267  var UnsignedShortType = 1012;
268  var IntType = 1013;
269  var UnsignedIntType = 1014;
270  var FloatType = 1015;
271  var HalfFloatType = 1016;
272  var UnsignedShort4444Type = 1017;
273  var UnsignedShort5551Type = 1018;
274  var UnsignedShort565Type = 1019;
275  var UnsignedInt248Type = 1020;
276  var AlphaFormat = 1021;
277  var RGBFormat = 1022;
278  var RGBAFormat = 1023;
279  var LuminanceFormat = 1024;
280  var LuminanceAlphaFormat = 1025;
281  var RGBEFormat = RGBAFormat;
282  var DepthFormat = 1026;
283  var DepthStencilFormat = 1027;
284  var RedFormat = 1028;
285  var RGB_S3TC_DXT1_Format = 33776;
286  var RGBA_S3TC_DXT1_Format = 33777;
287  var RGBA_S3TC_DXT3_Format = 33778;
288  var RGBA_S3TC_DXT5_Format = 33779;
289  var RGB_PVRTC_4BPPV1_Format = 35840;
290  var RGB_PVRTC_2BPPV1_Format = 35841;
291  var RGBA_PVRTC_4BPPV1_Format = 35842;
292  var RGBA_PVRTC_2BPPV1_Format = 35843;
293  var RGB_ETC1_Format = 36196;
294  var RGBA_ASTC_4x4_Format = 37808;
295  var RGBA_ASTC_5x4_Format = 37809;
296  var RGBA_ASTC_5x5_Format = 37810;
297  var RGBA_ASTC_6x5_Format = 37811;
298  var RGBA_ASTC_6x6_Format = 37812;
299  var RGBA_ASTC_8x5_Format = 37813;
300  var RGBA_ASTC_8x6_Format = 37814;
301  var RGBA_ASTC_8x8_Format = 37815;
302  var RGBA_ASTC_10x5_Format = 37816;
303  var RGBA_ASTC_10x6_Format = 37817;
304  var RGBA_ASTC_10x8_Format = 37818;
305  var RGBA_ASTC_10x10_Format = 37819;
306  var RGBA_ASTC_12x10_Format = 37820;
307  var RGBA_ASTC_12x12_Format = 37821;
308  var LoopOnce = 2200;
309  var LoopRepeat = 2201;
310  var LoopPingPong = 2202;
311  var InterpolateDiscrete = 2300;
312  var InterpolateLinear = 2301;
313  var InterpolateSmooth = 2302;
314  var ZeroCurvatureEnding = 2400;
315  var ZeroSlopeEnding = 2401;
316  var WrapAroundEnding = 2402;
317  var TrianglesDrawMode = 0;
318  var TriangleStripDrawMode = 1;
319  var TriangleFanDrawMode = 2;
320  var LinearEncoding = 3000;
321  var sRGBEncoding = 3001;
322  var GammaEncoding = 3007;
323  var RGBEEncoding = 3002;
324  var LogLuvEncoding = 3003;
325  var RGBM7Encoding = 3004;
326  var RGBM16Encoding = 3005;
327  var RGBDEncoding = 3006;
328  var BasicDepthPacking = 3200;
329  var RGBADepthPacking = 3201;
330  var TangentSpaceNormalMap = 0;
331  var ObjectSpaceNormalMap = 1;
332 
338  var _Math = {
339 
340  DEG2RAD: Math.PI / 180,
341  RAD2DEG: 180 / Math.PI,
342 
343  generateUUID: ( function () {
344 
345  // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136
346 
347  var lut = [];
348 
349  for ( var i = 0; i < 256; i ++ ) {
350 
351  lut[ i ] = ( i < 16 ? '0' : '' ) + ( i ).toString( 16 );
352 
353  }
354 
355  return function generateUUID() {
356 
357  var d0 = Math.random() * 0xffffffff | 0;
358  var d1 = Math.random() * 0xffffffff | 0;
359  var d2 = Math.random() * 0xffffffff | 0;
360  var d3 = Math.random() * 0xffffffff | 0;
361  var uuid = lut[ d0 & 0xff ] + lut[ d0 >> 8 & 0xff ] + lut[ d0 >> 16 & 0xff ] + lut[ d0 >> 24 & 0xff ] + '-' +
362  lut[ d1 & 0xff ] + lut[ d1 >> 8 & 0xff ] + '-' + lut[ d1 >> 16 & 0x0f | 0x40 ] + lut[ d1 >> 24 & 0xff ] + '-' +
363  lut[ d2 & 0x3f | 0x80 ] + lut[ d2 >> 8 & 0xff ] + '-' + lut[ d2 >> 16 & 0xff ] + lut[ d2 >> 24 & 0xff ] +
364  lut[ d3 & 0xff ] + lut[ d3 >> 8 & 0xff ] + lut[ d3 >> 16 & 0xff ] + lut[ d3 >> 24 & 0xff ];
365 
366  // .toUpperCase() here flattens concatenated strings to save heap memory space.
367  return uuid.toUpperCase();
368 
369  };
370 
371  } )(),
372 
373  clamp: function ( value, min, max ) {
374 
375  return Math.max( min, Math.min( max, value ) );
376 
377  },
378 
379  // compute euclidian modulo of m % n
380  // https://en.wikipedia.org/wiki/Modulo_operation
381 
382  euclideanModulo: function ( n, m ) {
383 
384  return ( ( n % m ) + m ) % m;
385 
386  },
387 
388  // Linear mapping from range <a1, a2> to range <b1, b2>
389 
390  mapLinear: function ( x, a1, a2, b1, b2 ) {
391 
392  return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 );
393 
394  },
395 
396  // https://en.wikipedia.org/wiki/Linear_interpolation
397 
398  lerp: function ( x, y, t ) {
399 
400  return ( 1 - t ) * x + t * y;
401 
402  },
403 
404  // http://en.wikipedia.org/wiki/Smoothstep
405 
406  smoothstep: function ( x, min, max ) {
407 
408  if ( x <= min ) return 0;
409  if ( x >= max ) return 1;
410 
411  x = ( x - min ) / ( max - min );
412 
413  return x * x * ( 3 - 2 * x );
414 
415  },
416 
417  smootherstep: function ( x, min, max ) {
418 
419  if ( x <= min ) return 0;
420  if ( x >= max ) return 1;
421 
422  x = ( x - min ) / ( max - min );
423 
424  return x * x * x * ( x * ( x * 6 - 15 ) + 10 );
425 
426  },
427 
428  // Random integer from <low, high> interval
429 
430  randInt: function ( low, high ) {
431 
432  return low + Math.floor( Math.random() * ( high - low + 1 ) );
433 
434  },
435 
436  // Random float from <low, high> interval
437 
438  randFloat: function ( low, high ) {
439 
440  return low + Math.random() * ( high - low );
441 
442  },
443 
444  // Random float from <-range/2, range/2> interval
445 
446  randFloatSpread: function ( range ) {
447 
448  return range * ( 0.5 - Math.random() );
449 
450  },
451 
452  degToRad: function ( degrees ) {
453 
454  return degrees * _Math.DEG2RAD;
455 
456  },
457 
458  radToDeg: function ( radians ) {
459 
460  return radians * _Math.RAD2DEG;
461 
462  },
463 
464  isPowerOfTwo: function ( value ) {
465 
466  return ( value & ( value - 1 ) ) === 0 && value !== 0;
467 
468  },
469 
470  ceilPowerOfTwo: function ( value ) {
471 
472  return Math.pow( 2, Math.ceil( Math.log( value ) / Math.LN2 ) );
473 
474  },
475 
476  floorPowerOfTwo: function ( value ) {
477 
478  return Math.pow( 2, Math.floor( Math.log( value ) / Math.LN2 ) );
479 
480  }
481 
482  };
483 
491  function Vector2( x, y ) {
492 
493  this.x = x || 0;
494  this.y = y || 0;
495 
496  }
497 
498  Object.defineProperties( Vector2.prototype, {
499 
500  "width": {
501 
502  get: function () {
503 
504  return this.x;
505 
506  },
507 
508  set: function ( value ) {
509 
510  this.x = value;
511 
512  }
513 
514  },
515 
516  "height": {
517 
518  get: function () {
519 
520  return this.y;
521 
522  },
523 
524  set: function ( value ) {
525 
526  this.y = value;
527 
528  }
529 
530  }
531 
532  } );
533 
534  Object.assign( Vector2.prototype, {
535 
536  isVector2: true,
537 
538  set: function ( x, y ) {
539 
540  this.x = x;
541  this.y = y;
542 
543  return this;
544 
545  },
546 
547  setScalar: function ( scalar ) {
548 
549  this.x = scalar;
550  this.y = scalar;
551 
552  return this;
553 
554  },
555 
556  setX: function ( x ) {
557 
558  this.x = x;
559 
560  return this;
561 
562  },
563 
564  setY: function ( y ) {
565 
566  this.y = y;
567 
568  return this;
569 
570  },
571 
572  setComponent: function ( index, value ) {
573 
574  switch ( index ) {
575 
576  case 0: this.x = value; break;
577  case 1: this.y = value; break;
578  default: throw new Error( 'index is out of range: ' + index );
579 
580  }
581 
582  return this;
583 
584  },
585 
586  getComponent: function ( index ) {
587 
588  switch ( index ) {
589 
590  case 0: return this.x;
591  case 1: return this.y;
592  default: throw new Error( 'index is out of range: ' + index );
593 
594  }
595 
596  },
597 
598  clone: function () {
599 
600  return new this.constructor( this.x, this.y );
601 
602  },
603 
604  copy: function ( v ) {
605 
606  this.x = v.x;
607  this.y = v.y;
608 
609  return this;
610 
611  },
612 
613  add: function ( v, w ) {
614 
615  if ( w !== undefined ) {
616 
617  console.warn( 'THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
618  return this.addVectors( v, w );
619 
620  }
621 
622  this.x += v.x;
623  this.y += v.y;
624 
625  return this;
626 
627  },
628 
629  addScalar: function ( s ) {
630 
631  this.x += s;
632  this.y += s;
633 
634  return this;
635 
636  },
637 
638  addVectors: function ( a, b ) {
639 
640  this.x = a.x + b.x;
641  this.y = a.y + b.y;
642 
643  return this;
644 
645  },
646 
647  addScaledVector: function ( v, s ) {
648 
649  this.x += v.x * s;
650  this.y += v.y * s;
651 
652  return this;
653 
654  },
655 
656  sub: function ( v, w ) {
657 
658  if ( w !== undefined ) {
659 
660  console.warn( 'THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
661  return this.subVectors( v, w );
662 
663  }
664 
665  this.x -= v.x;
666  this.y -= v.y;
667 
668  return this;
669 
670  },
671 
672  subScalar: function ( s ) {
673 
674  this.x -= s;
675  this.y -= s;
676 
677  return this;
678 
679  },
680 
681  subVectors: function ( a, b ) {
682 
683  this.x = a.x - b.x;
684  this.y = a.y - b.y;
685 
686  return this;
687 
688  },
689 
690  multiply: function ( v ) {
691 
692  this.x *= v.x;
693  this.y *= v.y;
694 
695  return this;
696 
697  },
698 
699  multiplyScalar: function ( scalar ) {
700 
701  this.x *= scalar;
702  this.y *= scalar;
703 
704  return this;
705 
706  },
707 
708  divide: function ( v ) {
709 
710  this.x /= v.x;
711  this.y /= v.y;
712 
713  return this;
714 
715  },
716 
717  divideScalar: function ( scalar ) {
718 
719  return this.multiplyScalar( 1 / scalar );
720 
721  },
722 
723  applyMatrix3: function ( m ) {
724 
725  var x = this.x, y = this.y;
726  var e = m.elements;
727 
728  this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ];
729  this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ];
730 
731  return this;
732 
733  },
734 
735  min: function ( v ) {
736 
737  this.x = Math.min( this.x, v.x );
738  this.y = Math.min( this.y, v.y );
739 
740  return this;
741 
742  },
743 
744  max: function ( v ) {
745 
746  this.x = Math.max( this.x, v.x );
747  this.y = Math.max( this.y, v.y );
748 
749  return this;
750 
751  },
752 
753  clamp: function ( min, max ) {
754 
755  // assumes min < max, componentwise
756 
757  this.x = Math.max( min.x, Math.min( max.x, this.x ) );
758  this.y = Math.max( min.y, Math.min( max.y, this.y ) );
759 
760  return this;
761 
762  },
763 
764  clampScalar: function () {
765 
766  var min = new Vector2();
767  var max = new Vector2();
768 
769  return function clampScalar( minVal, maxVal ) {
770 
771  min.set( minVal, minVal );
772  max.set( maxVal, maxVal );
773 
774  return this.clamp( min, max );
775 
776  };
777 
778  }(),
779 
780  clampLength: function ( min, max ) {
781 
782  var length = this.length();
783 
784  return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
785 
786  },
787 
788  floor: function () {
789 
790  this.x = Math.floor( this.x );
791  this.y = Math.floor( this.y );
792 
793  return this;
794 
795  },
796 
797  ceil: function () {
798 
799  this.x = Math.ceil( this.x );
800  this.y = Math.ceil( this.y );
801 
802  return this;
803 
804  },
805 
806  round: function () {
807 
808  this.x = Math.round( this.x );
809  this.y = Math.round( this.y );
810 
811  return this;
812 
813  },
814 
815  roundToZero: function () {
816 
817  this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
818  this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
819 
820  return this;
821 
822  },
823 
824  negate: function () {
825 
826  this.x = - this.x;
827  this.y = - this.y;
828 
829  return this;
830 
831  },
832 
833  dot: function ( v ) {
834 
835  return this.x * v.x + this.y * v.y;
836 
837  },
838 
839  cross: function ( v ) {
840 
841  return this.x * v.y - this.y * v.x;
842 
843  },
844 
845  lengthSq: function () {
846 
847  return this.x * this.x + this.y * this.y;
848 
849  },
850 
851  length: function () {
852 
853  return Math.sqrt( this.x * this.x + this.y * this.y );
854 
855  },
856 
857  manhattanLength: function () {
858 
859  return Math.abs( this.x ) + Math.abs( this.y );
860 
861  },
862 
863  normalize: function () {
864 
865  return this.divideScalar( this.length() || 1 );
866 
867  },
868 
869  angle: function () {
870 
871  // computes the angle in radians with respect to the positive x-axis
872 
873  var angle = Math.atan2( this.y, this.x );
874 
875  if ( angle < 0 ) angle += 2 * Math.PI;
876 
877  return angle;
878 
879  },
880 
881  distanceTo: function ( v ) {
882 
883  return Math.sqrt( this.distanceToSquared( v ) );
884 
885  },
886 
887  distanceToSquared: function ( v ) {
888 
889  var dx = this.x - v.x, dy = this.y - v.y;
890  return dx * dx + dy * dy;
891 
892  },
893 
894  manhattanDistanceTo: function ( v ) {
895 
896  return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y );
897 
898  },
899 
900  setLength: function ( length ) {
901 
902  return this.normalize().multiplyScalar( length );
903 
904  },
905 
906  lerp: function ( v, alpha ) {
907 
908  this.x += ( v.x - this.x ) * alpha;
909  this.y += ( v.y - this.y ) * alpha;
910 
911  return this;
912 
913  },
914 
915  lerpVectors: function ( v1, v2, alpha ) {
916 
917  return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );
918 
919  },
920 
921  equals: function ( v ) {
922 
923  return ( ( v.x === this.x ) && ( v.y === this.y ) );
924 
925  },
926 
927  fromArray: function ( array, offset ) {
928 
929  if ( offset === undefined ) offset = 0;
930 
931  this.x = array[ offset ];
932  this.y = array[ offset + 1 ];
933 
934  return this;
935 
936  },
937 
938  toArray: function ( array, offset ) {
939 
940  if ( array === undefined ) array = [];
941  if ( offset === undefined ) offset = 0;
942 
943  array[ offset ] = this.x;
944  array[ offset + 1 ] = this.y;
945 
946  return array;
947 
948  },
949 
950  fromBufferAttribute: function ( attribute, index, offset ) {
951 
952  if ( offset !== undefined ) {
953 
954  console.warn( 'THREE.Vector2: offset has been removed from .fromBufferAttribute().' );
955 
956  }
957 
958  this.x = attribute.getX( index );
959  this.y = attribute.getY( index );
960 
961  return this;
962 
963  },
964 
965  rotateAround: function ( center, angle ) {
966 
967  var c = Math.cos( angle ), s = Math.sin( angle );
968 
969  var x = this.x - center.x;
970  var y = this.y - center.y;
971 
972  this.x = x * c - y * s + center.x;
973  this.y = x * s + y * c + center.y;
974 
975  return this;
976 
977  }
978 
979  } );
980 
994  function Matrix4() {
995 
996  this.elements = [
997 
998  1, 0, 0, 0,
999  0, 1, 0, 0,
1000  0, 0, 1, 0,
1001  0, 0, 0, 1
1002 
1003  ];
1004 
1005  if ( arguments.length > 0 ) {
1006 
1007  console.error( 'THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.' );
1008 
1009  }
1010 
1011  }
1012 
1013  Object.assign( Matrix4.prototype, {
1014 
1015  isMatrix4: true,
1016 
1017  set: function ( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
1018 
1019  var te = this.elements;
1020 
1021  te[ 0 ] = n11; te[ 4 ] = n12; te[ 8 ] = n13; te[ 12 ] = n14;
1022  te[ 1 ] = n21; te[ 5 ] = n22; te[ 9 ] = n23; te[ 13 ] = n24;
1023  te[ 2 ] = n31; te[ 6 ] = n32; te[ 10 ] = n33; te[ 14 ] = n34;
1024  te[ 3 ] = n41; te[ 7 ] = n42; te[ 11 ] = n43; te[ 15 ] = n44;
1025 
1026  return this;
1027 
1028  },
1029 
1030  identity: function () {
1031 
1032  this.set(
1033 
1034  1, 0, 0, 0,
1035  0, 1, 0, 0,
1036  0, 0, 1, 0,
1037  0, 0, 0, 1
1038 
1039  );
1040 
1041  return this;
1042 
1043  },
1044 
1045  clone: function () {
1046 
1047  return new Matrix4().fromArray( this.elements );
1048 
1049  },
1050 
1051  copy: function ( m ) {
1052 
1053  var te = this.elements;
1054  var me = m.elements;
1055 
1056  te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ]; te[ 3 ] = me[ 3 ];
1057  te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ]; te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ];
1058  te[ 8 ] = me[ 8 ]; te[ 9 ] = me[ 9 ]; te[ 10 ] = me[ 10 ]; te[ 11 ] = me[ 11 ];
1059  te[ 12 ] = me[ 12 ]; te[ 13 ] = me[ 13 ]; te[ 14 ] = me[ 14 ]; te[ 15 ] = me[ 15 ];
1060 
1061  return this;
1062 
1063  },
1064 
1065  copyPosition: function ( m ) {
1066 
1067  var te = this.elements, me = m.elements;
1068 
1069  te[ 12 ] = me[ 12 ];
1070  te[ 13 ] = me[ 13 ];
1071  te[ 14 ] = me[ 14 ];
1072 
1073  return this;
1074 
1075  },
1076 
1077  extractBasis: function ( xAxis, yAxis, zAxis ) {
1078 
1079  xAxis.setFromMatrixColumn( this, 0 );
1080  yAxis.setFromMatrixColumn( this, 1 );
1081  zAxis.setFromMatrixColumn( this, 2 );
1082 
1083  return this;
1084 
1085  },
1086 
1087  makeBasis: function ( xAxis, yAxis, zAxis ) {
1088 
1089  this.set(
1090  xAxis.x, yAxis.x, zAxis.x, 0,
1091  xAxis.y, yAxis.y, zAxis.y, 0,
1092  xAxis.z, yAxis.z, zAxis.z, 0,
1093  0, 0, 0, 1
1094  );
1095 
1096  return this;
1097 
1098  },
1099 
1100  extractRotation: function () {
1101 
1102  var v1 = new Vector3();
1103 
1104  return function extractRotation( m ) {
1105 
1106  // this method does not support reflection matrices
1107 
1108  var te = this.elements;
1109  var me = m.elements;
1110 
1111  var scaleX = 1 / v1.setFromMatrixColumn( m, 0 ).length();
1112  var scaleY = 1 / v1.setFromMatrixColumn( m, 1 ).length();
1113  var scaleZ = 1 / v1.setFromMatrixColumn( m, 2 ).length();
1114 
1115  te[ 0 ] = me[ 0 ] * scaleX;
1116  te[ 1 ] = me[ 1 ] * scaleX;
1117  te[ 2 ] = me[ 2 ] * scaleX;
1118  te[ 3 ] = 0;
1119 
1120  te[ 4 ] = me[ 4 ] * scaleY;
1121  te[ 5 ] = me[ 5 ] * scaleY;
1122  te[ 6 ] = me[ 6 ] * scaleY;
1123  te[ 7 ] = 0;
1124 
1125  te[ 8 ] = me[ 8 ] * scaleZ;
1126  te[ 9 ] = me[ 9 ] * scaleZ;
1127  te[ 10 ] = me[ 10 ] * scaleZ;
1128  te[ 11 ] = 0;
1129 
1130  te[ 12 ] = 0;
1131  te[ 13 ] = 0;
1132  te[ 14 ] = 0;
1133  te[ 15 ] = 1;
1134 
1135  return this;
1136 
1137  };
1138 
1139  }(),
1140 
1141  makeRotationFromEuler: function ( euler ) {
1142 
1143  if ( ! ( euler && euler.isEuler ) ) {
1144 
1145  console.error( 'THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.' );
1146 
1147  }
1148 
1149  var te = this.elements;
1150 
1151  var x = euler.x, y = euler.y, z = euler.z;
1152  var a = Math.cos( x ), b = Math.sin( x );
1153  var c = Math.cos( y ), d = Math.sin( y );
1154  var e = Math.cos( z ), f = Math.sin( z );
1155 
1156  if ( euler.order === 'XYZ' ) {
1157 
1158  var ae = a * e, af = a * f, be = b * e, bf = b * f;
1159 
1160  te[ 0 ] = c * e;
1161  te[ 4 ] = - c * f;
1162  te[ 8 ] = d;
1163 
1164  te[ 1 ] = af + be * d;
1165  te[ 5 ] = ae - bf * d;
1166  te[ 9 ] = - b * c;
1167 
1168  te[ 2 ] = bf - ae * d;
1169  te[ 6 ] = be + af * d;
1170  te[ 10 ] = a * c;
1171 
1172  } else if ( euler.order === 'YXZ' ) {
1173 
1174  var ce = c * e, cf = c * f, de = d * e, df = d * f;
1175 
1176  te[ 0 ] = ce + df * b;
1177  te[ 4 ] = de * b - cf;
1178  te[ 8 ] = a * d;
1179 
1180  te[ 1 ] = a * f;
1181  te[ 5 ] = a * e;
1182  te[ 9 ] = - b;
1183 
1184  te[ 2 ] = cf * b - de;
1185  te[ 6 ] = df + ce * b;
1186  te[ 10 ] = a * c;
1187 
1188  } else if ( euler.order === 'ZXY' ) {
1189 
1190  var ce = c * e, cf = c * f, de = d * e, df = d * f;
1191 
1192  te[ 0 ] = ce - df * b;
1193  te[ 4 ] = - a * f;
1194  te[ 8 ] = de + cf * b;
1195 
1196  te[ 1 ] = cf + de * b;
1197  te[ 5 ] = a * e;
1198  te[ 9 ] = df - ce * b;
1199 
1200  te[ 2 ] = - a * d;
1201  te[ 6 ] = b;
1202  te[ 10 ] = a * c;
1203 
1204  } else if ( euler.order === 'ZYX' ) {
1205 
1206  var ae = a * e, af = a * f, be = b * e, bf = b * f;
1207 
1208  te[ 0 ] = c * e;
1209  te[ 4 ] = be * d - af;
1210  te[ 8 ] = ae * d + bf;
1211 
1212  te[ 1 ] = c * f;
1213  te[ 5 ] = bf * d + ae;
1214  te[ 9 ] = af * d - be;
1215 
1216  te[ 2 ] = - d;
1217  te[ 6 ] = b * c;
1218  te[ 10 ] = a * c;
1219 
1220  } else if ( euler.order === 'YZX' ) {
1221 
1222  var ac = a * c, ad = a * d, bc = b * c, bd = b * d;
1223 
1224  te[ 0 ] = c * e;
1225  te[ 4 ] = bd - ac * f;
1226  te[ 8 ] = bc * f + ad;
1227 
1228  te[ 1 ] = f;
1229  te[ 5 ] = a * e;
1230  te[ 9 ] = - b * e;
1231 
1232  te[ 2 ] = - d * e;
1233  te[ 6 ] = ad * f + bc;
1234  te[ 10 ] = ac - bd * f;
1235 
1236  } else if ( euler.order === 'XZY' ) {
1237 
1238  var ac = a * c, ad = a * d, bc = b * c, bd = b * d;
1239 
1240  te[ 0 ] = c * e;
1241  te[ 4 ] = - f;
1242  te[ 8 ] = d * e;
1243 
1244  te[ 1 ] = ac * f + bd;
1245  te[ 5 ] = a * e;
1246  te[ 9 ] = ad * f - bc;
1247 
1248  te[ 2 ] = bc * f - ad;
1249  te[ 6 ] = b * e;
1250  te[ 10 ] = bd * f + ac;
1251 
1252  }
1253 
1254  // bottom row
1255  te[ 3 ] = 0;
1256  te[ 7 ] = 0;
1257  te[ 11 ] = 0;
1258 
1259  // last column
1260  te[ 12 ] = 0;
1261  te[ 13 ] = 0;
1262  te[ 14 ] = 0;
1263  te[ 15 ] = 1;
1264 
1265  return this;
1266 
1267  },
1268 
1269  makeRotationFromQuaternion: function () {
1270 
1271  var zero = new Vector3( 0, 0, 0 );
1272  var one = new Vector3( 1, 1, 1 );
1273 
1274  return function makeRotationFromQuaternion( q ) {
1275 
1276  return this.compose( zero, q, one );
1277 
1278  };
1279 
1280  }(),
1281 
1282  lookAt: function () {
1283 
1284  var x = new Vector3();
1285  var y = new Vector3();
1286  var z = new Vector3();
1287 
1288  return function lookAt( eye, target, up ) {
1289 
1290  var te = this.elements;
1291 
1292  z.subVectors( eye, target );
1293 
1294  if ( z.lengthSq() === 0 ) {
1295 
1296  // eye and target are in the same position
1297 
1298  z.z = 1;
1299 
1300  }
1301 
1302  z.normalize();
1303  x.crossVectors( up, z );
1304 
1305  if ( x.lengthSq() === 0 ) {
1306 
1307  // up and z are parallel
1308 
1309  if ( Math.abs( up.z ) === 1 ) {
1310 
1311  z.x += 0.0001;
1312 
1313  } else {
1314 
1315  z.z += 0.0001;
1316 
1317  }
1318 
1319  z.normalize();
1320  x.crossVectors( up, z );
1321 
1322  }
1323 
1324  x.normalize();
1325  y.crossVectors( z, x );
1326 
1327  te[ 0 ] = x.x; te[ 4 ] = y.x; te[ 8 ] = z.x;
1328  te[ 1 ] = x.y; te[ 5 ] = y.y; te[ 9 ] = z.y;
1329  te[ 2 ] = x.z; te[ 6 ] = y.z; te[ 10 ] = z.z;
1330 
1331  return this;
1332 
1333  };
1334 
1335  }(),
1336 
1337  multiply: function ( m, n ) {
1338 
1339  if ( n !== undefined ) {
1340 
1341  console.warn( 'THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead.' );
1342  return this.multiplyMatrices( m, n );
1343 
1344  }
1345 
1346  return this.multiplyMatrices( this, m );
1347 
1348  },
1349 
1350  premultiply: function ( m ) {
1351 
1352  return this.multiplyMatrices( m, this );
1353 
1354  },
1355 
1356  multiplyMatrices: function ( a, b ) {
1357 
1358  var ae = a.elements;
1359  var be = b.elements;
1360  var te = this.elements;
1361 
1362  var a11 = ae[ 0 ], a12 = ae[ 4 ], a13 = ae[ 8 ], a14 = ae[ 12 ];
1363  var a21 = ae[ 1 ], a22 = ae[ 5 ], a23 = ae[ 9 ], a24 = ae[ 13 ];
1364  var a31 = ae[ 2 ], a32 = ae[ 6 ], a33 = ae[ 10 ], a34 = ae[ 14 ];
1365  var a41 = ae[ 3 ], a42 = ae[ 7 ], a43 = ae[ 11 ], a44 = ae[ 15 ];
1366 
1367  var b11 = be[ 0 ], b12 = be[ 4 ], b13 = be[ 8 ], b14 = be[ 12 ];
1368  var b21 = be[ 1 ], b22 = be[ 5 ], b23 = be[ 9 ], b24 = be[ 13 ];
1369  var b31 = be[ 2 ], b32 = be[ 6 ], b33 = be[ 10 ], b34 = be[ 14 ];
1370  var b41 = be[ 3 ], b42 = be[ 7 ], b43 = be[ 11 ], b44 = be[ 15 ];
1371 
1372  te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
1373  te[ 4 ] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
1374  te[ 8 ] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
1375  te[ 12 ] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
1376 
1377  te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
1378  te[ 5 ] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
1379  te[ 9 ] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
1380  te[ 13 ] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
1381 
1382  te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
1383  te[ 6 ] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
1384  te[ 10 ] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
1385  te[ 14 ] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
1386 
1387  te[ 3 ] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
1388  te[ 7 ] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
1389  te[ 11 ] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
1390  te[ 15 ] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
1391 
1392  return this;
1393 
1394  },
1395 
1396  multiplyScalar: function ( s ) {
1397 
1398  var te = this.elements;
1399 
1400  te[ 0 ] *= s; te[ 4 ] *= s; te[ 8 ] *= s; te[ 12 ] *= s;
1401  te[ 1 ] *= s; te[ 5 ] *= s; te[ 9 ] *= s; te[ 13 ] *= s;
1402  te[ 2 ] *= s; te[ 6 ] *= s; te[ 10 ] *= s; te[ 14 ] *= s;
1403  te[ 3 ] *= s; te[ 7 ] *= s; te[ 11 ] *= s; te[ 15 ] *= s;
1404 
1405  return this;
1406 
1407  },
1408 
1409  applyToBufferAttribute: function () {
1410 
1411  var v1 = new Vector3();
1412 
1413  return function applyToBufferAttribute( attribute ) {
1414 
1415  for ( var i = 0, l = attribute.count; i < l; i ++ ) {
1416 
1417  v1.x = attribute.getX( i );
1418  v1.y = attribute.getY( i );
1419  v1.z = attribute.getZ( i );
1420 
1421  v1.applyMatrix4( this );
1422 
1423  attribute.setXYZ( i, v1.x, v1.y, v1.z );
1424 
1425  }
1426 
1427  return attribute;
1428 
1429  };
1430 
1431  }(),
1432 
1433  determinant: function () {
1434 
1435  var te = this.elements;
1436 
1437  var n11 = te[ 0 ], n12 = te[ 4 ], n13 = te[ 8 ], n14 = te[ 12 ];
1438  var n21 = te[ 1 ], n22 = te[ 5 ], n23 = te[ 9 ], n24 = te[ 13 ];
1439  var n31 = te[ 2 ], n32 = te[ 6 ], n33 = te[ 10 ], n34 = te[ 14 ];
1440  var n41 = te[ 3 ], n42 = te[ 7 ], n43 = te[ 11 ], n44 = te[ 15 ];
1441 
1442  //TODO: make this more efficient
1443  //( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm )
1444 
1445  return (
1446  n41 * (
1447  + n14 * n23 * n32
1448  - n13 * n24 * n32
1449  - n14 * n22 * n33
1450  + n12 * n24 * n33
1451  + n13 * n22 * n34
1452  - n12 * n23 * n34
1453  ) +
1454  n42 * (
1455  + n11 * n23 * n34
1456  - n11 * n24 * n33
1457  + n14 * n21 * n33
1458  - n13 * n21 * n34
1459  + n13 * n24 * n31
1460  - n14 * n23 * n31
1461  ) +
1462  n43 * (
1463  + n11 * n24 * n32
1464  - n11 * n22 * n34
1465  - n14 * n21 * n32
1466  + n12 * n21 * n34
1467  + n14 * n22 * n31
1468  - n12 * n24 * n31
1469  ) +
1470  n44 * (
1471  - n13 * n22 * n31
1472  - n11 * n23 * n32
1473  + n11 * n22 * n33
1474  + n13 * n21 * n32
1475  - n12 * n21 * n33
1476  + n12 * n23 * n31
1477  )
1478 
1479  );
1480 
1481  },
1482 
1483  transpose: function () {
1484 
1485  var te = this.elements;
1486  var tmp;
1487 
1488  tmp = te[ 1 ]; te[ 1 ] = te[ 4 ]; te[ 4 ] = tmp;
1489  tmp = te[ 2 ]; te[ 2 ] = te[ 8 ]; te[ 8 ] = tmp;
1490  tmp = te[ 6 ]; te[ 6 ] = te[ 9 ]; te[ 9 ] = tmp;
1491 
1492  tmp = te[ 3 ]; te[ 3 ] = te[ 12 ]; te[ 12 ] = tmp;
1493  tmp = te[ 7 ]; te[ 7 ] = te[ 13 ]; te[ 13 ] = tmp;
1494  tmp = te[ 11 ]; te[ 11 ] = te[ 14 ]; te[ 14 ] = tmp;
1495 
1496  return this;
1497 
1498  },
1499 
1500  setPosition: function ( v ) {
1501 
1502  var te = this.elements;
1503 
1504  te[ 12 ] = v.x;
1505  te[ 13 ] = v.y;
1506  te[ 14 ] = v.z;
1507 
1508  return this;
1509 
1510  },
1511 
1512  getInverse: function ( m, throwOnDegenerate ) {
1513 
1514  // based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm
1515  var te = this.elements,
1516  me = m.elements,
1517 
1518  n11 = me[ 0 ], n21 = me[ 1 ], n31 = me[ 2 ], n41 = me[ 3 ],
1519  n12 = me[ 4 ], n22 = me[ 5 ], n32 = me[ 6 ], n42 = me[ 7 ],
1520  n13 = me[ 8 ], n23 = me[ 9 ], n33 = me[ 10 ], n43 = me[ 11 ],
1521  n14 = me[ 12 ], n24 = me[ 13 ], n34 = me[ 14 ], n44 = me[ 15 ],
1522 
1523  t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44,
1524  t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44,
1525  t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44,
1526  t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34;
1527 
1528  var det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14;
1529 
1530  if ( det === 0 ) {
1531 
1532  var msg = "THREE.Matrix4: .getInverse() can't invert matrix, determinant is 0";
1533 
1534  if ( throwOnDegenerate === true ) {
1535 
1536  throw new Error( msg );
1537 
1538  } else {
1539 
1540  console.warn( msg );
1541 
1542  }
1543 
1544  return this.identity();
1545 
1546  }
1547 
1548  var detInv = 1 / det;
1549 
1550  te[ 0 ] = t11 * detInv;
1551  te[ 1 ] = ( n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44 ) * detInv;
1552  te[ 2 ] = ( n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44 ) * detInv;
1553  te[ 3 ] = ( n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43 ) * detInv;
1554 
1555  te[ 4 ] = t12 * detInv;
1556  te[ 5 ] = ( n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44 ) * detInv;
1557  te[ 6 ] = ( n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44 ) * detInv;
1558  te[ 7 ] = ( n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43 ) * detInv;
1559 
1560  te[ 8 ] = t13 * detInv;
1561  te[ 9 ] = ( n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44 ) * detInv;
1562  te[ 10 ] = ( n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44 ) * detInv;
1563  te[ 11 ] = ( n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43 ) * detInv;
1564 
1565  te[ 12 ] = t14 * detInv;
1566  te[ 13 ] = ( n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34 ) * detInv;
1567  te[ 14 ] = ( n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34 ) * detInv;
1568  te[ 15 ] = ( n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33 ) * detInv;
1569 
1570  return this;
1571 
1572  },
1573 
1574  scale: function ( v ) {
1575 
1576  var te = this.elements;
1577  var x = v.x, y = v.y, z = v.z;
1578 
1579  te[ 0 ] *= x; te[ 4 ] *= y; te[ 8 ] *= z;
1580  te[ 1 ] *= x; te[ 5 ] *= y; te[ 9 ] *= z;
1581  te[ 2 ] *= x; te[ 6 ] *= y; te[ 10 ] *= z;
1582  te[ 3 ] *= x; te[ 7 ] *= y; te[ 11 ] *= z;
1583 
1584  return this;
1585 
1586  },
1587 
1588  getMaxScaleOnAxis: function () {
1589 
1590  var te = this.elements;
1591 
1592  var scaleXSq = te[ 0 ] * te[ 0 ] + te[ 1 ] * te[ 1 ] + te[ 2 ] * te[ 2 ];
1593  var scaleYSq = te[ 4 ] * te[ 4 ] + te[ 5 ] * te[ 5 ] + te[ 6 ] * te[ 6 ];
1594  var scaleZSq = te[ 8 ] * te[ 8 ] + te[ 9 ] * te[ 9 ] + te[ 10 ] * te[ 10 ];
1595 
1596  return Math.sqrt( Math.max( scaleXSq, scaleYSq, scaleZSq ) );
1597 
1598  },
1599 
1600  makeTranslation: function ( x, y, z ) {
1601 
1602  this.set(
1603 
1604  1, 0, 0, x,
1605  0, 1, 0, y,
1606  0, 0, 1, z,
1607  0, 0, 0, 1
1608 
1609  );
1610 
1611  return this;
1612 
1613  },
1614 
1615  makeRotationX: function ( theta ) {
1616 
1617  var c = Math.cos( theta ), s = Math.sin( theta );
1618 
1619  this.set(
1620 
1621  1, 0, 0, 0,
1622  0, c, - s, 0,
1623  0, s, c, 0,
1624  0, 0, 0, 1
1625 
1626  );
1627 
1628  return this;
1629 
1630  },
1631 
1632  makeRotationY: function ( theta ) {
1633 
1634  var c = Math.cos( theta ), s = Math.sin( theta );
1635 
1636  this.set(
1637 
1638  c, 0, s, 0,
1639  0, 1, 0, 0,
1640  - s, 0, c, 0,
1641  0, 0, 0, 1
1642 
1643  );
1644 
1645  return this;
1646 
1647  },
1648 
1649  makeRotationZ: function ( theta ) {
1650 
1651  var c = Math.cos( theta ), s = Math.sin( theta );
1652 
1653  this.set(
1654 
1655  c, - s, 0, 0,
1656  s, c, 0, 0,
1657  0, 0, 1, 0,
1658  0, 0, 0, 1
1659 
1660  );
1661 
1662  return this;
1663 
1664  },
1665 
1666  makeRotationAxis: function ( axis, angle ) {
1667 
1668  // Based on http://www.gamedev.net/reference/articles/article1199.asp
1669 
1670  var c = Math.cos( angle );
1671  var s = Math.sin( angle );
1672  var t = 1 - c;
1673  var x = axis.x, y = axis.y, z = axis.z;
1674  var tx = t * x, ty = t * y;
1675 
1676  this.set(
1677 
1678  tx * x + c, tx * y - s * z, tx * z + s * y, 0,
1679  tx * y + s * z, ty * y + c, ty * z - s * x, 0,
1680  tx * z - s * y, ty * z + s * x, t * z * z + c, 0,
1681  0, 0, 0, 1
1682 
1683  );
1684 
1685  return this;
1686 
1687  },
1688 
1689  makeScale: function ( x, y, z ) {
1690 
1691  this.set(
1692 
1693  x, 0, 0, 0,
1694  0, y, 0, 0,
1695  0, 0, z, 0,
1696  0, 0, 0, 1
1697 
1698  );
1699 
1700  return this;
1701 
1702  },
1703 
1704  makeShear: function ( x, y, z ) {
1705 
1706  this.set(
1707 
1708  1, y, z, 0,
1709  x, 1, z, 0,
1710  x, y, 1, 0,
1711  0, 0, 0, 1
1712 
1713  );
1714 
1715  return this;
1716 
1717  },
1718 
1719  compose: function ( position, quaternion, scale ) {
1720 
1721  var te = this.elements;
1722 
1723  var x = quaternion._x, y = quaternion._y, z = quaternion._z, w = quaternion._w;
1724  var x2 = x + x, y2 = y + y, z2 = z + z;
1725  var xx = x * x2, xy = x * y2, xz = x * z2;
1726  var yy = y * y2, yz = y * z2, zz = z * z2;
1727  var wx = w * x2, wy = w * y2, wz = w * z2;
1728 
1729  var sx = scale.x, sy = scale.y, sz = scale.z;
1730 
1731  te[ 0 ] = ( 1 - ( yy + zz ) ) * sx;
1732  te[ 1 ] = ( xy + wz ) * sx;
1733  te[ 2 ] = ( xz - wy ) * sx;
1734  te[ 3 ] = 0;
1735 
1736  te[ 4 ] = ( xy - wz ) * sy;
1737  te[ 5 ] = ( 1 - ( xx + zz ) ) * sy;
1738  te[ 6 ] = ( yz + wx ) * sy;
1739  te[ 7 ] = 0;
1740 
1741  te[ 8 ] = ( xz + wy ) * sz;
1742  te[ 9 ] = ( yz - wx ) * sz;
1743  te[ 10 ] = ( 1 - ( xx + yy ) ) * sz;
1744  te[ 11 ] = 0;
1745 
1746  te[ 12 ] = position.x;
1747  te[ 13 ] = position.y;
1748  te[ 14 ] = position.z;
1749  te[ 15 ] = 1;
1750 
1751  return this;
1752 
1753  },
1754 
1755  decompose: function () {
1756 
1757  var vector = new Vector3();
1758  var matrix = new Matrix4();
1759 
1760  return function decompose( position, quaternion, scale ) {
1761 
1762  var te = this.elements;
1763 
1764  var sx = vector.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length();
1765  var sy = vector.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length();
1766  var sz = vector.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length();
1767 
1768  // if determine is negative, we need to invert one scale
1769  var det = this.determinant();
1770  if ( det < 0 ) sx = - sx;
1771 
1772  position.x = te[ 12 ];
1773  position.y = te[ 13 ];
1774  position.z = te[ 14 ];
1775 
1776  // scale the rotation part
1777  matrix.copy( this );
1778 
1779  var invSX = 1 / sx;
1780  var invSY = 1 / sy;
1781  var invSZ = 1 / sz;
1782 
1783  matrix.elements[ 0 ] *= invSX;
1784  matrix.elements[ 1 ] *= invSX;
1785  matrix.elements[ 2 ] *= invSX;
1786 
1787  matrix.elements[ 4 ] *= invSY;
1788  matrix.elements[ 5 ] *= invSY;
1789  matrix.elements[ 6 ] *= invSY;
1790 
1791  matrix.elements[ 8 ] *= invSZ;
1792  matrix.elements[ 9 ] *= invSZ;
1793  matrix.elements[ 10 ] *= invSZ;
1794 
1795  quaternion.setFromRotationMatrix( matrix );
1796 
1797  scale.x = sx;
1798  scale.y = sy;
1799  scale.z = sz;
1800 
1801  return this;
1802 
1803  };
1804 
1805  }(),
1806 
1807  makePerspective: function ( left, right, top, bottom, near, far ) {
1808 
1809  if ( far === undefined ) {
1810 
1811  console.warn( 'THREE.Matrix4: .makePerspective() has been redefined and has a new signature. Please check the docs.' );
1812 
1813  }
1814 
1815  var te = this.elements;
1816  var x = 2 * near / ( right - left );
1817  var y = 2 * near / ( top - bottom );
1818 
1819  var a = ( right + left ) / ( right - left );
1820  var b = ( top + bottom ) / ( top - bottom );
1821  var c = - ( far + near ) / ( far - near );
1822  var d = - 2 * far * near / ( far - near );
1823 
1824  te[ 0 ] = x; te[ 4 ] = 0; te[ 8 ] = a; te[ 12 ] = 0;
1825  te[ 1 ] = 0; te[ 5 ] = y; te[ 9 ] = b; te[ 13 ] = 0;
1826  te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = c; te[ 14 ] = d;
1827  te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = - 1; te[ 15 ] = 0;
1828 
1829  return this;
1830 
1831  },
1832 
1833  makeOrthographic: function ( left, right, top, bottom, near, far ) {
1834 
1835  var te = this.elements;
1836  var w = 1.0 / ( right - left );
1837  var h = 1.0 / ( top - bottom );
1838  var p = 1.0 / ( far - near );
1839 
1840  var x = ( right + left ) * w;
1841  var y = ( top + bottom ) * h;
1842  var z = ( far + near ) * p;
1843 
1844  te[ 0 ] = 2 * w; te[ 4 ] = 0; te[ 8 ] = 0; te[ 12 ] = - x;
1845  te[ 1 ] = 0; te[ 5 ] = 2 * h; te[ 9 ] = 0; te[ 13 ] = - y;
1846  te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = - 2 * p; te[ 14 ] = - z;
1847  te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = 0; te[ 15 ] = 1;
1848 
1849  return this;
1850 
1851  },
1852 
1853  equals: function ( matrix ) {
1854 
1855  var te = this.elements;
1856  var me = matrix.elements;
1857 
1858  for ( var i = 0; i < 16; i ++ ) {
1859 
1860  if ( te[ i ] !== me[ i ] ) return false;
1861 
1862  }
1863 
1864  return true;
1865 
1866  },
1867 
1868  fromArray: function ( array, offset ) {
1869 
1870  if ( offset === undefined ) offset = 0;
1871 
1872  for ( var i = 0; i < 16; i ++ ) {
1873 
1874  this.elements[ i ] = array[ i + offset ];
1875 
1876  }
1877 
1878  return this;
1879 
1880  },
1881 
1882  toArray: function ( array, offset ) {
1883 
1884  if ( array === undefined ) array = [];
1885  if ( offset === undefined ) offset = 0;
1886 
1887  var te = this.elements;
1888 
1889  array[ offset ] = te[ 0 ];
1890  array[ offset + 1 ] = te[ 1 ];
1891  array[ offset + 2 ] = te[ 2 ];
1892  array[ offset + 3 ] = te[ 3 ];
1893 
1894  array[ offset + 4 ] = te[ 4 ];
1895  array[ offset + 5 ] = te[ 5 ];
1896  array[ offset + 6 ] = te[ 6 ];
1897  array[ offset + 7 ] = te[ 7 ];
1898 
1899  array[ offset + 8 ] = te[ 8 ];
1900  array[ offset + 9 ] = te[ 9 ];
1901  array[ offset + 10 ] = te[ 10 ];
1902  array[ offset + 11 ] = te[ 11 ];
1903 
1904  array[ offset + 12 ] = te[ 12 ];
1905  array[ offset + 13 ] = te[ 13 ];
1906  array[ offset + 14 ] = te[ 14 ];
1907  array[ offset + 15 ] = te[ 15 ];
1908 
1909  return array;
1910 
1911  }
1912 
1913  } );
1914 
1922  function Quaternion( x, y, z, w ) {
1923 
1924  this._x = x || 0;
1925  this._y = y || 0;
1926  this._z = z || 0;
1927  this._w = ( w !== undefined ) ? w : 1;
1928 
1929  }
1930 
1931  Object.assign( Quaternion, {
1932 
1933  slerp: function ( qa, qb, qm, t ) {
1934 
1935  return qm.copy( qa ).slerp( qb, t );
1936 
1937  },
1938 
1939  slerpFlat: function ( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) {
1940 
1941  // fuzz-free, array-based Quaternion SLERP operation
1942 
1943  var x0 = src0[ srcOffset0 + 0 ],
1944  y0 = src0[ srcOffset0 + 1 ],
1945  z0 = src0[ srcOffset0 + 2 ],
1946  w0 = src0[ srcOffset0 + 3 ],
1947 
1948  x1 = src1[ srcOffset1 + 0 ],
1949  y1 = src1[ srcOffset1 + 1 ],
1950  z1 = src1[ srcOffset1 + 2 ],
1951  w1 = src1[ srcOffset1 + 3 ];
1952 
1953  if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) {
1954 
1955  var s = 1 - t,
1956 
1957  cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1,
1958 
1959  dir = ( cos >= 0 ? 1 : - 1 ),
1960  sqrSin = 1 - cos * cos;
1961 
1962  // Skip the Slerp for tiny steps to avoid numeric problems:
1963  if ( sqrSin > Number.EPSILON ) {
1964 
1965  var sin = Math.sqrt( sqrSin ),
1966  len = Math.atan2( sin, cos * dir );
1967 
1968  s = Math.sin( s * len ) / sin;
1969  t = Math.sin( t * len ) / sin;
1970 
1971  }
1972 
1973  var tDir = t * dir;
1974 
1975  x0 = x0 * s + x1 * tDir;
1976  y0 = y0 * s + y1 * tDir;
1977  z0 = z0 * s + z1 * tDir;
1978  w0 = w0 * s + w1 * tDir;
1979 
1980  // Normalize in case we just did a lerp:
1981  if ( s === 1 - t ) {
1982 
1983  var f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 );
1984 
1985  x0 *= f;
1986  y0 *= f;
1987  z0 *= f;
1988  w0 *= f;
1989 
1990  }
1991 
1992  }
1993 
1994  dst[ dstOffset ] = x0;
1995  dst[ dstOffset + 1 ] = y0;
1996  dst[ dstOffset + 2 ] = z0;
1997  dst[ dstOffset + 3 ] = w0;
1998 
1999  }
2000 
2001  } );
2002 
2003  Object.defineProperties( Quaternion.prototype, {
2004 
2005  x: {
2006 
2007  get: function () {
2008 
2009  return this._x;
2010 
2011  },
2012 
2013  set: function ( value ) {
2014 
2015  this._x = value;
2016  this.onChangeCallback();
2017 
2018  }
2019 
2020  },
2021 
2022  y: {
2023 
2024  get: function () {
2025 
2026  return this._y;
2027 
2028  },
2029 
2030  set: function ( value ) {
2031 
2032  this._y = value;
2033  this.onChangeCallback();
2034 
2035  }
2036 
2037  },
2038 
2039  z: {
2040 
2041  get: function () {
2042 
2043  return this._z;
2044 
2045  },
2046 
2047  set: function ( value ) {
2048 
2049  this._z = value;
2050  this.onChangeCallback();
2051 
2052  }
2053 
2054  },
2055 
2056  w: {
2057 
2058  get: function () {
2059 
2060  return this._w;
2061 
2062  },
2063 
2064  set: function ( value ) {
2065 
2066  this._w = value;
2067  this.onChangeCallback();
2068 
2069  }
2070 
2071  }
2072 
2073  } );
2074 
2075  Object.assign( Quaternion.prototype, {
2076 
2077  isQuaternion: true,
2078 
2079  set: function ( x, y, z, w ) {
2080 
2081  this._x = x;
2082  this._y = y;
2083  this._z = z;
2084  this._w = w;
2085 
2086  this.onChangeCallback();
2087 
2088  return this;
2089 
2090  },
2091 
2092  clone: function () {
2093 
2094  return new this.constructor( this._x, this._y, this._z, this._w );
2095 
2096  },
2097 
2098  copy: function ( quaternion ) {
2099 
2100  this._x = quaternion.x;
2101  this._y = quaternion.y;
2102  this._z = quaternion.z;
2103  this._w = quaternion.w;
2104 
2105  this.onChangeCallback();
2106 
2107  return this;
2108 
2109  },
2110 
2111  setFromEuler: function ( euler, update ) {
2112 
2113  if ( ! ( euler && euler.isEuler ) ) {
2114 
2115  throw new Error( 'THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.' );
2116 
2117  }
2118 
2119  var x = euler._x, y = euler._y, z = euler._z, order = euler.order;
2120 
2121  // http://www.mathworks.com/matlabcentral/fileexchange/
2122  // 20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/
2123  // content/SpinCalc.m
2124 
2125  var cos = Math.cos;
2126  var sin = Math.sin;
2127 
2128  var c1 = cos( x / 2 );
2129  var c2 = cos( y / 2 );
2130  var c3 = cos( z / 2 );
2131 
2132  var s1 = sin( x / 2 );
2133  var s2 = sin( y / 2 );
2134  var s3 = sin( z / 2 );
2135 
2136  if ( order === 'XYZ' ) {
2137 
2138  this._x = s1 * c2 * c3 + c1 * s2 * s3;
2139  this._y = c1 * s2 * c3 - s1 * c2 * s3;
2140  this._z = c1 * c2 * s3 + s1 * s2 * c3;
2141  this._w = c1 * c2 * c3 - s1 * s2 * s3;
2142 
2143  } else if ( order === 'YXZ' ) {
2144 
2145  this._x = s1 * c2 * c3 + c1 * s2 * s3;
2146  this._y = c1 * s2 * c3 - s1 * c2 * s3;
2147  this._z = c1 * c2 * s3 - s1 * s2 * c3;
2148  this._w = c1 * c2 * c3 + s1 * s2 * s3;
2149 
2150  } else if ( order === 'ZXY' ) {
2151 
2152  this._x = s1 * c2 * c3 - c1 * s2 * s3;
2153  this._y = c1 * s2 * c3 + s1 * c2 * s3;
2154  this._z = c1 * c2 * s3 + s1 * s2 * c3;
2155  this._w = c1 * c2 * c3 - s1 * s2 * s3;
2156 
2157  } else if ( order === 'ZYX' ) {
2158 
2159  this._x = s1 * c2 * c3 - c1 * s2 * s3;
2160  this._y = c1 * s2 * c3 + s1 * c2 * s3;
2161  this._z = c1 * c2 * s3 - s1 * s2 * c3;
2162  this._w = c1 * c2 * c3 + s1 * s2 * s3;
2163 
2164  } else if ( order === 'YZX' ) {
2165 
2166  this._x = s1 * c2 * c3 + c1 * s2 * s3;
2167  this._y = c1 * s2 * c3 + s1 * c2 * s3;
2168  this._z = c1 * c2 * s3 - s1 * s2 * c3;
2169  this._w = c1 * c2 * c3 - s1 * s2 * s3;
2170 
2171  } else if ( order === 'XZY' ) {
2172 
2173  this._x = s1 * c2 * c3 - c1 * s2 * s3;
2174  this._y = c1 * s2 * c3 - s1 * c2 * s3;
2175  this._z = c1 * c2 * s3 + s1 * s2 * c3;
2176  this._w = c1 * c2 * c3 + s1 * s2 * s3;
2177 
2178  }
2179 
2180  if ( update !== false ) this.onChangeCallback();
2181 
2182  return this;
2183 
2184  },
2185 
2186  setFromAxisAngle: function ( axis, angle ) {
2187 
2188  // http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm
2189 
2190  // assumes axis is normalized
2191 
2192  var halfAngle = angle / 2, s = Math.sin( halfAngle );
2193 
2194  this._x = axis.x * s;
2195  this._y = axis.y * s;
2196  this._z = axis.z * s;
2197  this._w = Math.cos( halfAngle );
2198 
2199  this.onChangeCallback();
2200 
2201  return this;
2202 
2203  },
2204 
2205  setFromRotationMatrix: function ( m ) {
2206 
2207  // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
2208 
2209  // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
2210 
2211  var te = m.elements,
2212 
2213  m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
2214  m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
2215  m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ],
2216 
2217  trace = m11 + m22 + m33,
2218  s;
2219 
2220  if ( trace > 0 ) {
2221 
2222  s = 0.5 / Math.sqrt( trace + 1.0 );
2223 
2224  this._w = 0.25 / s;
2225  this._x = ( m32 - m23 ) * s;
2226  this._y = ( m13 - m31 ) * s;
2227  this._z = ( m21 - m12 ) * s;
2228 
2229  } else if ( m11 > m22 && m11 > m33 ) {
2230 
2231  s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 );
2232 
2233  this._w = ( m32 - m23 ) / s;
2234  this._x = 0.25 * s;
2235  this._y = ( m12 + m21 ) / s;
2236  this._z = ( m13 + m31 ) / s;
2237 
2238  } else if ( m22 > m33 ) {
2239 
2240  s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 );
2241 
2242  this._w = ( m13 - m31 ) / s;
2243  this._x = ( m12 + m21 ) / s;
2244  this._y = 0.25 * s;
2245  this._z = ( m23 + m32 ) / s;
2246 
2247  } else {
2248 
2249  s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 );
2250 
2251  this._w = ( m21 - m12 ) / s;
2252  this._x = ( m13 + m31 ) / s;
2253  this._y = ( m23 + m32 ) / s;
2254  this._z = 0.25 * s;
2255 
2256  }
2257 
2258  this.onChangeCallback();
2259 
2260  return this;
2261 
2262  },
2263 
2264  setFromUnitVectors: function () {
2265 
2266  // assumes direction vectors vFrom and vTo are normalized
2267 
2268  var v1 = new Vector3();
2269  var r;
2270 
2271  var EPS = 0.000001;
2272 
2273  return function setFromUnitVectors( vFrom, vTo ) {
2274 
2275  if ( v1 === undefined ) v1 = new Vector3();
2276 
2277  r = vFrom.dot( vTo ) + 1;
2278 
2279  if ( r < EPS ) {
2280 
2281  r = 0;
2282 
2283  if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) {
2284 
2285  v1.set( - vFrom.y, vFrom.x, 0 );
2286 
2287  } else {
2288 
2289  v1.set( 0, - vFrom.z, vFrom.y );
2290 
2291  }
2292 
2293  } else {
2294 
2295  v1.crossVectors( vFrom, vTo );
2296 
2297  }
2298 
2299  this._x = v1.x;
2300  this._y = v1.y;
2301  this._z = v1.z;
2302  this._w = r;
2303 
2304  return this.normalize();
2305 
2306  };
2307 
2308  }(),
2309 
2310  angleTo: function ( q ) {
2311 
2312  return 2 * Math.acos( Math.abs( _Math.clamp( this.dot( q ), - 1, 1 ) ) );
2313 
2314  },
2315 
2316  rotateTowards: function ( q, step ) {
2317 
2318  var angle = this.angleTo( q );
2319 
2320  if ( angle === 0 ) return this;
2321 
2322  var t = Math.min( 1, step / angle );
2323 
2324  this.slerp( q, t );
2325 
2326  return this;
2327 
2328  },
2329 
2330  inverse: function () {
2331 
2332  // quaternion is assumed to have unit length
2333 
2334  return this.conjugate();
2335 
2336  },
2337 
2338  conjugate: function () {
2339 
2340  this._x *= - 1;
2341  this._y *= - 1;
2342  this._z *= - 1;
2343 
2344  this.onChangeCallback();
2345 
2346  return this;
2347 
2348  },
2349 
2350  dot: function ( v ) {
2351 
2352  return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w;
2353 
2354  },
2355 
2356  lengthSq: function () {
2357 
2358  return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w;
2359 
2360  },
2361 
2362  length: function () {
2363 
2364  return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w );
2365 
2366  },
2367 
2368  normalize: function () {
2369 
2370  var l = this.length();
2371 
2372  if ( l === 0 ) {
2373 
2374  this._x = 0;
2375  this._y = 0;
2376  this._z = 0;
2377  this._w = 1;
2378 
2379  } else {
2380 
2381  l = 1 / l;
2382 
2383  this._x = this._x * l;
2384  this._y = this._y * l;
2385  this._z = this._z * l;
2386  this._w = this._w * l;
2387 
2388  }
2389 
2390  this.onChangeCallback();
2391 
2392  return this;
2393 
2394  },
2395 
2396  multiply: function ( q, p ) {
2397 
2398  if ( p !== undefined ) {
2399 
2400  console.warn( 'THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead.' );
2401  return this.multiplyQuaternions( q, p );
2402 
2403  }
2404 
2405  return this.multiplyQuaternions( this, q );
2406 
2407  },
2408 
2409  premultiply: function ( q ) {
2410 
2411  return this.multiplyQuaternions( q, this );
2412 
2413  },
2414 
2415  multiplyQuaternions: function ( a, b ) {
2416 
2417  // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm
2418 
2419  var qax = a._x, qay = a._y, qaz = a._z, qaw = a._w;
2420  var qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w;
2421 
2422  this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;
2423  this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;
2424  this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;
2425  this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;
2426 
2427  this.onChangeCallback();
2428 
2429  return this;
2430 
2431  },
2432 
2433  slerp: function ( qb, t ) {
2434 
2435  if ( t === 0 ) return this;
2436  if ( t === 1 ) return this.copy( qb );
2437 
2438  var x = this._x, y = this._y, z = this._z, w = this._w;
2439 
2440  // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/
2441 
2442  var cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z;
2443 
2444  if ( cosHalfTheta < 0 ) {
2445 
2446  this._w = - qb._w;
2447  this._x = - qb._x;
2448  this._y = - qb._y;
2449  this._z = - qb._z;
2450 
2451  cosHalfTheta = - cosHalfTheta;
2452 
2453  } else {
2454 
2455  this.copy( qb );
2456 
2457  }
2458 
2459  if ( cosHalfTheta >= 1.0 ) {
2460 
2461  this._w = w;
2462  this._x = x;
2463  this._y = y;
2464  this._z = z;
2465 
2466  return this;
2467 
2468  }
2469 
2470  var sqrSinHalfTheta = 1.0 - cosHalfTheta * cosHalfTheta;
2471 
2472  if ( sqrSinHalfTheta <= Number.EPSILON ) {
2473 
2474  var s = 1 - t;
2475  this._w = s * w + t * this._w;
2476  this._x = s * x + t * this._x;
2477  this._y = s * y + t * this._y;
2478  this._z = s * z + t * this._z;
2479 
2480  return this.normalize();
2481 
2482  }
2483 
2484  var sinHalfTheta = Math.sqrt( sqrSinHalfTheta );
2485  var halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta );
2486  var ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta,
2487  ratioB = Math.sin( t * halfTheta ) / sinHalfTheta;
2488 
2489  this._w = ( w * ratioA + this._w * ratioB );
2490  this._x = ( x * ratioA + this._x * ratioB );
2491  this._y = ( y * ratioA + this._y * ratioB );
2492  this._z = ( z * ratioA + this._z * ratioB );
2493 
2494  this.onChangeCallback();
2495 
2496  return this;
2497 
2498  },
2499 
2500  equals: function ( quaternion ) {
2501 
2502  return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w );
2503 
2504  },
2505 
2506  fromArray: function ( array, offset ) {
2507 
2508  if ( offset === undefined ) offset = 0;
2509 
2510  this._x = array[ offset ];
2511  this._y = array[ offset + 1 ];
2512  this._z = array[ offset + 2 ];
2513  this._w = array[ offset + 3 ];
2514 
2515  this.onChangeCallback();
2516 
2517  return this;
2518 
2519  },
2520 
2521  toArray: function ( array, offset ) {
2522 
2523  if ( array === undefined ) array = [];
2524  if ( offset === undefined ) offset = 0;
2525 
2526  array[ offset ] = this._x;
2527  array[ offset + 1 ] = this._y;
2528  array[ offset + 2 ] = this._z;
2529  array[ offset + 3 ] = this._w;
2530 
2531  return array;
2532 
2533  },
2534 
2535  onChange: function ( callback ) {
2536 
2537  this.onChangeCallback = callback;
2538 
2539  return this;
2540 
2541  },
2542 
2543  onChangeCallback: function () {}
2544 
2545  } );
2546 
2556  function Vector3( x, y, z ) {
2557 
2558  this.x = x || 0;
2559  this.y = y || 0;
2560  this.z = z || 0;
2561 
2562  }
2563 
2564  Object.assign( Vector3.prototype, {
2565 
2566  isVector3: true,
2567 
2568  set: function ( x, y, z ) {
2569 
2570  this.x = x;
2571  this.y = y;
2572  this.z = z;
2573 
2574  return this;
2575 
2576  },
2577 
2578  setScalar: function ( scalar ) {
2579 
2580  this.x = scalar;
2581  this.y = scalar;
2582  this.z = scalar;
2583 
2584  return this;
2585 
2586  },
2587 
2588  setX: function ( x ) {
2589 
2590  this.x = x;
2591 
2592  return this;
2593 
2594  },
2595 
2596  setY: function ( y ) {
2597 
2598  this.y = y;
2599 
2600  return this;
2601 
2602  },
2603 
2604  setZ: function ( z ) {
2605 
2606  this.z = z;
2607 
2608  return this;
2609 
2610  },
2611 
2612  setComponent: function ( index, value ) {
2613 
2614  switch ( index ) {
2615 
2616  case 0: this.x = value; break;
2617  case 1: this.y = value; break;
2618  case 2: this.z = value; break;
2619  default: throw new Error( 'index is out of range: ' + index );
2620 
2621  }
2622 
2623  return this;
2624 
2625  },
2626 
2627  getComponent: function ( index ) {
2628 
2629  switch ( index ) {
2630 
2631  case 0: return this.x;
2632  case 1: return this.y;
2633  case 2: return this.z;
2634  default: throw new Error( 'index is out of range: ' + index );
2635 
2636  }
2637 
2638  },
2639 
2640  clone: function () {
2641 
2642  return new this.constructor( this.x, this.y, this.z );
2643 
2644  },
2645 
2646  copy: function ( v ) {
2647 
2648  this.x = v.x;
2649  this.y = v.y;
2650  this.z = v.z;
2651 
2652  return this;
2653 
2654  },
2655 
2656  add: function ( v, w ) {
2657 
2658  if ( w !== undefined ) {
2659 
2660  console.warn( 'THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
2661  return this.addVectors( 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  addScalar: function ( s ) {
2674 
2675  this.x += s;
2676  this.y += s;
2677  this.z += s;
2678 
2679  return this;
2680 
2681  },
2682 
2683  addVectors: 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  addScaledVector: function ( v, s ) {
2694 
2695  this.x += v.x * s;
2696  this.y += v.y * s;
2697  this.z += v.z * s;
2698 
2699  return this;
2700 
2701  },
2702 
2703  sub: function ( v, w ) {
2704 
2705  if ( w !== undefined ) {
2706 
2707  console.warn( 'THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
2708  return this.subVectors( v, w );
2709 
2710  }
2711 
2712  this.x -= v.x;
2713  this.y -= v.y;
2714  this.z -= v.z;
2715 
2716  return this;
2717 
2718  },
2719 
2720  subScalar: function ( s ) {
2721 
2722  this.x -= s;
2723  this.y -= s;
2724  this.z -= s;
2725 
2726  return this;
2727 
2728  },
2729 
2730  subVectors: function ( a, b ) {
2731 
2732  this.x = a.x - b.x;
2733  this.y = a.y - b.y;
2734  this.z = a.z - b.z;
2735 
2736  return this;
2737 
2738  },
2739 
2740  multiply: function ( v, w ) {
2741 
2742  if ( w !== undefined ) {
2743 
2744  console.warn( 'THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead.' );
2745  return this.multiplyVectors( v, w );
2746 
2747  }
2748 
2749  this.x *= v.x;
2750  this.y *= v.y;
2751  this.z *= v.z;
2752 
2753  return this;
2754 
2755  },
2756 
2757  multiplyScalar: function ( scalar ) {
2758 
2759  this.x *= scalar;
2760  this.y *= scalar;
2761  this.z *= scalar;
2762 
2763  return this;
2764 
2765  },
2766 
2767  multiplyVectors: function ( a, b ) {
2768 
2769  this.x = a.x * b.x;
2770  this.y = a.y * b.y;
2771  this.z = a.z * b.z;
2772 
2773  return this;
2774 
2775  },
2776 
2777  applyEuler: function () {
2778 
2779  var quaternion = new Quaternion();
2780 
2781  return function applyEuler( euler ) {
2782 
2783  if ( ! ( euler && euler.isEuler ) ) {
2784 
2785  console.error( 'THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order.' );
2786 
2787  }
2788 
2789  return this.applyQuaternion( quaternion.setFromEuler( euler ) );
2790 
2791  };
2792 
2793  }(),
2794 
2795  applyAxisAngle: function () {
2796 
2797  var quaternion = new Quaternion();
2798 
2799  return function applyAxisAngle( axis, angle ) {
2800 
2801  return this.applyQuaternion( quaternion.setFromAxisAngle( axis, angle ) );
2802 
2803  };
2804 
2805  }(),
2806 
2807  applyMatrix3: function ( m ) {
2808 
2809  var x = this.x, y = this.y, z = this.z;
2810  var e = m.elements;
2811 
2812  this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z;
2813  this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z;
2814  this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z;
2815 
2816  return this;
2817 
2818  },
2819 
2820  applyMatrix4: function ( m ) {
2821 
2822  var x = this.x, y = this.y, z = this.z;
2823  var e = m.elements;
2824 
2825  var w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] );
2826 
2827  this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w;
2828  this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w;
2829  this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w;
2830 
2831  return this;
2832 
2833  },
2834 
2835  applyQuaternion: function ( q ) {
2836 
2837  var x = this.x, y = this.y, z = this.z;
2838  var qx = q.x, qy = q.y, qz = q.z, qw = q.w;
2839 
2840  // calculate quat * vector
2841 
2842  var ix = qw * x + qy * z - qz * y;
2843  var iy = qw * y + qz * x - qx * z;
2844  var iz = qw * z + qx * y - qy * x;
2845  var iw = - qx * x - qy * y - qz * z;
2846 
2847  // calculate result * inverse quat
2848 
2849  this.x = ix * qw + iw * - qx + iy * - qz - iz * - qy;
2850  this.y = iy * qw + iw * - qy + iz * - qx - ix * - qz;
2851  this.z = iz * qw + iw * - qz + ix * - qy - iy * - qx;
2852 
2853  return this;
2854 
2855  },
2856 
2857  project: function ( camera ) {
2858 
2859  return this.applyMatrix4( camera.matrixWorldInverse ).applyMatrix4( camera.projectionMatrix );
2860 
2861  },
2862 
2863  unproject: function () {
2864 
2865  var matrix = new Matrix4();
2866 
2867  return function unproject( camera ) {
2868 
2869  return this.applyMatrix4( matrix.getInverse( camera.projectionMatrix ) ).applyMatrix4( camera.matrixWorld );
2870 
2871  };
2872 
2873  }(),
2874 
2875  transformDirection: function ( m ) {
2876 
2877  // input: THREE.Matrix4 affine matrix
2878  // vector interpreted as a direction
2879 
2880  var x = this.x, y = this.y, z = this.z;
2881  var e = m.elements;
2882 
2883  this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z;
2884  this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z;
2885  this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z;
2886 
2887  return this.normalize();
2888 
2889  },
2890 
2891  divide: function ( v ) {
2892 
2893  this.x /= v.x;
2894  this.y /= v.y;
2895  this.z /= v.z;
2896 
2897  return this;
2898 
2899  },
2900 
2901  divideScalar: function ( scalar ) {
2902 
2903  return this.multiplyScalar( 1 / scalar );
2904 
2905  },
2906 
2907  min: function ( v ) {
2908 
2909  this.x = Math.min( this.x, v.x );
2910  this.y = Math.min( this.y, v.y );
2911  this.z = Math.min( this.z, v.z );
2912 
2913  return this;
2914 
2915  },
2916 
2917  max: function ( v ) {
2918 
2919  this.x = Math.max( this.x, v.x );
2920  this.y = Math.max( this.y, v.y );
2921  this.z = Math.max( this.z, v.z );
2922 
2923  return this;
2924 
2925  },
2926 
2927  clamp: function ( min, max ) {
2928 
2929  // assumes min < max, componentwise
2930 
2931  this.x = Math.max( min.x, Math.min( max.x, this.x ) );
2932  this.y = Math.max( min.y, Math.min( max.y, this.y ) );
2933  this.z = Math.max( min.z, Math.min( max.z, this.z ) );
2934 
2935  return this;
2936 
2937  },
2938 
2939  clampScalar: function () {
2940 
2941  var min = new Vector3();
2942  var max = new Vector3();
2943 
2944  return function clampScalar( minVal, maxVal ) {
2945 
2946  min.set( minVal, minVal, minVal );
2947  max.set( maxVal, maxVal, maxVal );
2948 
2949  return this.clamp( min, max );
2950 
2951  };
2952 
2953  }(),
2954 
2955  clampLength: function ( min, max ) {
2956 
2957  var length = this.length();
2958 
2959  return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
2960 
2961  },
2962 
2963  floor: function () {
2964 
2965  this.x = Math.floor( this.x );
2966  this.y = Math.floor( this.y );
2967  this.z = Math.floor( this.z );
2968 
2969  return this;
2970 
2971  },
2972 
2973  ceil: function () {
2974 
2975  this.x = Math.ceil( this.x );
2976  this.y = Math.ceil( this.y );
2977  this.z = Math.ceil( this.z );
2978 
2979  return this;
2980 
2981  },
2982 
2983  round: function () {
2984 
2985  this.x = Math.round( this.x );
2986  this.y = Math.round( this.y );
2987  this.z = Math.round( this.z );
2988 
2989  return this;
2990 
2991  },
2992 
2993  roundToZero: function () {
2994 
2995  this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
2996  this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
2997  this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );
2998 
2999  return this;
3000 
3001  },
3002 
3003  negate: function () {
3004 
3005  this.x = - this.x;
3006  this.y = - this.y;
3007  this.z = - this.z;
3008 
3009  return this;
3010 
3011  },
3012 
3013  dot: function ( v ) {
3014 
3015  return this.x * v.x + this.y * v.y + this.z * v.z;
3016 
3017  },
3018 
3019  // TODO lengthSquared?
3020 
3021  lengthSq: function () {
3022 
3023  return this.x * this.x + this.y * this.y + this.z * this.z;
3024 
3025  },
3026 
3027  length: function () {
3028 
3029  return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z );
3030 
3031  },
3032 
3033  manhattanLength: function () {
3034 
3035  return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z );
3036 
3037  },
3038 
3039  normalize: function () {
3040 
3041  return this.divideScalar( this.length() || 1 );
3042 
3043  },
3044 
3045  setLength: function ( length ) {
3046 
3047  return this.normalize().multiplyScalar( length );
3048 
3049  },
3050 
3051  lerp: function ( v, alpha ) {
3052 
3053  this.x += ( v.x - this.x ) * alpha;
3054  this.y += ( v.y - this.y ) * alpha;
3055  this.z += ( v.z - this.z ) * alpha;
3056 
3057  return this;
3058 
3059  },
3060 
3061  lerpVectors: function ( v1, v2, alpha ) {
3062 
3063  return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );
3064 
3065  },
3066 
3067  cross: function ( v, w ) {
3068 
3069  if ( w !== undefined ) {
3070 
3071  console.warn( 'THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead.' );
3072  return this.crossVectors( v, w );
3073 
3074  }
3075 
3076  return this.crossVectors( this, v );
3077 
3078  },
3079 
3080  crossVectors: function ( a, b ) {
3081 
3082  var ax = a.x, ay = a.y, az = a.z;
3083  var bx = b.x, by = b.y, bz = b.z;
3084 
3085  this.x = ay * bz - az * by;
3086  this.y = az * bx - ax * bz;
3087  this.z = ax * by - ay * bx;
3088 
3089  return this;
3090 
3091  },
3092 
3093  projectOnVector: function ( vector ) {
3094 
3095  var scalar = vector.dot( this ) / vector.lengthSq();
3096 
3097  return this.copy( vector ).multiplyScalar( scalar );
3098 
3099  },
3100 
3101  projectOnPlane: function () {
3102 
3103  var v1 = new Vector3();
3104 
3105  return function projectOnPlane( planeNormal ) {
3106 
3107  v1.copy( this ).projectOnVector( planeNormal );
3108 
3109  return this.sub( v1 );
3110 
3111  };
3112 
3113  }(),
3114 
3115  reflect: function () {
3116 
3117  // reflect incident vector off plane orthogonal to normal
3118  // normal is assumed to have unit length
3119 
3120  var v1 = new Vector3();
3121 
3122  return function reflect( normal ) {
3123 
3124  return this.sub( v1.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) );
3125 
3126  };
3127 
3128  }(),
3129 
3130  angleTo: function ( v ) {
3131 
3132  var theta = this.dot( v ) / ( Math.sqrt( this.lengthSq() * v.lengthSq() ) );
3133 
3134  // clamp, to handle numerical problems
3135 
3136  return Math.acos( _Math.clamp( theta, - 1, 1 ) );
3137 
3138  },
3139 
3140  distanceTo: function ( v ) {
3141 
3142  return Math.sqrt( this.distanceToSquared( v ) );
3143 
3144  },
3145 
3146  distanceToSquared: function ( v ) {
3147 
3148  var dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z;
3149 
3150  return dx * dx + dy * dy + dz * dz;
3151 
3152  },
3153 
3154  manhattanDistanceTo: function ( v ) {
3155 
3156  return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ) + Math.abs( this.z - v.z );
3157 
3158  },
3159 
3160  setFromSpherical: function ( s ) {
3161 
3162  return this.setFromSphericalCoords( s.radius, s.phi, s.theta );
3163 
3164  },
3165 
3166  setFromSphericalCoords: function ( radius, phi, theta ) {
3167 
3168  var sinPhiRadius = Math.sin( phi ) * radius;
3169 
3170  this.x = sinPhiRadius * Math.sin( theta );
3171  this.y = Math.cos( phi ) * radius;
3172  this.z = sinPhiRadius * Math.cos( theta );
3173 
3174  return this;
3175 
3176  },
3177 
3178  setFromCylindrical: function ( c ) {
3179 
3180  return this.setFromCylindricalCoords( c.radius, c.theta, c.y );
3181 
3182  },
3183 
3184  setFromCylindricalCoords: function ( radius, theta, y ) {
3185 
3186  this.x = radius * Math.sin( theta );
3187  this.y = y;
3188  this.z = radius * Math.cos( theta );
3189 
3190  return this;
3191 
3192  },
3193 
3194  setFromMatrixPosition: function ( m ) {
3195 
3196  var e = m.elements;
3197 
3198  this.x = e[ 12 ];
3199  this.y = e[ 13 ];
3200  this.z = e[ 14 ];
3201 
3202  return this;
3203 
3204  },
3205 
3206  setFromMatrixScale: function ( m ) {
3207 
3208  var sx = this.setFromMatrixColumn( m, 0 ).length();
3209  var sy = this.setFromMatrixColumn( m, 1 ).length();
3210  var sz = this.setFromMatrixColumn( m, 2 ).length();
3211 
3212  this.x = sx;
3213  this.y = sy;
3214  this.z = sz;
3215 
3216  return this;
3217 
3218  },
3219 
3220  setFromMatrixColumn: function ( m, index ) {
3221 
3222  return this.fromArray( m.elements, index * 4 );
3223 
3224  },
3225 
3226  equals: function ( v ) {
3227 
3228  return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) );
3229 
3230  },
3231 
3232  fromArray: function ( array, offset ) {
3233 
3234  if ( offset === undefined ) offset = 0;
3235 
3236  this.x = array[ offset ];
3237  this.y = array[ offset + 1 ];
3238  this.z = array[ offset + 2 ];
3239 
3240  return this;
3241 
3242  },
3243 
3244  toArray: function ( array, offset ) {
3245 
3246  if ( array === undefined ) array = [];
3247  if ( offset === undefined ) offset = 0;
3248 
3249  array[ offset ] = this.x;
3250  array[ offset + 1 ] = this.y;
3251  array[ offset + 2 ] = this.z;
3252 
3253  return array;
3254 
3255  },
3256 
3257  fromBufferAttribute: function ( attribute, index, offset ) {
3258 
3259  if ( offset !== undefined ) {
3260 
3261  console.warn( 'THREE.Vector3: offset has been removed from .fromBufferAttribute().' );
3262 
3263  }
3264 
3265  this.x = attribute.getX( index );
3266  this.y = attribute.getY( index );
3267  this.z = attribute.getZ( index );
3268 
3269  return this;
3270 
3271  }
3272 
3273  } );
3274 
3282  function Matrix3() {
3283 
3284  this.elements = [
3285 
3286  1, 0, 0,
3287  0, 1, 0,
3288  0, 0, 1
3289 
3290  ];
3291 
3292  if ( arguments.length > 0 ) {
3293 
3294  console.error( 'THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.' );
3295 
3296  }
3297 
3298  }
3299 
3300  Object.assign( Matrix3.prototype, {
3301 
3302  isMatrix3: true,
3303 
3304  set: function ( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) {
3305 
3306  var te = this.elements;
3307 
3308  te[ 0 ] = n11; te[ 1 ] = n21; te[ 2 ] = n31;
3309  te[ 3 ] = n12; te[ 4 ] = n22; te[ 5 ] = n32;
3310  te[ 6 ] = n13; te[ 7 ] = n23; te[ 8 ] = n33;
3311 
3312  return this;
3313 
3314  },
3315 
3316  identity: function () {
3317 
3318  this.set(
3319 
3320  1, 0, 0,
3321  0, 1, 0,
3322  0, 0, 1
3323 
3324  );
3325 
3326  return this;
3327 
3328  },
3329 
3330  clone: function () {
3331 
3332  return new this.constructor().fromArray( this.elements );
3333 
3334  },
3335 
3336  copy: function ( m ) {
3337 
3338  var te = this.elements;
3339  var me = m.elements;
3340 
3341  te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ];
3342  te[ 3 ] = me[ 3 ]; te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ];
3343  te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ]; te[ 8 ] = me[ 8 ];
3344 
3345  return this;
3346 
3347  },
3348 
3349  setFromMatrix4: function ( m ) {
3350 
3351  var me = m.elements;
3352 
3353  this.set(
3354 
3355  me[ 0 ], me[ 4 ], me[ 8 ],
3356  me[ 1 ], me[ 5 ], me[ 9 ],
3357  me[ 2 ], me[ 6 ], me[ 10 ]
3358 
3359  );
3360 
3361  return this;
3362 
3363  },
3364 
3365  applyToBufferAttribute: function () {
3366 
3367  var v1 = new Vector3();
3368 
3369  return function applyToBufferAttribute( attribute ) {
3370 
3371  for ( var i = 0, l = attribute.count; i < l; i ++ ) {
3372 
3373  v1.x = attribute.getX( i );
3374  v1.y = attribute.getY( i );
3375  v1.z = attribute.getZ( i );
3376 
3377  v1.applyMatrix3( this );
3378 
3379  attribute.setXYZ( i, v1.x, v1.y, v1.z );
3380 
3381  }
3382 
3383  return attribute;
3384 
3385  };
3386 
3387  }(),
3388 
3389  multiply: function ( m ) {
3390 
3391  return this.multiplyMatrices( this, m );
3392 
3393  },
3394 
3395  premultiply: function ( m ) {
3396 
3397  return this.multiplyMatrices( m, this );
3398 
3399  },
3400 
3401  multiplyMatrices: function ( a, b ) {
3402 
3403  var ae = a.elements;
3404  var be = b.elements;
3405  var te = this.elements;
3406 
3407  var a11 = ae[ 0 ], a12 = ae[ 3 ], a13 = ae[ 6 ];
3408  var a21 = ae[ 1 ], a22 = ae[ 4 ], a23 = ae[ 7 ];
3409  var a31 = ae[ 2 ], a32 = ae[ 5 ], a33 = ae[ 8 ];
3410 
3411  var b11 = be[ 0 ], b12 = be[ 3 ], b13 = be[ 6 ];
3412  var b21 = be[ 1 ], b22 = be[ 4 ], b23 = be[ 7 ];
3413  var b31 = be[ 2 ], b32 = be[ 5 ], b33 = be[ 8 ];
3414 
3415  te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31;
3416  te[ 3 ] = a11 * b12 + a12 * b22 + a13 * b32;
3417  te[ 6 ] = a11 * b13 + a12 * b23 + a13 * b33;
3418 
3419  te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31;
3420  te[ 4 ] = a21 * b12 + a22 * b22 + a23 * b32;
3421  te[ 7 ] = a21 * b13 + a22 * b23 + a23 * b33;
3422 
3423  te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31;
3424  te[ 5 ] = a31 * b12 + a32 * b22 + a33 * b32;
3425  te[ 8 ] = a31 * b13 + a32 * b23 + a33 * b33;
3426 
3427  return this;
3428 
3429  },
3430 
3431  multiplyScalar: function ( s ) {
3432 
3433  var te = this.elements;
3434 
3435  te[ 0 ] *= s; te[ 3 ] *= s; te[ 6 ] *= s;
3436  te[ 1 ] *= s; te[ 4 ] *= s; te[ 7 ] *= s;
3437  te[ 2 ] *= s; te[ 5 ] *= s; te[ 8 ] *= s;
3438 
3439  return this;
3440 
3441  },
3442 
3443  determinant: function () {
3444 
3445  var te = this.elements;
3446 
3447  var a = te[ 0 ], b = te[ 1 ], c = te[ 2 ],
3448  d = te[ 3 ], e = te[ 4 ], f = te[ 5 ],
3449  g = te[ 6 ], h = te[ 7 ], i = te[ 8 ];
3450 
3451  return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g;
3452 
3453  },
3454 
3455  getInverse: function ( matrix, throwOnDegenerate ) {
3456 
3457  if ( matrix && matrix.isMatrix4 ) {
3458 
3459  console.error( "THREE.Matrix3: .getInverse() no longer takes a Matrix4 argument." );
3460 
3461  }
3462 
3463  var me = matrix.elements,
3464  te = this.elements,
3465 
3466  n11 = me[ 0 ], n21 = me[ 1 ], n31 = me[ 2 ],
3467  n12 = me[ 3 ], n22 = me[ 4 ], n32 = me[ 5 ],
3468  n13 = me[ 6 ], n23 = me[ 7 ], n33 = me[ 8 ],
3469 
3470  t11 = n33 * n22 - n32 * n23,
3471  t12 = n32 * n13 - n33 * n12,
3472  t13 = n23 * n12 - n22 * n13,
3473 
3474  det = n11 * t11 + n21 * t12 + n31 * t13;
3475 
3476  if ( det === 0 ) {
3477 
3478  var msg = "THREE.Matrix3: .getInverse() can't invert matrix, determinant is 0";
3479 
3480  if ( throwOnDegenerate === true ) {
3481 
3482  throw new Error( msg );
3483 
3484  } else {
3485 
3486  console.warn( msg );
3487 
3488  }
3489 
3490  return this.identity();
3491 
3492  }
3493 
3494  var detInv = 1 / det;
3495 
3496  te[ 0 ] = t11 * detInv;
3497  te[ 1 ] = ( n31 * n23 - n33 * n21 ) * detInv;
3498  te[ 2 ] = ( n32 * n21 - n31 * n22 ) * detInv;
3499 
3500  te[ 3 ] = t12 * detInv;
3501  te[ 4 ] = ( n33 * n11 - n31 * n13 ) * detInv;
3502  te[ 5 ] = ( n31 * n12 - n32 * n11 ) * detInv;
3503 
3504  te[ 6 ] = t13 * detInv;
3505  te[ 7 ] = ( n21 * n13 - n23 * n11 ) * detInv;
3506  te[ 8 ] = ( n22 * n11 - n21 * n12 ) * detInv;
3507 
3508  return this;
3509 
3510  },
3511 
3512  transpose: function () {
3513 
3514  var tmp, m = this.elements;
3515 
3516  tmp = m[ 1 ]; m[ 1 ] = m[ 3 ]; m[ 3 ] = tmp;
3517  tmp = m[ 2 ]; m[ 2 ] = m[ 6 ]; m[ 6 ] = tmp;
3518  tmp = m[ 5 ]; m[ 5 ] = m[ 7 ]; m[ 7 ] = tmp;
3519 
3520  return this;
3521 
3522  },
3523 
3524  getNormalMatrix: function ( matrix4 ) {
3525 
3526  return this.setFromMatrix4( matrix4 ).getInverse( this ).transpose();
3527 
3528  },
3529 
3530  transposeIntoArray: function ( r ) {
3531 
3532  var m = this.elements;
3533 
3534  r[ 0 ] = m[ 0 ];
3535  r[ 1 ] = m[ 3 ];
3536  r[ 2 ] = m[ 6 ];
3537  r[ 3 ] = m[ 1 ];
3538  r[ 4 ] = m[ 4 ];
3539  r[ 5 ] = m[ 7 ];
3540  r[ 6 ] = m[ 2 ];
3541  r[ 7 ] = m[ 5 ];
3542  r[ 8 ] = m[ 8 ];
3543 
3544  return this;
3545 
3546  },
3547 
3548  setUvTransform: function ( tx, ty, sx, sy, rotation, cx, cy ) {
3549 
3550  var c = Math.cos( rotation );
3551  var s = Math.sin( rotation );
3552 
3553  this.set(
3554  sx * c, sx * s, - sx * ( c * cx + s * cy ) + cx + tx,
3555  - sy * s, sy * c, - sy * ( - s * cx + c * cy ) + cy + ty,
3556  0, 0, 1
3557  );
3558 
3559  },
3560 
3561  scale: function ( sx, sy ) {
3562 
3563  var te = this.elements;
3564 
3565  te[ 0 ] *= sx; te[ 3 ] *= sx; te[ 6 ] *= sx;
3566  te[ 1 ] *= sy; te[ 4 ] *= sy; te[ 7 ] *= sy;
3567 
3568  return this;
3569 
3570  },
3571 
3572  rotate: function ( theta ) {
3573 
3574  var c = Math.cos( theta );
3575  var s = Math.sin( theta );
3576 
3577  var te = this.elements;
3578 
3579  var a11 = te[ 0 ], a12 = te[ 3 ], a13 = te[ 6 ];
3580  var a21 = te[ 1 ], a22 = te[ 4 ], a23 = te[ 7 ];
3581 
3582  te[ 0 ] = c * a11 + s * a21;
3583  te[ 3 ] = c * a12 + s * a22;
3584  te[ 6 ] = c * a13 + s * a23;
3585 
3586  te[ 1 ] = - s * a11 + c * a21;
3587  te[ 4 ] = - s * a12 + c * a22;
3588  te[ 7 ] = - s * a13 + c * a23;
3589 
3590  return this;
3591 
3592  },
3593 
3594  translate: function ( tx, ty ) {
3595 
3596  var te = this.elements;
3597 
3598  te[ 0 ] += tx * te[ 2 ]; te[ 3 ] += tx * te[ 5 ]; te[ 6 ] += tx * te[ 8 ];
3599  te[ 1 ] += ty * te[ 2 ]; te[ 4 ] += ty * te[ 5 ]; te[ 7 ] += ty * te[ 8 ];
3600 
3601  return this;
3602 
3603  },
3604 
3605  equals: function ( matrix ) {
3606 
3607  var te = this.elements;
3608  var me = matrix.elements;
3609 
3610  for ( var i = 0; i < 9; i ++ ) {
3611 
3612  if ( te[ i ] !== me[ i ] ) return false;
3613 
3614  }
3615 
3616  return true;
3617 
3618  },
3619 
3620  fromArray: function ( array, offset ) {
3621 
3622  if ( offset === undefined ) offset = 0;
3623 
3624  for ( var i = 0; i < 9; i ++ ) {
3625 
3626  this.elements[ i ] = array[ i + offset ];
3627 
3628  }
3629 
3630  return this;
3631 
3632  },
3633 
3634  toArray: function ( array, offset ) {
3635 
3636  if ( array === undefined ) array = [];
3637  if ( offset === undefined ) offset = 0;
3638 
3639  var te = this.elements;
3640 
3641  array[ offset ] = te[ 0 ];
3642  array[ offset + 1 ] = te[ 1 ];
3643  array[ offset + 2 ] = te[ 2 ];
3644 
3645  array[ offset + 3 ] = te[ 3 ];
3646  array[ offset + 4 ] = te[ 4 ];
3647  array[ offset + 5 ] = te[ 5 ];
3648 
3649  array[ offset + 6 ] = te[ 6 ];
3650  array[ offset + 7 ] = te[ 7 ];
3651  array[ offset + 8 ] = te[ 8 ];
3652 
3653  return array;
3654 
3655  }
3656 
3657  } );
3658 
3665  var _canvas;
3666 
3667  var ImageUtils = {
3668 
3669  getDataURL: function ( image ) {
3670 
3671  var canvas;
3672 
3673  if ( typeof HTMLCanvasElement == 'undefined' ) {
3674 
3675  return image.src;
3676 
3677  } else if ( image instanceof HTMLCanvasElement ) {
3678 
3679  canvas = image;
3680 
3681  } else {
3682 
3683  if ( _canvas === undefined ) _canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
3684 
3685  _canvas.width = image.width;
3686  _canvas.height = image.height;
3687 
3688  var context = _canvas.getContext( '2d' );
3689 
3690  if ( image instanceof ImageData ) {
3691 
3692  context.putImageData( image, 0, 0 );
3693 
3694  } else {
3695 
3696  context.drawImage( image, 0, 0, image.width, image.height );
3697 
3698  }
3699 
3700  canvas = _canvas;
3701 
3702  }
3703 
3704  if ( canvas.width > 2048 || canvas.height > 2048 ) {
3705 
3706  return canvas.toDataURL( 'image/jpeg', 0.6 );
3707 
3708  } else {
3709 
3710  return canvas.toDataURL( 'image/png' );
3711 
3712  }
3713 
3714  }
3715 
3716  };
3717 
3724  var textureId = 0;
3725 
3726  function Texture( image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) {
3727 
3728  Object.defineProperty( this, 'id', { value: textureId ++ } );
3729 
3730  this.uuid = _Math.generateUUID();
3731 
3732  this.name = '';
3733 
3734  this.image = image !== undefined ? image : Texture.DEFAULT_IMAGE;
3735  this.mipmaps = [];
3736 
3737  this.mapping = mapping !== undefined ? mapping : Texture.DEFAULT_MAPPING;
3738 
3739  this.wrapS = wrapS !== undefined ? wrapS : ClampToEdgeWrapping;
3740  this.wrapT = wrapT !== undefined ? wrapT : ClampToEdgeWrapping;
3741 
3742  this.magFilter = magFilter !== undefined ? magFilter : LinearFilter;
3743  this.minFilter = minFilter !== undefined ? minFilter : LinearMipMapLinearFilter;
3744 
3745  this.anisotropy = anisotropy !== undefined ? anisotropy : 1;
3746 
3747  this.format = format !== undefined ? format : RGBAFormat;
3748  this.type = type !== undefined ? type : UnsignedByteType;
3749 
3750  this.offset = new Vector2( 0, 0 );
3751  this.repeat = new Vector2( 1, 1 );
3752  this.center = new Vector2( 0, 0 );
3753  this.rotation = 0;
3754 
3755  this.matrixAutoUpdate = true;
3756  this.matrix = new Matrix3();
3757 
3758  this.generateMipmaps = true;
3759  this.premultiplyAlpha = false;
3760  this.flipY = true;
3761  this.unpackAlignment = 4; // valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml)
3762 
3763  // Values of encoding !== THREE.LinearEncoding only supported on map, envMap and emissiveMap.
3764  //
3765  // Also changing the encoding after already used by a Material will not automatically make the Material
3766  // update. You need to explicitly call Material.needsUpdate to trigger it to recompile.
3767  this.encoding = encoding !== undefined ? encoding : LinearEncoding;
3768 
3769  this.version = 0;
3770  this.onUpdate = null;
3771 
3772  }
3773 
3774  Texture.DEFAULT_IMAGE = undefined;
3775  Texture.DEFAULT_MAPPING = UVMapping;
3776 
3777  Texture.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
3778 
3779  constructor: Texture,
3780 
3781  isTexture: true,
3782 
3783  updateMatrix: function () {
3784 
3785  this.matrix.setUvTransform( this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y );
3786 
3787  },
3788 
3789  clone: function () {
3790 
3791  return new this.constructor().copy( this );
3792 
3793  },
3794 
3795  copy: function ( source ) {
3796 
3797  this.name = source.name;
3798 
3799  this.image = source.image;
3800  this.mipmaps = source.mipmaps.slice( 0 );
3801 
3802  this.mapping = source.mapping;
3803 
3804  this.wrapS = source.wrapS;
3805  this.wrapT = source.wrapT;
3806 
3807  this.magFilter = source.magFilter;
3808  this.minFilter = source.minFilter;
3809 
3810  this.anisotropy = source.anisotropy;
3811 
3812  this.format = source.format;
3813  this.type = source.type;
3814 
3815  this.offset.copy( source.offset );
3816  this.repeat.copy( source.repeat );
3817  this.center.copy( source.center );
3818  this.rotation = source.rotation;
3819 
3820  this.matrixAutoUpdate = source.matrixAutoUpdate;
3821  this.matrix.copy( source.matrix );
3822 
3823  this.generateMipmaps = source.generateMipmaps;
3824  this.premultiplyAlpha = source.premultiplyAlpha;
3825  this.flipY = source.flipY;
3826  this.unpackAlignment = source.unpackAlignment;
3827  this.encoding = source.encoding;
3828 
3829  return this;
3830 
3831  },
3832 
3833  toJSON: function ( meta ) {
3834 
3835  var isRootObject = ( meta === undefined || typeof meta === 'string' );
3836 
3837  if ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) {
3838 
3839  return meta.textures[ this.uuid ];
3840 
3841  }
3842 
3843  var output = {
3844 
3845  metadata: {
3846  version: 4.5,
3847  type: 'Texture',
3848  generator: 'Texture.toJSON'
3849  },
3850 
3851  uuid: this.uuid,
3852  name: this.name,
3853 
3854  mapping: this.mapping,
3855 
3856  repeat: [ this.repeat.x, this.repeat.y ],
3857  offset: [ this.offset.x, this.offset.y ],
3858  center: [ this.center.x, this.center.y ],
3859  rotation: this.rotation,
3860 
3861  wrap: [ this.wrapS, this.wrapT ],
3862 
3863  format: this.format,
3864  type: this.type,
3865  encoding: this.encoding,
3866 
3867  minFilter: this.minFilter,
3868  magFilter: this.magFilter,
3869  anisotropy: this.anisotropy,
3870 
3871  flipY: this.flipY,
3872 
3873  premultiplyAlpha: this.premultiplyAlpha,
3874  unpackAlignment: this.unpackAlignment
3875 
3876  };
3877 
3878  if ( this.image !== undefined ) {
3879 
3880  // TODO: Move to THREE.Image
3881 
3882  var image = this.image;
3883 
3884  if ( image.uuid === undefined ) {
3885 
3886  image.uuid = _Math.generateUUID(); // UGH
3887 
3888  }
3889 
3890  if ( ! isRootObject && meta.images[ image.uuid ] === undefined ) {
3891 
3892  var url;
3893 
3894  if ( Array.isArray( image ) ) {
3895 
3896  // process array of images e.g. CubeTexture
3897 
3898  url = [];
3899 
3900  for ( var i = 0, l = image.length; i < l; i ++ ) {
3901 
3902  url.push( ImageUtils.getDataURL( image[ i ] ) );
3903 
3904  }
3905 
3906  } else {
3907 
3908  // process single image
3909 
3910  url = ImageUtils.getDataURL( image );
3911 
3912  }
3913 
3914  meta.images[ image.uuid ] = {
3915  uuid: image.uuid,
3916  url: url
3917  };
3918 
3919  }
3920 
3921  output.image = image.uuid;
3922 
3923  }
3924 
3925  if ( ! isRootObject ) {
3926 
3927  meta.textures[ this.uuid ] = output;
3928 
3929  }
3930 
3931  return output;
3932 
3933  },
3934 
3935  dispose: function () {
3936 
3937  this.dispatchEvent( { type: 'dispose' } );
3938 
3939  },
3940 
3941  transformUv: function ( uv ) {
3942 
3943  if ( this.mapping !== UVMapping ) return uv;
3944 
3945  uv.applyMatrix3( this.matrix );
3946 
3947  if ( uv.x < 0 || uv.x > 1 ) {
3948 
3949  switch ( this.wrapS ) {
3950 
3951  case RepeatWrapping:
3952 
3953  uv.x = uv.x - Math.floor( uv.x );
3954  break;
3955 
3956  case ClampToEdgeWrapping:
3957 
3958  uv.x = uv.x < 0 ? 0 : 1;
3959  break;
3960 
3961  case MirroredRepeatWrapping:
3962 
3963  if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) {
3964 
3965  uv.x = Math.ceil( uv.x ) - uv.x;
3966 
3967  } else {
3968 
3969  uv.x = uv.x - Math.floor( uv.x );
3970 
3971  }
3972  break;
3973 
3974  }
3975 
3976  }
3977 
3978  if ( uv.y < 0 || uv.y > 1 ) {
3979 
3980  switch ( this.wrapT ) {
3981 
3982  case RepeatWrapping:
3983 
3984  uv.y = uv.y - Math.floor( uv.y );
3985  break;
3986 
3987  case ClampToEdgeWrapping:
3988 
3989  uv.y = uv.y < 0 ? 0 : 1;
3990  break;
3991 
3992  case MirroredRepeatWrapping:
3993 
3994  if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) {
3995 
3996  uv.y = Math.ceil( uv.y ) - uv.y;
3997 
3998  } else {
3999 
4000  uv.y = uv.y - Math.floor( uv.y );
4001 
4002  }
4003  break;
4004 
4005  }
4006 
4007  }
4008 
4009  if ( this.flipY ) {
4010 
4011  uv.y = 1 - uv.y;
4012 
4013  }
4014 
4015  return uv;
4016 
4017  }
4018 
4019  } );
4020 
4021  Object.defineProperty( Texture.prototype, "needsUpdate", {
4022 
4023  set: function ( value ) {
4024 
4025  if ( value === true ) this.version ++;
4026 
4027  }
4028 
4029  } );
4030 
4039  function Vector4( x, y, z, w ) {
4040 
4041  this.x = x || 0;
4042  this.y = y || 0;
4043  this.z = z || 0;
4044  this.w = ( w !== undefined ) ? w : 1;
4045 
4046  }
4047 
4048  Object.assign( Vector4.prototype, {
4049 
4050  isVector4: true,
4051 
4052  set: function ( x, y, z, w ) {
4053 
4054  this.x = x;
4055  this.y = y;
4056  this.z = z;
4057  this.w = w;
4058 
4059  return this;
4060 
4061  },
4062 
4063  setScalar: function ( scalar ) {
4064 
4065  this.x = scalar;
4066  this.y = scalar;
4067  this.z = scalar;
4068  this.w = scalar;
4069 
4070  return this;
4071 
4072  },
4073 
4074  setX: function ( x ) {
4075 
4076  this.x = x;
4077 
4078  return this;
4079 
4080  },
4081 
4082  setY: function ( y ) {
4083 
4084  this.y = y;
4085 
4086  return this;
4087 
4088  },
4089 
4090  setZ: function ( z ) {
4091 
4092  this.z = z;
4093 
4094  return this;
4095 
4096  },
4097 
4098  setW: function ( w ) {
4099 
4100  this.w = w;
4101 
4102  return this;
4103 
4104  },
4105 
4106  setComponent: function ( index, value ) {
4107 
4108  switch ( index ) {
4109 
4110  case 0: this.x = value; break;
4111  case 1: this.y = value; break;
4112  case 2: this.z = value; break;
4113  case 3: this.w = value; break;
4114  default: throw new Error( 'index is out of range: ' + index );
4115 
4116  }
4117 
4118  return this;
4119 
4120  },
4121 
4122  getComponent: function ( index ) {
4123 
4124  switch ( index ) {
4125 
4126  case 0: return this.x;
4127  case 1: return this.y;
4128  case 2: return this.z;
4129  case 3: return this.w;
4130  default: throw new Error( 'index is out of range: ' + index );
4131 
4132  }
4133 
4134  },
4135 
4136  clone: function () {
4137 
4138  return new this.constructor( this.x, this.y, this.z, this.w );
4139 
4140  },
4141 
4142  copy: function ( v ) {
4143 
4144  this.x = v.x;
4145  this.y = v.y;
4146  this.z = v.z;
4147  this.w = ( v.w !== undefined ) ? v.w : 1;
4148 
4149  return this;
4150 
4151  },
4152 
4153  add: function ( v, w ) {
4154 
4155  if ( w !== undefined ) {
4156 
4157  console.warn( 'THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
4158  return this.addVectors( v, w );
4159 
4160  }
4161 
4162  this.x += v.x;
4163  this.y += v.y;
4164  this.z += v.z;
4165  this.w += v.w;
4166 
4167  return this;
4168 
4169  },
4170 
4171  addScalar: function ( s ) {
4172 
4173  this.x += s;
4174  this.y += s;
4175  this.z += s;
4176  this.w += s;
4177 
4178  return this;
4179 
4180  },
4181 
4182  addVectors: function ( a, b ) {
4183 
4184  this.x = a.x + b.x;
4185  this.y = a.y + b.y;
4186  this.z = a.z + b.z;
4187  this.w = a.w + b.w;
4188 
4189  return this;
4190 
4191  },
4192 
4193  addScaledVector: function ( v, s ) {
4194 
4195  this.x += v.x * s;
4196  this.y += v.y * s;
4197  this.z += v.z * s;
4198  this.w += v.w * s;
4199 
4200  return this;
4201 
4202  },
4203 
4204  sub: function ( v, w ) {
4205 
4206  if ( w !== undefined ) {
4207 
4208  console.warn( 'THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
4209  return this.subVectors( v, w );
4210 
4211  }
4212 
4213  this.x -= v.x;
4214  this.y -= v.y;
4215  this.z -= v.z;
4216  this.w -= v.w;
4217 
4218  return this;
4219 
4220  },
4221 
4222  subScalar: function ( s ) {
4223 
4224  this.x -= s;
4225  this.y -= s;
4226  this.z -= s;
4227  this.w -= s;
4228 
4229  return this;
4230 
4231  },
4232 
4233  subVectors: function ( a, b ) {
4234 
4235  this.x = a.x - b.x;
4236  this.y = a.y - b.y;
4237  this.z = a.z - b.z;
4238  this.w = a.w - b.w;
4239 
4240  return this;
4241 
4242  },
4243 
4244  multiplyScalar: function ( scalar ) {
4245 
4246  this.x *= scalar;
4247  this.y *= scalar;
4248  this.z *= scalar;
4249  this.w *= scalar;
4250 
4251  return this;
4252 
4253  },
4254 
4255  applyMatrix4: function ( m ) {
4256 
4257  var x = this.x, y = this.y, z = this.z, w = this.w;
4258  var e = m.elements;
4259 
4260  this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w;
4261  this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w;
4262  this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w;
4263  this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w;
4264 
4265  return this;
4266 
4267  },
4268 
4269  divideScalar: function ( scalar ) {
4270 
4271  return this.multiplyScalar( 1 / scalar );
4272 
4273  },
4274 
4275  setAxisAngleFromQuaternion: function ( q ) {
4276 
4277  // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm
4278 
4279  // q is assumed to be normalized
4280 
4281  this.w = 2 * Math.acos( q.w );
4282 
4283  var s = Math.sqrt( 1 - q.w * q.w );
4284 
4285  if ( s < 0.0001 ) {
4286 
4287  this.x = 1;
4288  this.y = 0;
4289  this.z = 0;
4290 
4291  } else {
4292 
4293  this.x = q.x / s;
4294  this.y = q.y / s;
4295  this.z = q.z / s;
4296 
4297  }
4298 
4299  return this;
4300 
4301  },
4302 
4303  setAxisAngleFromRotationMatrix: function ( m ) {
4304 
4305  // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm
4306 
4307  // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
4308 
4309  var angle, x, y, z, // variables for result
4310  epsilon = 0.01, // margin to allow for rounding errors
4311  epsilon2 = 0.1, // margin to distinguish between 0 and 180 degrees
4312 
4313  te = m.elements,
4314 
4315  m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
4316  m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
4317  m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
4318 
4319  if ( ( Math.abs( m12 - m21 ) < epsilon ) &&
4320  ( Math.abs( m13 - m31 ) < epsilon ) &&
4321  ( Math.abs( m23 - m32 ) < epsilon ) ) {
4322 
4323  // singularity found
4324  // first check for identity matrix which must have +1 for all terms
4325  // in leading diagonal and zero in other terms
4326 
4327  if ( ( Math.abs( m12 + m21 ) < epsilon2 ) &&
4328  ( Math.abs( m13 + m31 ) < epsilon2 ) &&
4329  ( Math.abs( m23 + m32 ) < epsilon2 ) &&
4330  ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) {
4331 
4332  // this singularity is identity matrix so angle = 0
4333 
4334  this.set( 1, 0, 0, 0 );
4335 
4336  return this; // zero angle, arbitrary axis
4337 
4338  }
4339 
4340  // otherwise this singularity is angle = 180
4341 
4342  angle = Math.PI;
4343 
4344  var xx = ( m11 + 1 ) / 2;
4345  var yy = ( m22 + 1 ) / 2;
4346  var zz = ( m33 + 1 ) / 2;
4347  var xy = ( m12 + m21 ) / 4;
4348  var xz = ( m13 + m31 ) / 4;
4349  var yz = ( m23 + m32 ) / 4;
4350 
4351  if ( ( xx > yy ) && ( xx > zz ) ) {
4352 
4353  // m11 is the largest diagonal term
4354 
4355  if ( xx < epsilon ) {
4356 
4357  x = 0;
4358  y = 0.707106781;
4359  z = 0.707106781;
4360 
4361  } else {
4362 
4363  x = Math.sqrt( xx );
4364  y = xy / x;
4365  z = xz / x;
4366 
4367  }
4368 
4369  } else if ( yy > zz ) {
4370 
4371  // m22 is the largest diagonal term
4372 
4373  if ( yy < epsilon ) {
4374 
4375  x = 0.707106781;
4376  y = 0;
4377  z = 0.707106781;
4378 
4379  } else {
4380 
4381  y = Math.sqrt( yy );
4382  x = xy / y;
4383  z = yz / y;
4384 
4385  }
4386 
4387  } else {
4388 
4389  // m33 is the largest diagonal term so base result on this
4390 
4391  if ( zz < epsilon ) {
4392 
4393  x = 0.707106781;
4394  y = 0.707106781;
4395  z = 0;
4396 
4397  } else {
4398 
4399  z = Math.sqrt( zz );
4400  x = xz / z;
4401  y = yz / z;
4402 
4403  }
4404 
4405  }
4406 
4407  this.set( x, y, z, angle );
4408 
4409  return this; // return 180 deg rotation
4410 
4411  }
4412 
4413  // as we have reached here there are no singularities so we can handle normally
4414 
4415  var s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) +
4416  ( m13 - m31 ) * ( m13 - m31 ) +
4417  ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize
4418 
4419  if ( Math.abs( s ) < 0.001 ) s = 1;
4420 
4421  // prevent divide by zero, should not happen if matrix is orthogonal and should be
4422  // caught by singularity test above, but I've left it in just in case
4423 
4424  this.x = ( m32 - m23 ) / s;
4425  this.y = ( m13 - m31 ) / s;
4426  this.z = ( m21 - m12 ) / s;
4427  this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 );
4428 
4429  return this;
4430 
4431  },
4432 
4433  min: function ( v ) {
4434 
4435  this.x = Math.min( this.x, v.x );
4436  this.y = Math.min( this.y, v.y );
4437  this.z = Math.min( this.z, v.z );
4438  this.w = Math.min( this.w, v.w );
4439 
4440  return this;
4441 
4442  },
4443 
4444  max: function ( v ) {
4445 
4446  this.x = Math.max( this.x, v.x );
4447  this.y = Math.max( this.y, v.y );
4448  this.z = Math.max( this.z, v.z );
4449  this.w = Math.max( this.w, v.w );
4450 
4451  return this;
4452 
4453  },
4454 
4455  clamp: function ( min, max ) {
4456 
4457  // assumes min < max, componentwise
4458 
4459  this.x = Math.max( min.x, Math.min( max.x, this.x ) );
4460  this.y = Math.max( min.y, Math.min( max.y, this.y ) );
4461  this.z = Math.max( min.z, Math.min( max.z, this.z ) );
4462  this.w = Math.max( min.w, Math.min( max.w, this.w ) );
4463 
4464  return this;
4465 
4466  },
4467 
4468  clampScalar: function () {
4469 
4470  var min, max;
4471 
4472  return function clampScalar( minVal, maxVal ) {
4473 
4474  if ( min === undefined ) {
4475 
4476  min = new Vector4();
4477  max = new Vector4();
4478 
4479  }
4480 
4481  min.set( minVal, minVal, minVal, minVal );
4482  max.set( maxVal, maxVal, maxVal, maxVal );
4483 
4484  return this.clamp( min, max );
4485 
4486  };
4487 
4488  }(),
4489 
4490  clampLength: function ( min, max ) {
4491 
4492  var length = this.length();
4493 
4494  return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
4495 
4496  },
4497 
4498  floor: function () {
4499 
4500  this.x = Math.floor( this.x );
4501  this.y = Math.floor( this.y );
4502  this.z = Math.floor( this.z );
4503  this.w = Math.floor( this.w );
4504 
4505  return this;
4506 
4507  },
4508 
4509  ceil: function () {
4510 
4511  this.x = Math.ceil( this.x );
4512  this.y = Math.ceil( this.y );
4513  this.z = Math.ceil( this.z );
4514  this.w = Math.ceil( this.w );
4515 
4516  return this;
4517 
4518  },
4519 
4520  round: function () {
4521 
4522  this.x = Math.round( this.x );
4523  this.y = Math.round( this.y );
4524  this.z = Math.round( this.z );
4525  this.w = Math.round( this.w );
4526 
4527  return this;
4528 
4529  },
4530 
4531  roundToZero: function () {
4532 
4533  this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
4534  this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
4535  this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );
4536  this.w = ( this.w < 0 ) ? Math.ceil( this.w ) : Math.floor( this.w );
4537 
4538  return this;
4539 
4540  },
4541 
4542  negate: function () {
4543 
4544  this.x = - this.x;
4545  this.y = - this.y;
4546  this.z = - this.z;
4547  this.w = - this.w;
4548 
4549  return this;
4550 
4551  },
4552 
4553  dot: function ( v ) {
4554 
4555  return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;
4556 
4557  },
4558 
4559  lengthSq: function () {
4560 
4561  return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
4562 
4563  },
4564 
4565  length: function () {
4566 
4567  return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w );
4568 
4569  },
4570 
4571  manhattanLength: function () {
4572 
4573  return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w );
4574 
4575  },
4576 
4577  normalize: function () {
4578 
4579  return this.divideScalar( this.length() || 1 );
4580 
4581  },
4582 
4583  setLength: function ( length ) {
4584 
4585  return this.normalize().multiplyScalar( length );
4586 
4587  },
4588 
4589  lerp: function ( v, alpha ) {
4590 
4591  this.x += ( v.x - this.x ) * alpha;
4592  this.y += ( v.y - this.y ) * alpha;
4593  this.z += ( v.z - this.z ) * alpha;
4594  this.w += ( v.w - this.w ) * alpha;
4595 
4596  return this;
4597 
4598  },
4599 
4600  lerpVectors: function ( v1, v2, alpha ) {
4601 
4602  return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );
4603 
4604  },
4605 
4606  equals: function ( v ) {
4607 
4608  return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) );
4609 
4610  },
4611 
4612  fromArray: function ( array, offset ) {
4613 
4614  if ( offset === undefined ) offset = 0;
4615 
4616  this.x = array[ offset ];
4617  this.y = array[ offset + 1 ];
4618  this.z = array[ offset + 2 ];
4619  this.w = array[ offset + 3 ];
4620 
4621  return this;
4622 
4623  },
4624 
4625  toArray: function ( array, offset ) {
4626 
4627  if ( array === undefined ) array = [];
4628  if ( offset === undefined ) offset = 0;
4629 
4630  array[ offset ] = this.x;
4631  array[ offset + 1 ] = this.y;
4632  array[ offset + 2 ] = this.z;
4633  array[ offset + 3 ] = this.w;
4634 
4635  return array;
4636 
4637  },
4638 
4639  fromBufferAttribute: function ( attribute, index, offset ) {
4640 
4641  if ( offset !== undefined ) {
4642 
4643  console.warn( 'THREE.Vector4: offset has been removed from .fromBufferAttribute().' );
4644 
4645  }
4646 
4647  this.x = attribute.getX( index );
4648  this.y = attribute.getY( index );
4649  this.z = attribute.getZ( index );
4650  this.w = attribute.getW( index );
4651 
4652  return this;
4653 
4654  }
4655 
4656  } );
4657 
4664  /*
4665  In options, we can specify:
4666  * Texture parameters for an auto-generated target texture
4667  * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers
4668  */
4669  function WebGLRenderTarget( width, height, options ) {
4670 
4671  this.width = width;
4672  this.height = height;
4673 
4674  this.scissor = new Vector4( 0, 0, width, height );
4675  this.scissorTest = false;
4676 
4677  this.viewport = new Vector4( 0, 0, width, height );
4678 
4679  options = options || {};
4680 
4681  this.texture = new Texture( undefined, undefined, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding );
4682 
4683  this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false;
4684  this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter;
4685 
4686  this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true;
4687  this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : true;
4688  this.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null;
4689 
4690  }
4691 
4692  WebGLRenderTarget.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
4693 
4694  constructor: WebGLRenderTarget,
4695 
4696  isWebGLRenderTarget: true,
4697 
4698  setSize: function ( width, height ) {
4699 
4700  if ( this.width !== width || this.height !== height ) {
4701 
4702  this.width = width;
4703  this.height = height;
4704 
4705  this.dispose();
4706 
4707  }
4708 
4709  this.viewport.set( 0, 0, width, height );
4710  this.scissor.set( 0, 0, width, height );
4711 
4712  },
4713 
4714  clone: function () {
4715 
4716  return new this.constructor().copy( this );
4717 
4718  },
4719 
4720  copy: function ( source ) {
4721 
4722  this.width = source.width;
4723  this.height = source.height;
4724 
4725  this.viewport.copy( source.viewport );
4726 
4727  this.texture = source.texture.clone();
4728 
4729  this.depthBuffer = source.depthBuffer;
4730  this.stencilBuffer = source.stencilBuffer;
4731  this.depthTexture = source.depthTexture;
4732 
4733  return this;
4734 
4735  },
4736 
4737  dispose: function () {
4738 
4739  this.dispatchEvent( { type: 'dispose' } );
4740 
4741  }
4742 
4743  } );
4744 
4750  function WebGLMultisampleRenderTarget( width, height, options ) {
4751 
4752  WebGLRenderTarget.call( this, width, height, options );
4753 
4754  this.samples = 4;
4755 
4756  }
4757 
4758  WebGLMultisampleRenderTarget.prototype = Object.assign( Object.create( WebGLRenderTarget.prototype ), {
4759 
4760  constructor: WebGLMultisampleRenderTarget,
4761 
4762  isWebGLMultisampleRenderTarget: true,
4763 
4764  copy: function ( source ) {
4765 
4766  WebGLRenderTarget.prototype.copy.call( this, source );
4767 
4768  this.samples = source.samples;
4769 
4770  return this;
4771 
4772  }
4773 
4774  } );
4775 
4780  function WebGLRenderTargetCube( width, height, options ) {
4781 
4782  WebGLRenderTarget.call( this, width, height, options );
4783 
4784  }
4785 
4786  WebGLRenderTargetCube.prototype = Object.create( WebGLRenderTarget.prototype );
4787  WebGLRenderTargetCube.prototype.constructor = WebGLRenderTargetCube;
4788 
4789  WebGLRenderTargetCube.prototype.isWebGLRenderTargetCube = true;
4790 
4795  function DataTexture( data, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) {
4796 
4797  Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
4798 
4799  this.image = { data: data, width: width, height: height };
4800 
4801  this.magFilter = magFilter !== undefined ? magFilter : NearestFilter;
4802  this.minFilter = minFilter !== undefined ? minFilter : NearestFilter;
4803 
4804  this.generateMipmaps = false;
4805  this.flipY = false;
4806  this.unpackAlignment = 1;
4807 
4808  }
4809 
4810  DataTexture.prototype = Object.create( Texture.prototype );
4811  DataTexture.prototype.constructor = DataTexture;
4812 
4813  DataTexture.prototype.isDataTexture = true;
4814 
4820  function Box3( min, max ) {
4821 
4822  this.min = ( min !== undefined ) ? min : new Vector3( + Infinity, + Infinity, + Infinity );
4823  this.max = ( max !== undefined ) ? max : new Vector3( - Infinity, - Infinity, - Infinity );
4824 
4825  }
4826 
4827  Object.assign( Box3.prototype, {
4828 
4829  isBox3: true,
4830 
4831  set: function ( min, max ) {
4832 
4833  this.min.copy( min );
4834  this.max.copy( max );
4835 
4836  return this;
4837 
4838  },
4839 
4840  setFromArray: function ( array ) {
4841 
4842  var minX = + Infinity;
4843  var minY = + Infinity;
4844  var minZ = + Infinity;
4845 
4846  var maxX = - Infinity;
4847  var maxY = - Infinity;
4848  var maxZ = - Infinity;
4849 
4850  for ( var i = 0, l = array.length; i < l; i += 3 ) {
4851 
4852  var x = array[ i ];
4853  var y = array[ i + 1 ];
4854  var z = array[ i + 2 ];
4855 
4856  if ( x < minX ) minX = x;
4857  if ( y < minY ) minY = y;
4858  if ( z < minZ ) minZ = z;
4859 
4860  if ( x > maxX ) maxX = x;
4861  if ( y > maxY ) maxY = y;
4862  if ( z > maxZ ) maxZ = z;
4863 
4864  }
4865 
4866  this.min.set( minX, minY, minZ );
4867  this.max.set( maxX, maxY, maxZ );
4868 
4869  return this;
4870 
4871  },
4872 
4873  setFromBufferAttribute: function ( attribute ) {
4874 
4875  var minX = + Infinity;
4876  var minY = + Infinity;
4877  var minZ = + Infinity;
4878 
4879  var maxX = - Infinity;
4880  var maxY = - Infinity;
4881  var maxZ = - Infinity;
4882 
4883  for ( var i = 0, l = attribute.count; i < l; i ++ ) {
4884 
4885  var x = attribute.getX( i );
4886  var y = attribute.getY( i );
4887  var z = attribute.getZ( i );
4888 
4889  if ( x < minX ) minX = x;
4890  if ( y < minY ) minY = y;
4891  if ( z < minZ ) minZ = z;
4892 
4893  if ( x > maxX ) maxX = x;
4894  if ( y > maxY ) maxY = y;
4895  if ( z > maxZ ) maxZ = z;
4896 
4897  }
4898 
4899  this.min.set( minX, minY, minZ );
4900  this.max.set( maxX, maxY, maxZ );
4901 
4902  return this;
4903 
4904  },
4905 
4906  setFromPoints: function ( points ) {
4907 
4908  this.makeEmpty();
4909 
4910  for ( var i = 0, il = points.length; i < il; i ++ ) {
4911 
4912  this.expandByPoint( points[ i ] );
4913 
4914  }
4915 
4916  return this;
4917 
4918  },
4919 
4920  setFromCenterAndSize: function () {
4921 
4922  var v1 = new Vector3();
4923 
4924  return function setFromCenterAndSize( center, size ) {
4925 
4926  var halfSize = v1.copy( size ).multiplyScalar( 0.5 );
4927 
4928  this.min.copy( center ).sub( halfSize );
4929  this.max.copy( center ).add( halfSize );
4930 
4931  return this;
4932 
4933  };
4934 
4935  }(),
4936 
4937  setFromObject: function ( object ) {
4938 
4939  this.makeEmpty();
4940 
4941  return this.expandByObject( object );
4942 
4943  },
4944 
4945  clone: function () {
4946 
4947  return new this.constructor().copy( this );
4948 
4949  },
4950 
4951  copy: function ( box ) {
4952 
4953  this.min.copy( box.min );
4954  this.max.copy( box.max );
4955 
4956  return this;
4957 
4958  },
4959 
4960  makeEmpty: function () {
4961 
4962  this.min.x = this.min.y = this.min.z = + Infinity;
4963  this.max.x = this.max.y = this.max.z = - Infinity;
4964 
4965  return this;
4966 
4967  },
4968 
4969  isEmpty: function () {
4970 
4971  // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
4972 
4973  return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ) || ( this.max.z < this.min.z );
4974 
4975  },
4976 
4977  getCenter: function ( target ) {
4978 
4979  if ( target === undefined ) {
4980 
4981  console.warn( 'THREE.Box3: .getCenter() target is now required' );
4982  target = new Vector3();
4983 
4984  }
4985 
4986  return this.isEmpty() ? target.set( 0, 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 );
4987 
4988  },
4989 
4990  getSize: function ( target ) {
4991 
4992  if ( target === undefined ) {
4993 
4994  console.warn( 'THREE.Box3: .getSize() target is now required' );
4995  target = new Vector3();
4996 
4997  }
4998 
4999  return this.isEmpty() ? target.set( 0, 0, 0 ) : target.subVectors( this.max, this.min );
5000 
5001  },
5002 
5003  expandByPoint: function ( point ) {
5004 
5005  this.min.min( point );
5006  this.max.max( point );
5007 
5008  return this;
5009 
5010  },
5011 
5012  expandByVector: function ( vector ) {
5013 
5014  this.min.sub( vector );
5015  this.max.add( vector );
5016 
5017  return this;
5018 
5019  },
5020 
5021  expandByScalar: function ( scalar ) {
5022 
5023  this.min.addScalar( - scalar );
5024  this.max.addScalar( scalar );
5025 
5026  return this;
5027 
5028  },
5029 
5030  expandByObject: function () {
5031 
5032  // Computes the world-axis-aligned bounding box of an object (including its children),
5033  // accounting for both the object's, and children's, world transforms
5034 
5035  var scope, i, l;
5036 
5037  var v1 = new Vector3();
5038 
5039  function traverse( node ) {
5040 
5041  var geometry = node.geometry;
5042 
5043  if ( geometry !== undefined ) {
5044 
5045  if ( geometry.isGeometry ) {
5046 
5047  var vertices = geometry.vertices;
5048 
5049  for ( i = 0, l = vertices.length; i < l; i ++ ) {
5050 
5051  v1.copy( vertices[ i ] );
5052  v1.applyMatrix4( node.matrixWorld );
5053 
5054  scope.expandByPoint( v1 );
5055 
5056  }
5057 
5058  } else if ( geometry.isBufferGeometry ) {
5059 
5060  var attribute = geometry.attributes.position;
5061 
5062  if ( attribute !== undefined ) {
5063 
5064  for ( i = 0, l = attribute.count; i < l; i ++ ) {
5065 
5066  v1.fromBufferAttribute( attribute, i ).applyMatrix4( node.matrixWorld );
5067 
5068  scope.expandByPoint( v1 );
5069 
5070  }
5071 
5072  }
5073 
5074  }
5075 
5076  }
5077 
5078  }
5079 
5080  return function expandByObject( object ) {
5081 
5082  scope = this;
5083 
5084  object.updateMatrixWorld( true );
5085 
5086  object.traverse( traverse );
5087 
5088  return this;
5089 
5090  };
5091 
5092  }(),
5093 
5094  containsPoint: function ( point ) {
5095 
5096  return point.x < this.min.x || point.x > this.max.x ||
5097  point.y < this.min.y || point.y > this.max.y ||
5098  point.z < this.min.z || point.z > this.max.z ? false : true;
5099 
5100  },
5101 
5102  containsBox: function ( box ) {
5103 
5104  return this.min.x <= box.min.x && box.max.x <= this.max.x &&
5105  this.min.y <= box.min.y && box.max.y <= this.max.y &&
5106  this.min.z <= box.min.z && box.max.z <= this.max.z;
5107 
5108  },
5109 
5110  getParameter: function ( point, target ) {
5111 
5112  // This can potentially have a divide by zero if the box
5113  // has a size dimension of 0.
5114 
5115  if ( target === undefined ) {
5116 
5117  console.warn( 'THREE.Box3: .getParameter() target is now required' );
5118  target = new Vector3();
5119 
5120  }
5121 
5122  return target.set(
5123  ( point.x - this.min.x ) / ( this.max.x - this.min.x ),
5124  ( point.y - this.min.y ) / ( this.max.y - this.min.y ),
5125  ( point.z - this.min.z ) / ( this.max.z - this.min.z )
5126  );
5127 
5128  },
5129 
5130  intersectsBox: function ( box ) {
5131 
5132  // using 6 splitting planes to rule out intersections.
5133  return box.max.x < this.min.x || box.min.x > this.max.x ||
5134  box.max.y < this.min.y || box.min.y > this.max.y ||
5135  box.max.z < this.min.z || box.min.z > this.max.z ? false : true;
5136 
5137  },
5138 
5139  intersectsSphere: ( function () {
5140 
5141  var closestPoint = new Vector3();
5142 
5143  return function intersectsSphere( sphere ) {
5144 
5145  // Find the point on the AABB closest to the sphere center.
5146  this.clampPoint( sphere.center, closestPoint );
5147 
5148  // If that point is inside the sphere, the AABB and sphere intersect.
5149  return closestPoint.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius );
5150 
5151  };
5152 
5153  } )(),
5154 
5155  intersectsPlane: function ( plane ) {
5156 
5157  // We compute the minimum and maximum dot product values. If those values
5158  // are on the same side (back or front) of the plane, then there is no intersection.
5159 
5160  var min, max;
5161 
5162  if ( plane.normal.x > 0 ) {
5163 
5164  min = plane.normal.x * this.min.x;
5165  max = plane.normal.x * this.max.x;
5166 
5167  } else {
5168 
5169  min = plane.normal.x * this.max.x;
5170  max = plane.normal.x * this.min.x;
5171 
5172  }
5173 
5174  if ( plane.normal.y > 0 ) {
5175 
5176  min += plane.normal.y * this.min.y;
5177  max += plane.normal.y * this.max.y;
5178 
5179  } else {
5180 
5181  min += plane.normal.y * this.max.y;
5182  max += plane.normal.y * this.min.y;
5183 
5184  }
5185 
5186  if ( plane.normal.z > 0 ) {
5187 
5188  min += plane.normal.z * this.min.z;
5189  max += plane.normal.z * this.max.z;
5190 
5191  } else {
5192 
5193  min += plane.normal.z * this.max.z;
5194  max += plane.normal.z * this.min.z;
5195 
5196  }
5197 
5198  return ( min <= - plane.constant && max >= - plane.constant );
5199 
5200  },
5201 
5202  intersectsTriangle: ( function () {
5203 
5204  // triangle centered vertices
5205  var v0 = new Vector3();
5206  var v1 = new Vector3();
5207  var v2 = new Vector3();
5208 
5209  // triangle edge vectors
5210  var f0 = new Vector3();
5211  var f1 = new Vector3();
5212  var f2 = new Vector3();
5213 
5214  var testAxis = new Vector3();
5215 
5216  var center = new Vector3();
5217  var extents = new Vector3();
5218 
5219  var triangleNormal = new Vector3();
5220 
5221  function satForAxes( axes ) {
5222 
5223  var i, j;
5224 
5225  for ( i = 0, j = axes.length - 3; i <= j; i += 3 ) {
5226 
5227  testAxis.fromArray( axes, i );
5228  // project the aabb onto the seperating axis
5229  var r = extents.x * Math.abs( testAxis.x ) + extents.y * Math.abs( testAxis.y ) + extents.z * Math.abs( testAxis.z );
5230  // project all 3 vertices of the triangle onto the seperating axis
5231  var p0 = v0.dot( testAxis );
5232  var p1 = v1.dot( testAxis );
5233  var p2 = v2.dot( testAxis );
5234  // actual test, basically see if either of the most extreme of the triangle points intersects r
5235  if ( Math.max( - Math.max( p0, p1, p2 ), Math.min( p0, p1, p2 ) ) > r ) {
5236 
5237  // points of the projected triangle are outside the projected half-length of the aabb
5238  // the axis is seperating and we can exit
5239  return false;
5240 
5241  }
5242 
5243  }
5244 
5245  return true;
5246 
5247  }
5248 
5249  return function intersectsTriangle( triangle ) {
5250 
5251  if ( this.isEmpty() ) {
5252 
5253  return false;
5254 
5255  }
5256 
5257  // compute box center and extents
5258  this.getCenter( center );
5259  extents.subVectors( this.max, center );
5260 
5261  // translate triangle to aabb origin
5262  v0.subVectors( triangle.a, center );
5263  v1.subVectors( triangle.b, center );
5264  v2.subVectors( triangle.c, center );
5265 
5266  // compute edge vectors for triangle
5267  f0.subVectors( v1, v0 );
5268  f1.subVectors( v2, v1 );
5269  f2.subVectors( v0, v2 );
5270 
5271  // test against axes that are given by cross product combinations of the edges of the triangle and the edges of the aabb
5272  // 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
5273  // axis_ij = u_i x f_j (u0, u1, u2 = face normals of aabb = x,y,z axes vectors since aabb is axis aligned)
5274  var axes = [
5275  0, - f0.z, f0.y, 0, - f1.z, f1.y, 0, - f2.z, f2.y,
5276  f0.z, 0, - f0.x, f1.z, 0, - f1.x, f2.z, 0, - f2.x,
5277  - f0.y, f0.x, 0, - f1.y, f1.x, 0, - f2.y, f2.x, 0
5278  ];
5279  if ( ! satForAxes( axes ) ) {
5280 
5281  return false;
5282 
5283  }
5284 
5285  // test 3 face normals from the aabb
5286  axes = [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ];
5287  if ( ! satForAxes( axes ) ) {
5288 
5289  return false;
5290 
5291  }
5292 
5293  // finally testing the face normal of the triangle
5294  // use already existing triangle edge vectors here
5295  triangleNormal.crossVectors( f0, f1 );
5296  axes = [ triangleNormal.x, triangleNormal.y, triangleNormal.z ];
5297  return satForAxes( axes );
5298 
5299  };
5300 
5301  } )(),
5302 
5303  clampPoint: function ( point, target ) {
5304 
5305  if ( target === undefined ) {
5306 
5307  console.warn( 'THREE.Box3: .clampPoint() target is now required' );
5308  target = new Vector3();
5309 
5310  }
5311 
5312  return target.copy( point ).clamp( this.min, this.max );
5313 
5314  },
5315 
5316  distanceToPoint: function () {
5317 
5318  var v1 = new Vector3();
5319 
5320  return function distanceToPoint( point ) {
5321 
5322  var clampedPoint = v1.copy( point ).clamp( this.min, this.max );
5323  return clampedPoint.sub( point ).length();
5324 
5325  };
5326 
5327  }(),
5328 
5329  getBoundingSphere: function () {
5330 
5331  var v1 = new Vector3();
5332 
5333  return function getBoundingSphere( target ) {
5334 
5335  if ( target === undefined ) {
5336 
5337  console.warn( 'THREE.Box3: .getBoundingSphere() target is now required' );
5338  target = new Sphere();
5339 
5340  }
5341 
5342  this.getCenter( target.center );
5343 
5344  target.radius = this.getSize( v1 ).length() * 0.5;
5345 
5346  return target;
5347 
5348  };
5349 
5350  }(),
5351 
5352  intersect: function ( box ) {
5353 
5354  this.min.max( box.min );
5355  this.max.min( box.max );
5356 
5357  // 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.
5358  if ( this.isEmpty() ) this.makeEmpty();
5359 
5360  return this;
5361 
5362  },
5363 
5364  union: function ( box ) {
5365 
5366  this.min.min( box.min );
5367  this.max.max( box.max );
5368 
5369  return this;
5370 
5371  },
5372 
5373  applyMatrix4: function () {
5374 
5375  var points = [
5376  new Vector3(),
5377  new Vector3(),
5378  new Vector3(),
5379  new Vector3(),
5380  new Vector3(),
5381  new Vector3(),
5382  new Vector3(),
5383  new Vector3()
5384  ];
5385 
5386  return function applyMatrix4( matrix ) {
5387 
5388  // transform of empty box is an empty box.
5389  if ( this.isEmpty() ) return this;
5390 
5391  // NOTE: I am using a binary pattern to specify all 2^3 combinations below
5392  points[ 0 ].set( this.min.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 000
5393  points[ 1 ].set( this.min.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 001
5394  points[ 2 ].set( this.min.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 010
5395  points[ 3 ].set( this.min.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 011
5396  points[ 4 ].set( this.max.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 100
5397  points[ 5 ].set( this.max.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 101
5398  points[ 6 ].set( this.max.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 110
5399  points[ 7 ].set( this.max.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 111
5400 
5401  this.setFromPoints( points );
5402 
5403  return this;
5404 
5405  };
5406 
5407  }(),
5408 
5409  translate: function ( offset ) {
5410 
5411  this.min.add( offset );
5412  this.max.add( offset );
5413 
5414  return this;
5415 
5416  },
5417 
5418  equals: function ( box ) {
5419 
5420  return box.min.equals( this.min ) && box.max.equals( this.max );
5421 
5422  }
5423 
5424  } );
5425 
5431  function Sphere( center, radius ) {
5432 
5433  this.center = ( center !== undefined ) ? center : new Vector3();
5434  this.radius = ( radius !== undefined ) ? radius : 0;
5435 
5436  }
5437 
5438  Object.assign( Sphere.prototype, {
5439 
5440  set: function ( center, radius ) {
5441 
5442  this.center.copy( center );
5443  this.radius = radius;
5444 
5445  return this;
5446 
5447  },
5448 
5449  setFromPoints: function () {
5450 
5451  var box = new Box3();
5452 
5453  return function setFromPoints( points, optionalCenter ) {
5454 
5455  var center = this.center;
5456 
5457  if ( optionalCenter !== undefined ) {
5458 
5459  center.copy( optionalCenter );
5460 
5461  } else {
5462 
5463  box.setFromPoints( points ).getCenter( center );
5464 
5465  }
5466 
5467  var maxRadiusSq = 0;
5468 
5469  for ( var i = 0, il = points.length; i < il; i ++ ) {
5470 
5471  maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( points[ i ] ) );
5472 
5473  }
5474 
5475  this.radius = Math.sqrt( maxRadiusSq );
5476 
5477  return this;
5478 
5479  };
5480 
5481  }(),
5482 
5483  clone: function () {
5484 
5485  return new this.constructor().copy( this );
5486 
5487  },
5488 
5489  copy: function ( sphere ) {
5490 
5491  this.center.copy( sphere.center );
5492  this.radius = sphere.radius;
5493 
5494  return this;
5495 
5496  },
5497 
5498  empty: function () {
5499 
5500  return ( this.radius <= 0 );
5501 
5502  },
5503 
5504  containsPoint: function ( point ) {
5505 
5506  return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) );
5507 
5508  },
5509 
5510  distanceToPoint: function ( point ) {
5511 
5512  return ( point.distanceTo( this.center ) - this.radius );
5513 
5514  },
5515 
5516  intersectsSphere: function ( sphere ) {
5517 
5518  var radiusSum = this.radius + sphere.radius;
5519 
5520  return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum );
5521 
5522  },
5523 
5524  intersectsBox: function ( box ) {
5525 
5526  return box.intersectsSphere( this );
5527 
5528  },
5529 
5530  intersectsPlane: function ( plane ) {
5531 
5532  return Math.abs( plane.distanceToPoint( this.center ) ) <= this.radius;
5533 
5534  },
5535 
5536  clampPoint: function ( point, target ) {
5537 
5538  var deltaLengthSq = this.center.distanceToSquared( point );
5539 
5540  if ( target === undefined ) {
5541 
5542  console.warn( 'THREE.Sphere: .clampPoint() target is now required' );
5543  target = new Vector3();
5544 
5545  }
5546 
5547  target.copy( point );
5548 
5549  if ( deltaLengthSq > ( this.radius * this.radius ) ) {
5550 
5551  target.sub( this.center ).normalize();
5552  target.multiplyScalar( this.radius ).add( this.center );
5553 
5554  }
5555 
5556  return target;
5557 
5558  },
5559 
5560  getBoundingBox: function ( target ) {
5561 
5562  if ( target === undefined ) {
5563 
5564  console.warn( 'THREE.Sphere: .getBoundingBox() target is now required' );
5565  target = new Box3();
5566 
5567  }
5568 
5569  target.set( this.center, this.center );
5570  target.expandByScalar( this.radius );
5571 
5572  return target;
5573 
5574  },
5575 
5576  applyMatrix4: function ( matrix ) {
5577 
5578  this.center.applyMatrix4( matrix );
5579  this.radius = this.radius * matrix.getMaxScaleOnAxis();
5580 
5581  return this;
5582 
5583  },
5584 
5585  translate: function ( offset ) {
5586 
5587  this.center.add( offset );
5588 
5589  return this;
5590 
5591  },
5592 
5593  equals: function ( sphere ) {
5594 
5595  return sphere.center.equals( this.center ) && ( sphere.radius === this.radius );
5596 
5597  }
5598 
5599  } );
5600 
5605  function Plane( normal, constant ) {
5606 
5607  // normal is assumed to be normalized
5608 
5609  this.normal = ( normal !== undefined ) ? normal : new Vector3( 1, 0, 0 );
5610  this.constant = ( constant !== undefined ) ? constant : 0;
5611 
5612  }
5613 
5614  Object.assign( Plane.prototype, {
5615 
5616  set: function ( normal, constant ) {
5617 
5618  this.normal.copy( normal );
5619  this.constant = constant;
5620 
5621  return this;
5622 
5623  },
5624 
5625  setComponents: function ( x, y, z, w ) {
5626 
5627  this.normal.set( x, y, z );
5628  this.constant = w;
5629 
5630  return this;
5631 
5632  },
5633 
5634  setFromNormalAndCoplanarPoint: function ( normal, point ) {
5635 
5636  this.normal.copy( normal );
5637  this.constant = - point.dot( this.normal );
5638 
5639  return this;
5640 
5641  },
5642 
5643  setFromCoplanarPoints: function () {
5644 
5645  var v1 = new Vector3();
5646  var v2 = new Vector3();
5647 
5648  return function setFromCoplanarPoints( a, b, c ) {
5649 
5650  var normal = v1.subVectors( c, b ).cross( v2.subVectors( a, b ) ).normalize();
5651 
5652  // Q: should an error be thrown if normal is zero (e.g. degenerate plane)?
5653 
5654  this.setFromNormalAndCoplanarPoint( normal, a );
5655 
5656  return this;
5657 
5658  };
5659 
5660  }(),
5661 
5662  clone: function () {
5663 
5664  return new this.constructor().copy( this );
5665 
5666  },
5667 
5668  copy: function ( plane ) {
5669 
5670  this.normal.copy( plane.normal );
5671  this.constant = plane.constant;
5672 
5673  return this;
5674 
5675  },
5676 
5677  normalize: function () {
5678 
5679  // Note: will lead to a divide by zero if the plane is invalid.
5680 
5681  var inverseNormalLength = 1.0 / this.normal.length();
5682  this.normal.multiplyScalar( inverseNormalLength );
5683  this.constant *= inverseNormalLength;
5684 
5685  return this;
5686 
5687  },
5688 
5689  negate: function () {
5690 
5691  this.constant *= - 1;
5692  this.normal.negate();
5693 
5694  return this;
5695 
5696  },
5697 
5698  distanceToPoint: function ( point ) {
5699 
5700  return this.normal.dot( point ) + this.constant;
5701 
5702  },
5703 
5704  distanceToSphere: function ( sphere ) {
5705 
5706  return this.distanceToPoint( sphere.center ) - sphere.radius;
5707 
5708  },
5709 
5710  projectPoint: function ( point, target ) {
5711 
5712  if ( target === undefined ) {
5713 
5714  console.warn( 'THREE.Plane: .projectPoint() target is now required' );
5715  target = new Vector3();
5716 
5717  }
5718 
5719  return target.copy( this.normal ).multiplyScalar( - this.distanceToPoint( point ) ).add( point );
5720 
5721  },
5722 
5723  intersectLine: function () {
5724 
5725  var v1 = new Vector3();
5726 
5727  return function intersectLine( line, target ) {
5728 
5729  if ( target === undefined ) {
5730 
5731  console.warn( 'THREE.Plane: .intersectLine() target is now required' );
5732  target = new Vector3();
5733 
5734  }
5735 
5736  var direction = line.delta( v1 );
5737 
5738  var denominator = this.normal.dot( direction );
5739 
5740  if ( denominator === 0 ) {
5741 
5742  // line is coplanar, return origin
5743  if ( this.distanceToPoint( line.start ) === 0 ) {
5744 
5745  return target.copy( line.start );
5746 
5747  }
5748 
5749  // Unsure if this is the correct method to handle this case.
5750  return undefined;
5751 
5752  }
5753 
5754  var t = - ( line.start.dot( this.normal ) + this.constant ) / denominator;
5755 
5756  if ( t < 0 || t > 1 ) {
5757 
5758  return undefined;
5759 
5760  }
5761 
5762  return target.copy( direction ).multiplyScalar( t ).add( line.start );
5763 
5764  };
5765 
5766  }(),
5767 
5768  intersectsLine: function ( line ) {
5769 
5770  // Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it.
5771 
5772  var startSign = this.distanceToPoint( line.start );
5773  var endSign = this.distanceToPoint( line.end );
5774 
5775  return ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 );
5776 
5777  },
5778 
5779  intersectsBox: function ( box ) {
5780 
5781  return box.intersectsPlane( this );
5782 
5783  },
5784 
5785  intersectsSphere: function ( sphere ) {
5786 
5787  return sphere.intersectsPlane( this );
5788 
5789  },
5790 
5791  coplanarPoint: function ( target ) {
5792 
5793  if ( target === undefined ) {
5794 
5795  console.warn( 'THREE.Plane: .coplanarPoint() target is now required' );
5796  target = new Vector3();
5797 
5798  }
5799 
5800  return target.copy( this.normal ).multiplyScalar( - this.constant );
5801 
5802  },
5803 
5804  applyMatrix4: function () {
5805 
5806  var v1 = new Vector3();
5807  var m1 = new Matrix3();
5808 
5809  return function applyMatrix4( matrix, optionalNormalMatrix ) {
5810 
5811  var normalMatrix = optionalNormalMatrix || m1.getNormalMatrix( matrix );
5812 
5813  var referencePoint = this.coplanarPoint( v1 ).applyMatrix4( matrix );
5814 
5815  var normal = this.normal.applyMatrix3( normalMatrix ).normalize();
5816 
5817  this.constant = - referencePoint.dot( normal );
5818 
5819  return this;
5820 
5821  };
5822 
5823  }(),
5824 
5825  translate: function ( offset ) {
5826 
5827  this.constant -= offset.dot( this.normal );
5828 
5829  return this;
5830 
5831  },
5832 
5833  equals: function ( plane ) {
5834 
5835  return plane.normal.equals( this.normal ) && ( plane.constant === this.constant );
5836 
5837  }
5838 
5839  } );
5840 
5847  function Frustum( p0, p1, p2, p3, p4, p5 ) {
5848 
5849  this.planes = [
5850 
5851  ( p0 !== undefined ) ? p0 : new Plane(),
5852  ( p1 !== undefined ) ? p1 : new Plane(),
5853  ( p2 !== undefined ) ? p2 : new Plane(),
5854  ( p3 !== undefined ) ? p3 : new Plane(),
5855  ( p4 !== undefined ) ? p4 : new Plane(),
5856  ( p5 !== undefined ) ? p5 : new Plane()
5857 
5858  ];
5859 
5860  }
5861 
5862  Object.assign( Frustum.prototype, {
5863 
5864  set: function ( p0, p1, p2, p3, p4, p5 ) {
5865 
5866  var planes = this.planes;
5867 
5868  planes[ 0 ].copy( p0 );
5869  planes[ 1 ].copy( p1 );
5870  planes[ 2 ].copy( p2 );
5871  planes[ 3 ].copy( p3 );
5872  planes[ 4 ].copy( p4 );
5873  planes[ 5 ].copy( p5 );
5874 
5875  return this;
5876 
5877  },
5878 
5879  clone: function () {
5880 
5881  return new this.constructor().copy( this );
5882 
5883  },
5884 
5885  copy: function ( frustum ) {
5886 
5887  var planes = this.planes;
5888 
5889  for ( var i = 0; i < 6; i ++ ) {
5890 
5891  planes[ i ].copy( frustum.planes[ i ] );
5892 
5893  }
5894 
5895  return this;
5896 
5897  },
5898 
5899  setFromMatrix: function ( m ) {
5900 
5901  var planes = this.planes;
5902  var me = m.elements;
5903  var me0 = me[ 0 ], me1 = me[ 1 ], me2 = me[ 2 ], me3 = me[ 3 ];
5904  var me4 = me[ 4 ], me5 = me[ 5 ], me6 = me[ 6 ], me7 = me[ 7 ];
5905  var me8 = me[ 8 ], me9 = me[ 9 ], me10 = me[ 10 ], me11 = me[ 11 ];
5906  var me12 = me[ 12 ], me13 = me[ 13 ], me14 = me[ 14 ], me15 = me[ 15 ];
5907 
5908  planes[ 0 ].setComponents( me3 - me0, me7 - me4, me11 - me8, me15 - me12 ).normalize();
5909  planes[ 1 ].setComponents( me3 + me0, me7 + me4, me11 + me8, me15 + me12 ).normalize();
5910  planes[ 2 ].setComponents( me3 + me1, me7 + me5, me11 + me9, me15 + me13 ).normalize();
5911  planes[ 3 ].setComponents( me3 - me1, me7 - me5, me11 - me9, me15 - me13 ).normalize();
5912  planes[ 4 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize();
5913  planes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize();
5914 
5915  return this;
5916 
5917  },
5918 
5919  intersectsObject: function () {
5920 
5921  var sphere = new Sphere();
5922 
5923  return function intersectsObject( object ) {
5924 
5925  var geometry = object.geometry;
5926 
5927  if ( geometry.boundingSphere === null )
5928  geometry.computeBoundingSphere();
5929 
5930  sphere.copy( geometry.boundingSphere )
5931  .applyMatrix4( object.matrixWorld );
5932 
5933  return this.intersectsSphere( sphere );
5934 
5935  };
5936 
5937  }(),
5938 
5939  intersectsSprite: function () {
5940 
5941  var sphere = new Sphere();
5942 
5943  return function intersectsSprite( sprite ) {
5944 
5945  sphere.center.set( 0, 0, 0 );
5946  sphere.radius = 0.7071067811865476;
5947  sphere.applyMatrix4( sprite.matrixWorld );
5948 
5949  return this.intersectsSphere( sphere );
5950 
5951  };
5952 
5953  }(),
5954 
5955  intersectsSphere: function ( sphere ) {
5956 
5957  var planes = this.planes;
5958  var center = sphere.center;
5959  var negRadius = - sphere.radius;
5960 
5961  for ( var i = 0; i < 6; i ++ ) {
5962 
5963  var distance = planes[ i ].distanceToPoint( center );
5964 
5965  if ( distance < negRadius ) {
5966 
5967  return false;
5968 
5969  }
5970 
5971  }
5972 
5973  return true;
5974 
5975  },
5976 
5977  intersectsBox: function () {
5978 
5979  var p = new Vector3();
5980 
5981  return function intersectsBox( box ) {
5982 
5983  var planes = this.planes;
5984 
5985  for ( var i = 0; i < 6; i ++ ) {
5986 
5987  var plane = planes[ i ];
5988 
5989  // corner at max distance
5990 
5991  p.x = plane.normal.x > 0 ? box.max.x : box.min.x;
5992  p.y = plane.normal.y > 0 ? box.max.y : box.min.y;
5993  p.z = plane.normal.z > 0 ? box.max.z : box.min.z;
5994 
5995  if ( plane.distanceToPoint( p ) < 0 ) {
5996 
5997  return false;
5998 
5999  }
6000 
6001  }
6002 
6003  return true;
6004 
6005  };
6006 
6007  }(),
6008 
6009  containsPoint: function ( point ) {
6010 
6011  var planes = this.planes;
6012 
6013  for ( var i = 0; i < 6; i ++ ) {
6014 
6015  if ( planes[ i ].distanceToPoint( point ) < 0 ) {
6016 
6017  return false;
6018 
6019  }
6020 
6021  }
6022 
6023  return true;
6024 
6025  }
6026 
6027  } );
6028 
6029  var alphamap_fragment = "#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vUv ).g;\n#endif";
6030 
6031  var alphamap_pars_fragment = "#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif";
6032 
6033  var alphatest_fragment = "#ifdef ALPHATEST\n\tif ( diffuseColor.a < ALPHATEST ) discard;\n#endif";
6034 
6035  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";
6036 
6037  var aomap_pars_fragment = "#ifdef USE_AOMAP\n\tuniform sampler2D aoMap;\n\tuniform float aoMapIntensity;\n#endif";
6038 
6039  var begin_vertex = "vec3 transformed = vec3( position );";
6040 
6041  var beginnormal_vertex = "vec3 objectNormal = vec3( normal );\n#ifdef USE_TANGENT\n\tvec3 objectTangent = vec3( tangent.xyz );\n#endif";
6042 
6043  var bsdfs = "vec2 integrateSpecularBRDF( const in float dotNV, const in float roughness ) {\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\treturn vec2( -1.04, 1.04 ) * a004 + r.zw;\n}\nfloat punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\tif( cutoffDistance > 0.0 ) {\n\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t}\n\treturn distanceFalloff;\n#else\n\tif( cutoffDistance > 0.0 && decayExponent > 0.0 ) {\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n\t}\n\treturn 1.0;\n#endif\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\tvec2 brdf = integrateSpecularBRDF( dotNV, roughness );\n\treturn specularColor * brdf.x + brdf.y;\n}\nvoid BRDF_Specular_Multiscattering_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tvec3 F = F_Schlick( specularColor, dotNV );\n\tvec2 brdf = integrateSpecularBRDF( dotNV, roughness );\n\tvec3 FssEss = F * brdf.x + brdf.y;\n\tfloat Ess = brdf.x + brdf.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = specularColor + ( 1.0 - specularColor ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\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}";
6044 
6045  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\tfDet *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );\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";
6046 
6047  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";
6048 
6049  var clipping_planes_pars_fragment = "#if NUM_CLIPPING_PLANES > 0\n\t#if ! defined( PHYSICAL ) && ! defined( PHONG ) && ! defined( MATCAP )\n\t\tvarying vec3 vViewPosition;\n\t#endif\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif";
6050 
6051  var clipping_planes_pars_vertex = "#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG ) && ! defined( MATCAP )\n\tvarying vec3 vViewPosition;\n#endif";
6052 
6053  var clipping_planes_vertex = "#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG ) && ! defined( MATCAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif";
6054 
6055  var color_fragment = "#ifdef USE_COLOR\n\tdiffuseColor.rgb *= vColor;\n#endif";
6056 
6057  var color_pars_fragment = "#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif";
6058 
6059  var color_pars_vertex = "#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif";
6060 
6061  var color_vertex = "#ifdef USE_COLOR\n\tvColor.xyz = color.xyz;\n#endif";
6062 
6063  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}";
6064 
6065  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( sampler2D envMap, 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";
6066 
6067  var defaultnormal_vertex = "vec3 transformedNormal = normalMatrix * objectNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n#ifdef USE_TANGENT\n\tvec3 transformedTangent = normalMatrix * objectTangent;\n\t#ifdef FLIP_SIDED\n\t\ttransformedTangent = - transformedTangent;\n\t#endif\n#endif";
6068 
6069  var displacementmap_pars_vertex = "#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif";
6070 
6071  var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, uv ).x * displacementScale + displacementBias );\n#endif";
6072 
6073  var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif";
6074 
6075  var emissivemap_pars_fragment = "#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif";
6076 
6077  var encodings_fragment = "gl_FragColor = linearToOutputTexel( gl_FragColor );";
6078 
6079  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.rgb, vec3( gammaFactor ) ), value.a );\n}\nvec4 LinearToGamma( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.rgb, vec3( 1.0 / gammaFactor ) ), value.a );\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.a );\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.a );\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.rgb * value.a * maxRange, 1.0 );\n}\nvec4 LinearToRGBM( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.r, 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.r, 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 = cLogLuvM * value.rgb;\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 = cLogLuvInverseM * Xp_Y_XYZp.rgb;\n\treturn vec4( max( vRGB, 0.0 ), 1.0 );\n}";
6080 
6081  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";
6082 
6083  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";
6084 
6085  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";
6086 
6087  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";
6088 
6089  var fog_vertex = "#ifdef USE_FOG\n\tfogDepth = -mvPosition.z;\n#endif";
6090 
6091  var fog_pars_vertex = "#ifdef USE_FOG\n\tvarying float fogDepth;\n#endif";
6092 
6093  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";
6094 
6095  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";
6096 
6097  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";
6098 
6099  var lightmap_fragment = "#ifdef USE_LIGHTMAP\n\treflectedLight.indirectDiffuse += PI * texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n#endif";
6100 
6101  var lightmap_pars_fragment = "#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif";
6102 
6103  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 );\nvIndirectFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n\tvLightBack = vec3( 0.0 );\n\tvIndirectBack = 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\tvIndirectFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvIndirectBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\n\t\t#endif\n\t}\n#endif";
6104 
6105  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";
6106 
6107  var envmap_physical_pars_fragment = "#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( envMap, 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( envMap, 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";
6108 
6109  var lights_phong_fragment = "BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;";
6110 
6111  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)";
6112 
6113  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";
6114 
6115  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\t#ifndef ENVMAP_TYPE_CUBE_UV\n\t\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\t#endif\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, 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\tfloat clearCoatInv = 1.0 - clearCoatDHR;\n\t#if defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec3 singleScattering = vec3( 0.0 );\n\t\tvec3 multiScattering = vec3( 0.0 );\n\t\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\t\tBRDF_Specular_Multiscattering_Environment( geometry, material.specularColor, material.specularRoughness, singleScattering, multiScattering );\n\t\tvec3 diffuse = material.diffuseColor;\n\t\treflectedLight.indirectSpecular += clearCoatInv * radiance * singleScattering;\n\t\treflectedLight.indirectDiffuse += multiScattering * cosineWeightedIrradiance;\n\t\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n\t#else\n\t\treflectedLight.indirectSpecular += clearCoatInv * radiance * BRDF_Specular_GGX_Environment( geometry, material.specularColor, material.specularRoughness );\n\t#endif\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}";
6116 
6117  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";
6118 
6119  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";
6120 
6121  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, irradiance, clearCoatRadiance, geometry, material, reflectedLight );\n#endif";
6122 
6123  var logdepthbuf_fragment = "#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif";
6124 
6125  var logdepthbuf_pars_fragment = "#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tuniform float logDepthBufFC;\n\tvarying float vFragDepth;\n#endif";
6126 
6127  var logdepthbuf_pars_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#else\n\t\tuniform float logDepthBufFC;\n\t#endif\n#endif";
6128 
6129  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";
6130 
6131  var map_fragment = "#ifdef USE_MAP\n\tvec4 texelColor = texture2D( map, vUv );\n\ttexelColor = mapTexelToLinear( texelColor );\n\tdiffuseColor *= texelColor;\n#endif";
6132 
6133  var map_pars_fragment = "#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif";
6134 
6135  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";
6136 
6137  var map_particle_pars_fragment = "#ifdef USE_MAP\n\tuniform mat3 uvTransform;\n\tuniform sampler2D map;\n#endif";
6138 
6139  var metalnessmap_fragment = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif";
6140 
6141  var metalnessmap_pars_fragment = "#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif";
6142 
6143  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";
6144 
6145  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";
6146 
6147  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";
6148 
6149  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\t#ifdef USE_TANGENT\n\t\tvec3 tangent = normalize( vTangent );\n\t\tvec3 bitangent = normalize( vBitangent );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\ttangent = tangent * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\t\tbitangent = bitangent * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\t#endif\n\t#endif\n#endif";
6150 
6151  var normal_fragment_maps = "#ifdef USE_NORMALMAP\n\t#ifdef OBJECTSPACE_NORMALMAP\n\t\tnormal = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t\t#ifdef FLIP_SIDED\n\t\t\tnormal = - normal;\n\t\t#endif\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tnormal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\t#endif\n\t\tnormal = normalize( normalMatrix * normal );\n\t#else\n\t\t#ifdef USE_TANGENT\n\t\t\tmat3 vTBN = mat3( tangent, bitangent, normal );\n\t\t\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t\t\tmapN.xy = normalScale * mapN.xy;\n\t\t\tnormal = normalize( vTBN * mapN );\n\t\t#else\n\t\t\tnormal = perturbNormal2Arb( -vViewPosition, normal );\n\t\t#endif\n\t#endif\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n#endif";
6152 
6153  var normalmap_pars_fragment = "#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n\t#ifdef OBJECTSPACE_NORMALMAP\n\t\tuniform mat3 normalMatrix;\n\t#else\n\t\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {\n\t\t\tvec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );\n\t\t\tvec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );\n\t\t\tvec2 st0 = dFdx( vUv.st );\n\t\t\tvec2 st1 = dFdy( vUv.st );\n\t\t\tfloat scale = sign( st1.t * st0.s - st0.t * st1.s );\n\t\t\tvec3 S = normalize( ( q0 * st1.t - q1 * st0.t ) * scale );\n\t\t\tvec3 T = normalize( ( - q0 * st1.s + q1 * st0.s ) * scale );\n\t\t\tvec3 N = normalize( surf_norm );\n\t\t\tmat3 tsn = mat3( S, T, N );\n\t\t\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t\t\tmapN.xy *= normalScale;\n\t\t\tmapN.xy *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\t\treturn normalize( tsn * mapN );\n\t\t}\n\t#endif\n#endif";
6154 
6155  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}";
6156 
6157  var premultiplied_alpha_fragment = "#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif";
6158 
6159  var project_vertex = "vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );\ngl_Position = projectionMatrix * mvPosition;";
6160 
6161  var dithering_fragment = "#if defined( DITHERING )\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif";
6162 
6163  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";
6164 
6165  var roughnessmap_fragment = "float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif";
6166 
6167  var roughnessmap_pars_fragment = "#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif";
6168 
6169  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";
6170 
6171  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";
6172 
6173  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";
6174 
6175  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}";
6176 
6177  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";
6178 
6179  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";
6180 
6181  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";
6182 
6183  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\t#ifdef USE_TANGENT\n\t\tobjectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#endif\n#endif";
6184 
6185  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";
6186 
6187  var specularmap_pars_fragment = "#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif";
6188 
6189  var tonemapping_fragment = "#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif";
6190 
6191  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}\nvec3 ACESFilmicToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( ( color * ( 2.51 * color + 0.03 ) ) / ( color * ( 2.43 * color + 0.59 ) + 0.14 ) );\n}";
6192 
6193  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";
6194 
6195  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";
6196 
6197  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";
6198 
6199  var uv2_pars_fragment = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif";
6200 
6201  var uv2_pars_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tattribute vec2 uv2;\n\tvarying vec2 vUv2;\n#endif";
6202 
6203  var uv2_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = uv2;\n#endif";
6204 
6205  var worldpos_vertex = "#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )\n\tvec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );\n#endif";
6206 
6207  var background_frag = "uniform sampler2D t2D;\nvarying vec2 vUv;\nvoid main() {\n\tvec4 texColor = texture2D( t2D, vUv );\n\tgl_FragColor = mapTexelToLinear( texColor );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n}";
6208 
6209  var background_vert = "varying vec2 vUv;\nuniform mat3 uvTransform;\nvoid main() {\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\tgl_Position = vec4( position.xy, 1.0, 1.0 );\n}";
6210 
6211  var cube_frag = "uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldDirection;\nvoid main() {\n\tvec4 texColor = textureCube( tCube, vec3( tFlip * vWorldDirection.x, vWorldDirection.yz ) );\n\tgl_FragColor = mapTexelToLinear( texColor );\n\tgl_FragColor.a *= opacity;\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n}";
6212 
6213  var cube_vert = "varying vec3 vWorldDirection;\n#include <common>\nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include <begin_vertex>\n\t#include <project_vertex>\n\tgl_Position.z = gl_Position.w;\n}";
6214 
6215  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}";
6216 
6217  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}";
6218 
6219  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}";
6220 
6221  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}";
6222 
6223  var equirect_frag = "uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include <common>\nvoid main() {\n\tvec3 direction = normalize( vWorldDirection );\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\tvec4 texColor = texture2D( tEquirect, sampleUV );\n\tgl_FragColor = mapTexelToLinear( texColor );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n}";
6224 
6225  var equirect_vert = "varying vec3 vWorldDirection;\n#include <common>\nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include <begin_vertex>\n\t#include <project_vertex>\n}";
6226 
6227  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}";
6228 
6229  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}";
6230 
6231  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}";
6232 
6233  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}";
6234 
6235  var meshlambert_frag = "uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\nvarying vec3 vIndirectFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n\tvarying vec3 vIndirectBack;\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 <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#ifdef DOUBLE_SIDED\n\t\treflectedLight.indirectDiffuse += ( gl_FrontFacing ) ? vIndirectFront : vIndirectBack;\n\t#else\n\t\treflectedLight.indirectDiffuse += vIndirectFront;\n\t#endif\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}";
6236 
6237  var meshlambert_vert = "#define LAMBERT\nvarying vec3 vLightFront;\nvarying vec3 vIndirectFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n\tvarying vec3 vIndirectBack;\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 <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}";
6238 
6239  var meshmatcap_frag = "#define MATCAP\nuniform vec3 diffuse;\nuniform float opacity;\nuniform sampler2D matcap;\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <fog_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\tvec3 viewDir = normalize( vViewPosition );\n\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n\tvec3 y = cross( viewDir, x );\n\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;\n\t#ifdef USE_MATCAP\n\t\tvec4 matcapColor = texture2D( matcap, uv );\n\t\tmatcapColor = matcapTexelToLinear( matcapColor );\n\t#else\n\t\tvec4 matcapColor = vec4( 1.0 );\n\t#endif\n\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.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}";
6240 
6241  var meshmatcap_vert = "#define MATCAP\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_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 <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#ifndef FLAT_SHADED\n\t\tvNormal = normalize( transformedNormal );\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\t#include <fog_vertex>\n\tvViewPosition = - mvPosition.xyz;\n}";
6242 
6243  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_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}";
6244 
6245  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}";
6246 
6247  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\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\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 <bsdfs>\n#include <cube_uv_reflection_fragment>\n#include <envmap_pars_fragment>\n#include <envmap_physical_pars_fragment>\n#include <fog_pars_fragment>\n#include <lights_pars_begin>\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}";
6248 
6249  var meshphysical_vert = "#define PHYSICAL\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif\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\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\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}";
6250 
6251  var normal_frag = "#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || ( defined( USE_NORMALMAP ) && ! defined( OBJECTSPACE_NORMALMAP ) )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif\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}";
6252 
6253  var normal_vert = "#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || ( defined( USE_NORMALMAP ) && ! defined( OBJECTSPACE_NORMALMAP ) )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif\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\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\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 ) && ! defined( OBJECTSPACE_NORMALMAP ) )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}";
6254 
6255  var points_frag = "uniform vec3 diffuse;\nuniform float opacity;\n#include <common>\n#include <color_pars_fragment>\n#include <map_particle_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_particle_fragment>\n\t#include <color_fragment>\n\t#include <alphatest_fragment>\n\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}";
6256 
6257  var points_vert = "uniform float size;\nuniform float scale;\n#include <common>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <color_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <project_vertex>\n\tgl_PointSize = size;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = ( projectionMatrix[ 2 ][ 3 ] == - 1.0 );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <worldpos_vertex>\n\t#include <fog_vertex>\n}";
6258 
6259  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}";
6260 
6261  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}";
6262 
6263  var sprite_frag = "uniform vec3 diffuse;\nuniform float opacity;\n#include <common>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <alphatest_fragment>\n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n}";
6264 
6265  var sprite_vert = "uniform float rotation;\nuniform vec2 center;\n#include <common>\n#include <uv_pars_vertex>\n#include <fog_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\tvec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\n\tvec2 scale;\n\tscale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );\n\tscale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );\n\t#ifndef USE_SIZEATTENUATION\n\t\tbool isPerspective = ( projectionMatrix[ 2 ][ 3 ] == - 1.0 );\n\t\tif ( isPerspective ) scale *= - mvPosition.z;\n\t#endif\n\tvec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale;\n\tvec2 rotatedPosition;\n\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\n\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\n\tmvPosition.xy += rotatedPosition;\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n}";
6266 
6267  var ShaderChunk = {
6268  alphamap_fragment: alphamap_fragment,
6269  alphamap_pars_fragment: alphamap_pars_fragment,
6270  alphatest_fragment: alphatest_fragment,
6271  aomap_fragment: aomap_fragment,
6272  aomap_pars_fragment: aomap_pars_fragment,
6273  begin_vertex: begin_vertex,
6274  beginnormal_vertex: beginnormal_vertex,
6275  bsdfs: bsdfs,
6276  bumpmap_pars_fragment: bumpmap_pars_fragment,
6277  clipping_planes_fragment: clipping_planes_fragment,
6278  clipping_planes_pars_fragment: clipping_planes_pars_fragment,
6279  clipping_planes_pars_vertex: clipping_planes_pars_vertex,
6280  clipping_planes_vertex: clipping_planes_vertex,
6281  color_fragment: color_fragment,
6282  color_pars_fragment: color_pars_fragment,
6283  color_pars_vertex: color_pars_vertex,
6284  color_vertex: color_vertex,
6285  common: common,
6286  cube_uv_reflection_fragment: cube_uv_reflection_fragment,
6287  defaultnormal_vertex: defaultnormal_vertex,
6288  displacementmap_pars_vertex: displacementmap_pars_vertex,
6289  displacementmap_vertex: displacementmap_vertex,
6290  emissivemap_fragment: emissivemap_fragment,
6291  emissivemap_pars_fragment: emissivemap_pars_fragment,
6292  encodings_fragment: encodings_fragment,
6293  encodings_pars_fragment: encodings_pars_fragment,
6294  envmap_fragment: envmap_fragment,
6295  envmap_pars_fragment: envmap_pars_fragment,
6296  envmap_pars_vertex: envmap_pars_vertex,
6297  envmap_physical_pars_fragment: envmap_physical_pars_fragment,
6298  envmap_vertex: envmap_vertex,
6299  fog_vertex: fog_vertex,
6300  fog_pars_vertex: fog_pars_vertex,
6301  fog_fragment: fog_fragment,
6302  fog_pars_fragment: fog_pars_fragment,
6303  gradientmap_pars_fragment: gradientmap_pars_fragment,
6304  lightmap_fragment: lightmap_fragment,
6305  lightmap_pars_fragment: lightmap_pars_fragment,
6306  lights_lambert_vertex: lights_lambert_vertex,
6307  lights_pars_begin: lights_pars_begin,
6308  lights_phong_fragment: lights_phong_fragment,
6309  lights_phong_pars_fragment: lights_phong_pars_fragment,
6310  lights_physical_fragment: lights_physical_fragment,
6311  lights_physical_pars_fragment: lights_physical_pars_fragment,
6312  lights_fragment_begin: lights_fragment_begin,
6313  lights_fragment_maps: lights_fragment_maps,
6314  lights_fragment_end: lights_fragment_end,
6315  logdepthbuf_fragment: logdepthbuf_fragment,
6316  logdepthbuf_pars_fragment: logdepthbuf_pars_fragment,
6317  logdepthbuf_pars_vertex: logdepthbuf_pars_vertex,
6318  logdepthbuf_vertex: logdepthbuf_vertex,
6319  map_fragment: map_fragment,
6320  map_pars_fragment: map_pars_fragment,
6321  map_particle_fragment: map_particle_fragment,
6322  map_particle_pars_fragment: map_particle_pars_fragment,
6323  metalnessmap_fragment: metalnessmap_fragment,
6324  metalnessmap_pars_fragment: metalnessmap_pars_fragment,
6325  morphnormal_vertex: morphnormal_vertex,
6326  morphtarget_pars_vertex: morphtarget_pars_vertex,
6327  morphtarget_vertex: morphtarget_vertex,
6328  normal_fragment_begin: normal_fragment_begin,
6329  normal_fragment_maps: normal_fragment_maps,
6330  normalmap_pars_fragment: normalmap_pars_fragment,
6331  packing: packing,
6332  premultiplied_alpha_fragment: premultiplied_alpha_fragment,
6333  project_vertex: project_vertex,
6334  dithering_fragment: dithering_fragment,
6335  dithering_pars_fragment: dithering_pars_fragment,
6336  roughnessmap_fragment: roughnessmap_fragment,
6337  roughnessmap_pars_fragment: roughnessmap_pars_fragment,
6338  shadowmap_pars_fragment: shadowmap_pars_fragment,
6339  shadowmap_pars_vertex: shadowmap_pars_vertex,
6340  shadowmap_vertex: shadowmap_vertex,
6341  shadowmask_pars_fragment: shadowmask_pars_fragment,
6342  skinbase_vertex: skinbase_vertex,
6343  skinning_pars_vertex: skinning_pars_vertex,
6344  skinning_vertex: skinning_vertex,
6345  skinnormal_vertex: skinnormal_vertex,
6346  specularmap_fragment: specularmap_fragment,
6347  specularmap_pars_fragment: specularmap_pars_fragment,
6348  tonemapping_fragment: tonemapping_fragment,
6349  tonemapping_pars_fragment: tonemapping_pars_fragment,
6350  uv_pars_fragment: uv_pars_fragment,
6351  uv_pars_vertex: uv_pars_vertex,
6352  uv_vertex: uv_vertex,
6353  uv2_pars_fragment: uv2_pars_fragment,
6354  uv2_pars_vertex: uv2_pars_vertex,
6355  uv2_vertex: uv2_vertex,
6356  worldpos_vertex: worldpos_vertex,
6357 
6358  background_frag: background_frag,
6359  background_vert: background_vert,
6360  cube_frag: cube_frag,
6361  cube_vert: cube_vert,
6362  depth_frag: depth_frag,
6363  depth_vert: depth_vert,
6364  distanceRGBA_frag: distanceRGBA_frag,
6365  distanceRGBA_vert: distanceRGBA_vert,
6366  equirect_frag: equirect_frag,
6367  equirect_vert: equirect_vert,
6368  linedashed_frag: linedashed_frag,
6369  linedashed_vert: linedashed_vert,
6370  meshbasic_frag: meshbasic_frag,
6371  meshbasic_vert: meshbasic_vert,
6372  meshlambert_frag: meshlambert_frag,
6373  meshlambert_vert: meshlambert_vert,
6374  meshmatcap_frag: meshmatcap_frag,
6375  meshmatcap_vert: meshmatcap_vert,
6376  meshphong_frag: meshphong_frag,
6377  meshphong_vert: meshphong_vert,
6378  meshphysical_frag: meshphysical_frag,
6379  meshphysical_vert: meshphysical_vert,
6380  normal_frag: normal_frag,
6381  normal_vert: normal_vert,
6382  points_frag: points_frag,
6383  points_vert: points_vert,
6384  shadow_frag: shadow_frag,
6385  shadow_vert: shadow_vert,
6386  sprite_frag: sprite_frag,
6387  sprite_vert: sprite_vert
6388  };
6389 
6394  function cloneUniforms( src ) {
6395 
6396  var dst = {};
6397 
6398  for ( var u in src ) {
6399 
6400  dst[ u ] = {};
6401 
6402  for ( var p in src[ u ] ) {
6403 
6404  var property = src[ u ][ p ];
6405 
6406  if ( property && ( property.isColor ||
6407  property.isMatrix3 || property.isMatrix4 ||
6408  property.isVector2 || property.isVector3 || property.isVector4 ||
6409  property.isTexture ) ) {
6410 
6411  dst[ u ][ p ] = property.clone();
6412 
6413  } else if ( Array.isArray( property ) ) {
6414 
6415  dst[ u ][ p ] = property.slice();
6416 
6417  } else {
6418 
6419  dst[ u ][ p ] = property;
6420 
6421  }
6422 
6423  }
6424 
6425  }
6426 
6427  return dst;
6428 
6429  }
6430 
6431  function mergeUniforms( uniforms ) {
6432 
6433  var merged = {};
6434 
6435  for ( var u = 0; u < uniforms.length; u ++ ) {
6436 
6437  var tmp = cloneUniforms( uniforms[ u ] );
6438 
6439  for ( var p in tmp ) {
6440 
6441  merged[ p ] = tmp[ p ];
6442 
6443  }
6444 
6445  }
6446 
6447  return merged;
6448 
6449  }
6450 
6451  // Legacy
6452 
6453  var UniformsUtils = { clone: cloneUniforms, merge: mergeUniforms };
6454 
6459  var ColorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF,
6460  'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2,
6461  'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50,
6462  'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B,
6463  'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B,
6464  'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F,
6465  'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3,
6466  'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222,
6467  'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700,
6468  'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4,
6469  'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00,
6470  'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3,
6471  'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA,
6472  'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32,
6473  'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3,
6474  'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC,
6475  'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD,
6476  'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6,
6477  'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9,
6478  'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F,
6479  'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE,
6480  'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA,
6481  'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0,
6482  'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 };
6483 
6484  function Color( r, g, b ) {
6485 
6486  if ( g === undefined && b === undefined ) {
6487 
6488  // r is THREE.Color, hex or string
6489  return this.set( r );
6490 
6491  }
6492 
6493  return this.setRGB( r, g, b );
6494 
6495  }
6496 
6497  Object.assign( Color.prototype, {
6498 
6499  isColor: true,
6500 
6501  r: 1, g: 1, b: 1,
6502 
6503  set: function ( value ) {
6504 
6505  if ( value && value.isColor ) {
6506 
6507  this.copy( value );
6508 
6509  } else if ( typeof value === 'number' ) {
6510 
6511  this.setHex( value );
6512 
6513  } else if ( typeof value === 'string' ) {
6514 
6515  this.setStyle( value );
6516 
6517  }
6518 
6519  return this;
6520 
6521  },
6522 
6523  setScalar: function ( scalar ) {
6524 
6525  this.r = scalar;
6526  this.g = scalar;
6527  this.b = scalar;
6528 
6529  return this;
6530 
6531  },
6532 
6533  setHex: function ( hex ) {
6534 
6535  hex = Math.floor( hex );
6536 
6537  this.r = ( hex >> 16 & 255 ) / 255;
6538  this.g = ( hex >> 8 & 255 ) / 255;
6539  this.b = ( hex & 255 ) / 255;
6540 
6541  return this;
6542 
6543  },
6544 
6545  setRGB: function ( r, g, b ) {
6546 
6547  this.r = r;
6548  this.g = g;
6549  this.b = b;
6550 
6551  return this;
6552 
6553  },
6554 
6555  setHSL: function () {
6556 
6557  function hue2rgb( p, q, t ) {
6558 
6559  if ( t < 0 ) t += 1;
6560  if ( t > 1 ) t -= 1;
6561  if ( t < 1 / 6 ) return p + ( q - p ) * 6 * t;
6562  if ( t < 1 / 2 ) return q;
6563  if ( t < 2 / 3 ) return p + ( q - p ) * 6 * ( 2 / 3 - t );
6564  return p;
6565 
6566  }
6567 
6568  return function setHSL( h, s, l ) {
6569 
6570  // h,s,l ranges are in 0.0 - 1.0
6571  h = _Math.euclideanModulo( h, 1 );
6572  s = _Math.clamp( s, 0, 1 );
6573  l = _Math.clamp( l, 0, 1 );
6574 
6575  if ( s === 0 ) {
6576 
6577  this.r = this.g = this.b = l;
6578 
6579  } else {
6580 
6581  var p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s );
6582  var q = ( 2 * l ) - p;
6583 
6584  this.r = hue2rgb( q, p, h + 1 / 3 );
6585  this.g = hue2rgb( q, p, h );
6586  this.b = hue2rgb( q, p, h - 1 / 3 );
6587 
6588  }
6589 
6590  return this;
6591 
6592  };
6593 
6594  }(),
6595 
6596  setStyle: function ( style ) {
6597 
6598  function handleAlpha( string ) {
6599 
6600  if ( string === undefined ) return;
6601 
6602  if ( parseFloat( string ) < 1 ) {
6603 
6604  console.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' );
6605 
6606  }
6607 
6608  }
6609 
6610 
6611  var m;
6612 
6613  if ( m = /^((?:rgb|hsl)a?)\(\s*([^\)]*)\)/.exec( style ) ) {
6614 
6615  // rgb / hsl
6616 
6617  var color;
6618  var name = m[ 1 ];
6619  var components = m[ 2 ];
6620 
6621  switch ( name ) {
6622 
6623  case 'rgb':
6624  case 'rgba':
6625 
6626  if ( color = /^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) {
6627 
6628  // rgb(255,0,0) rgba(255,0,0,0.5)
6629  this.r = Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255;
6630  this.g = Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255;
6631  this.b = Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255;
6632 
6633  handleAlpha( color[ 5 ] );
6634 
6635  return this;
6636 
6637  }
6638 
6639  if ( color = /^(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) {
6640 
6641  // rgb(100%,0%,0%) rgba(100%,0%,0%,0.5)
6642  this.r = Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100;
6643  this.g = Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100;
6644  this.b = Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100;
6645 
6646  handleAlpha( color[ 5 ] );
6647 
6648  return this;
6649 
6650  }
6651 
6652  break;
6653 
6654  case 'hsl':
6655  case 'hsla':
6656 
6657  if ( color = /^([0-9]*\.?[0-9]+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) {
6658 
6659  // hsl(120,50%,50%) hsla(120,50%,50%,0.5)
6660  var h = parseFloat( color[ 1 ] ) / 360;
6661  var s = parseInt( color[ 2 ], 10 ) / 100;
6662  var l = parseInt( color[ 3 ], 10 ) / 100;
6663 
6664  handleAlpha( color[ 5 ] );
6665 
6666  return this.setHSL( h, s, l );
6667 
6668  }
6669 
6670  break;
6671 
6672  }
6673 
6674  } else if ( m = /^\#([A-Fa-f0-9]+)$/.exec( style ) ) {
6675 
6676  // hex color
6677 
6678  var hex = m[ 1 ];
6679  var size = hex.length;
6680 
6681  if ( size === 3 ) {
6682 
6683  // #ff0
6684  this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 0 ), 16 ) / 255;
6685  this.g = parseInt( hex.charAt( 1 ) + hex.charAt( 1 ), 16 ) / 255;
6686  this.b = parseInt( hex.charAt( 2 ) + hex.charAt( 2 ), 16 ) / 255;
6687 
6688  return this;
6689 
6690  } else if ( size === 6 ) {
6691 
6692  // #ff0000
6693  this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 1 ), 16 ) / 255;
6694  this.g = parseInt( hex.charAt( 2 ) + hex.charAt( 3 ), 16 ) / 255;
6695  this.b = parseInt( hex.charAt( 4 ) + hex.charAt( 5 ), 16 ) / 255;
6696 
6697  return this;
6698 
6699  }
6700 
6701  }
6702 
6703  if ( style && style.length > 0 ) {
6704 
6705  // color keywords
6706  var hex = ColorKeywords[ style ];
6707 
6708  if ( hex !== undefined ) {
6709 
6710  // red
6711  this.setHex( hex );
6712 
6713  } else {
6714 
6715  // unknown color
6716  console.warn( 'THREE.Color: Unknown color ' + style );
6717 
6718  }
6719 
6720  }
6721 
6722  return this;
6723 
6724  },
6725 
6726  clone: function () {
6727 
6728  return new this.constructor( this.r, this.g, this.b );
6729 
6730  },
6731 
6732  copy: function ( color ) {
6733 
6734  this.r = color.r;
6735  this.g = color.g;
6736  this.b = color.b;
6737 
6738  return this;
6739 
6740  },
6741 
6742  copyGammaToLinear: function ( color, gammaFactor ) {
6743 
6744  if ( gammaFactor === undefined ) gammaFactor = 2.0;
6745 
6746  this.r = Math.pow( color.r, gammaFactor );
6747  this.g = Math.pow( color.g, gammaFactor );
6748  this.b = Math.pow( color.b, gammaFactor );
6749 
6750  return this;
6751 
6752  },
6753 
6754  copyLinearToGamma: function ( color, gammaFactor ) {
6755 
6756  if ( gammaFactor === undefined ) gammaFactor = 2.0;
6757 
6758  var safeInverse = ( gammaFactor > 0 ) ? ( 1.0 / gammaFactor ) : 1.0;
6759 
6760  this.r = Math.pow( color.r, safeInverse );
6761  this.g = Math.pow( color.g, safeInverse );
6762  this.b = Math.pow( color.b, safeInverse );
6763 
6764  return this;
6765 
6766  },
6767 
6768  convertGammaToLinear: function ( gammaFactor ) {
6769 
6770  this.copyGammaToLinear( this, gammaFactor );
6771 
6772  return this;
6773 
6774  },
6775 
6776  convertLinearToGamma: function ( gammaFactor ) {
6777 
6778  this.copyLinearToGamma( this, gammaFactor );
6779 
6780  return this;
6781 
6782  },
6783 
6784  copySRGBToLinear: function () {
6785 
6786  function SRGBToLinear( c ) {
6787 
6788  return ( c < 0.04045 ) ? c * 0.0773993808 : Math.pow( c * 0.9478672986 + 0.0521327014, 2.4 );
6789 
6790  }
6791 
6792  return function copySRGBToLinear( color ) {
6793 
6794  this.r = SRGBToLinear( color.r );
6795  this.g = SRGBToLinear( color.g );
6796  this.b = SRGBToLinear( color.b );
6797 
6798  return this;
6799 
6800  };
6801 
6802  }(),
6803 
6804  copyLinearToSRGB: function () {
6805 
6806  function LinearToSRGB( c ) {
6807 
6808  return ( c < 0.0031308 ) ? c * 12.92 : 1.055 * ( Math.pow( c, 0.41666 ) ) - 0.055;
6809 
6810  }
6811 
6812  return function copyLinearToSRGB( color ) {
6813 
6814  this.r = LinearToSRGB( color.r );
6815  this.g = LinearToSRGB( color.g );
6816  this.b = LinearToSRGB( color.b );
6817 
6818  return this;
6819 
6820  };
6821 
6822  }(),
6823 
6824  convertSRGBToLinear: function () {
6825 
6826  this.copySRGBToLinear( this );
6827 
6828  return this;
6829 
6830  },
6831 
6832  convertLinearToSRGB: function () {
6833 
6834  this.copyLinearToSRGB( this );
6835 
6836  return this;
6837 
6838  },
6839 
6840  getHex: function () {
6841 
6842  return ( this.r * 255 ) << 16 ^ ( this.g * 255 ) << 8 ^ ( this.b * 255 ) << 0;
6843 
6844  },
6845 
6846  getHexString: function () {
6847 
6848  return ( '000000' + this.getHex().toString( 16 ) ).slice( - 6 );
6849 
6850  },
6851 
6852  getHSL: function ( target ) {
6853 
6854  // h,s,l ranges are in 0.0 - 1.0
6855 
6856  if ( target === undefined ) {
6857 
6858  console.warn( 'THREE.Color: .getHSL() target is now required' );
6859  target = { h: 0, s: 0, l: 0 };
6860 
6861  }
6862 
6863  var r = this.r, g = this.g, b = this.b;
6864 
6865  var max = Math.max( r, g, b );
6866  var min = Math.min( r, g, b );
6867 
6868  var hue, saturation;
6869  var lightness = ( min + max ) / 2.0;
6870 
6871  if ( min === max ) {
6872 
6873  hue = 0;
6874  saturation = 0;
6875 
6876  } else {
6877 
6878  var delta = max - min;
6879 
6880  saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min );
6881 
6882  switch ( max ) {
6883 
6884  case r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break;
6885  case g: hue = ( b - r ) / delta + 2; break;
6886  case b: hue = ( r - g ) / delta + 4; break;
6887 
6888  }
6889 
6890  hue /= 6;
6891 
6892  }
6893 
6894  target.h = hue;
6895  target.s = saturation;
6896  target.l = lightness;
6897 
6898  return target;
6899 
6900  },
6901 
6902  getStyle: function () {
6903 
6904  return 'rgb(' + ( ( this.r * 255 ) | 0 ) + ',' + ( ( this.g * 255 ) | 0 ) + ',' + ( ( this.b * 255 ) | 0 ) + ')';
6905 
6906  },
6907 
6908  offsetHSL: function () {
6909 
6910  var hsl = {};
6911 
6912  return function ( h, s, l ) {
6913 
6914  this.getHSL( hsl );
6915 
6916  hsl.h += h; hsl.s += s; hsl.l += l;
6917 
6918  this.setHSL( hsl.h, hsl.s, hsl.l );
6919 
6920  return this;
6921 
6922  };
6923 
6924  }(),
6925 
6926  add: function ( color ) {
6927 
6928  this.r += color.r;
6929  this.g += color.g;
6930  this.b += color.b;
6931 
6932  return this;
6933 
6934  },
6935 
6936  addColors: function ( color1, color2 ) {
6937 
6938  this.r = color1.r + color2.r;
6939  this.g = color1.g + color2.g;
6940  this.b = color1.b + color2.b;
6941 
6942  return this;
6943 
6944  },
6945 
6946  addScalar: function ( s ) {
6947 
6948  this.r += s;
6949  this.g += s;
6950  this.b += s;
6951 
6952  return this;
6953 
6954  },
6955 
6956  sub: function ( color ) {
6957 
6958  this.r = Math.max( 0, this.r - color.r );
6959  this.g = Math.max( 0, this.g - color.g );
6960  this.b = Math.max( 0, this.b - color.b );
6961 
6962  return this;
6963 
6964  },
6965 
6966  multiply: function ( color ) {
6967 
6968  this.r *= color.r;
6969  this.g *= color.g;
6970  this.b *= color.b;
6971 
6972  return this;
6973 
6974  },
6975 
6976  multiplyScalar: function ( s ) {
6977 
6978  this.r *= s;
6979  this.g *= s;
6980  this.b *= s;
6981 
6982  return this;
6983 
6984  },
6985 
6986  lerp: function ( color, alpha ) {
6987 
6988  this.r += ( color.r - this.r ) * alpha;
6989  this.g += ( color.g - this.g ) * alpha;
6990  this.b += ( color.b - this.b ) * alpha;
6991 
6992  return this;
6993 
6994  },
6995 
6996  lerpHSL: function () {
6997 
6998  var hslA = { h: 0, s: 0, l: 0 };
6999  var hslB = { h: 0, s: 0, l: 0 };
7000 
7001  return function lerpHSL( color, alpha ) {
7002 
7003  this.getHSL( hslA );
7004  color.getHSL( hslB );
7005 
7006  var h = _Math.lerp( hslA.h, hslB.h, alpha );
7007  var s = _Math.lerp( hslA.s, hslB.s, alpha );
7008  var l = _Math.lerp( hslA.l, hslB.l, alpha );
7009 
7010  this.setHSL( h, s, l );
7011 
7012  return this;
7013 
7014  };
7015 
7016  }(),
7017 
7018  equals: function ( c ) {
7019 
7020  return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b );
7021 
7022  },
7023 
7024  fromArray: function ( array, offset ) {
7025 
7026  if ( offset === undefined ) offset = 0;
7027 
7028  this.r = array[ offset ];
7029  this.g = array[ offset + 1 ];
7030  this.b = array[ offset + 2 ];
7031 
7032  return this;
7033 
7034  },
7035 
7036  toArray: function ( array, offset ) {
7037 
7038  if ( array === undefined ) array = [];
7039  if ( offset === undefined ) offset = 0;
7040 
7041  array[ offset ] = this.r;
7042  array[ offset + 1 ] = this.g;
7043  array[ offset + 2 ] = this.b;
7044 
7045  return array;
7046 
7047  },
7048 
7049  toJSON: function () {
7050 
7051  return this.getHex();
7052 
7053  }
7054 
7055  } );
7056 
7061  var UniformsLib = {
7062 
7063  common: {
7064 
7065  diffuse: { value: new Color( 0xeeeeee ) },
7066  opacity: { value: 1.0 },
7067 
7068  map: { value: null },
7069  uvTransform: { value: new Matrix3() },
7070 
7071  alphaMap: { value: null },
7072 
7073  },
7074 
7075  specularmap: {
7076 
7077  specularMap: { value: null },
7078 
7079  },
7080 
7081  envmap: {
7082 
7083  envMap: { value: null },
7084  flipEnvMap: { value: - 1 },
7085  reflectivity: { value: 1.0 },
7086  refractionRatio: { value: 0.98 },
7087  maxMipLevel: { value: 0 }
7088 
7089  },
7090 
7091  aomap: {
7092 
7093  aoMap: { value: null },
7094  aoMapIntensity: { value: 1 }
7095 
7096  },
7097 
7098  lightmap: {
7099 
7100  lightMap: { value: null },
7101  lightMapIntensity: { value: 1 }
7102 
7103  },
7104 
7105  emissivemap: {
7106 
7107  emissiveMap: { value: null }
7108 
7109  },
7110 
7111  bumpmap: {
7112 
7113  bumpMap: { value: null },
7114  bumpScale: { value: 1 }
7115 
7116  },
7117 
7118  normalmap: {
7119 
7120  normalMap: { value: null },
7121  normalScale: { value: new Vector2( 1, 1 ) }
7122 
7123  },
7124 
7125  displacementmap: {
7126 
7127  displacementMap: { value: null },
7128  displacementScale: { value: 1 },
7129  displacementBias: { value: 0 }
7130 
7131  },
7132 
7133  roughnessmap: {
7134 
7135  roughnessMap: { value: null }
7136 
7137  },
7138 
7139  metalnessmap: {
7140 
7141  metalnessMap: { value: null }
7142 
7143  },
7144 
7145  gradientmap: {
7146 
7147  gradientMap: { value: null }
7148 
7149  },
7150 
7151  fog: {
7152 
7153  fogDensity: { value: 0.00025 },
7154  fogNear: { value: 1 },
7155  fogFar: { value: 2000 },
7156  fogColor: { value: new Color( 0xffffff ) }
7157 
7158  },
7159 
7160  lights: {
7161 
7162  ambientLightColor: { value: [] },
7163 
7164  directionalLights: { value: [], properties: {
7165  direction: {},
7166  color: {},
7167 
7168  shadow: {},
7169  shadowBias: {},
7170  shadowRadius: {},
7171  shadowMapSize: {}
7172  } },
7173 
7174  directionalShadowMap: { value: [] },
7175  directionalShadowMatrix: { value: [] },
7176 
7177  spotLights: { value: [], properties: {
7178  color: {},
7179  position: {},
7180  direction: {},
7181  distance: {},
7182  coneCos: {},
7183  penumbraCos: {},
7184  decay: {},
7185 
7186  shadow: {},
7187  shadowBias: {},
7188  shadowRadius: {},
7189  shadowMapSize: {}
7190  } },
7191 
7192  spotShadowMap: { value: [] },
7193  spotShadowMatrix: { value: [] },
7194 
7195  pointLights: { value: [], properties: {
7196  color: {},
7197  position: {},
7198  decay: {},
7199  distance: {},
7200 
7201  shadow: {},
7202  shadowBias: {},
7203  shadowRadius: {},
7204  shadowMapSize: {},
7205  shadowCameraNear: {},
7206  shadowCameraFar: {}
7207  } },
7208 
7209  pointShadowMap: { value: [] },
7210  pointShadowMatrix: { value: [] },
7211 
7212  hemisphereLights: { value: [], properties: {
7213  direction: {},
7214  skyColor: {},
7215  groundColor: {}
7216  } },
7217 
7218  // TODO (abelnation): RectAreaLight BRDF data needs to be moved from example to main src
7219  rectAreaLights: { value: [], properties: {
7220  color: {},
7221  position: {},
7222  width: {},
7223  height: {}
7224  } }
7225 
7226  },
7227 
7228  points: {
7229 
7230  diffuse: { value: new Color( 0xeeeeee ) },
7231  opacity: { value: 1.0 },
7232  size: { value: 1.0 },
7233  scale: { value: 1.0 },
7234  map: { value: null },
7235  uvTransform: { value: new Matrix3() }
7236 
7237  },
7238 
7239  sprite: {
7240 
7241  diffuse: { value: new Color( 0xeeeeee ) },
7242  opacity: { value: 1.0 },
7243  center: { value: new Vector2( 0.5, 0.5 ) },
7244  rotation: { value: 0.0 },
7245  map: { value: null },
7246  uvTransform: { value: new Matrix3() }
7247 
7248  }
7249 
7250  };
7251 
7258  var ShaderLib = {
7259 
7260  basic: {
7261 
7262  uniforms: mergeUniforms( [
7263  UniformsLib.common,
7264  UniformsLib.specularmap,
7265  UniformsLib.envmap,
7266  UniformsLib.aomap,
7267  UniformsLib.lightmap,
7268  UniformsLib.fog
7269  ] ),
7270 
7271  vertexShader: ShaderChunk.meshbasic_vert,
7272  fragmentShader: ShaderChunk.meshbasic_frag
7273 
7274  },
7275 
7276  lambert: {
7277 
7278  uniforms: mergeUniforms( [
7279  UniformsLib.common,
7280  UniformsLib.specularmap,
7281  UniformsLib.envmap,
7282  UniformsLib.aomap,
7283  UniformsLib.lightmap,
7284  UniformsLib.emissivemap,
7285  UniformsLib.fog,
7286  UniformsLib.lights,
7287  {
7288  emissive: { value: new Color( 0x000000 ) }
7289  }
7290  ] ),
7291 
7292  vertexShader: ShaderChunk.meshlambert_vert,
7293  fragmentShader: ShaderChunk.meshlambert_frag
7294 
7295  },
7296 
7297  phong: {
7298 
7299  uniforms: mergeUniforms( [
7300  UniformsLib.common,
7301  UniformsLib.specularmap,
7302  UniformsLib.envmap,
7303  UniformsLib.aomap,
7304  UniformsLib.lightmap,
7305  UniformsLib.emissivemap,
7306  UniformsLib.bumpmap,
7307  UniformsLib.normalmap,
7308  UniformsLib.displacementmap,
7309  UniformsLib.gradientmap,
7310  UniformsLib.fog,
7311  UniformsLib.lights,
7312  {
7313  emissive: { value: new Color( 0x000000 ) },
7314  specular: { value: new Color( 0x111111 ) },
7315  shininess: { value: 30 }
7316  }
7317  ] ),
7318 
7319  vertexShader: ShaderChunk.meshphong_vert,
7320  fragmentShader: ShaderChunk.meshphong_frag
7321 
7322  },
7323 
7324  standard: {
7325 
7326  uniforms: mergeUniforms( [
7327  UniformsLib.common,
7328  UniformsLib.envmap,
7329  UniformsLib.aomap,
7330  UniformsLib.lightmap,
7331  UniformsLib.emissivemap,
7332  UniformsLib.bumpmap,
7333  UniformsLib.normalmap,
7334  UniformsLib.displacementmap,
7335  UniformsLib.roughnessmap,
7336  UniformsLib.metalnessmap,
7337  UniformsLib.fog,
7338  UniformsLib.lights,
7339  {
7340  emissive: { value: new Color( 0x000000 ) },
7341  roughness: { value: 0.5 },
7342  metalness: { value: 0.5 },
7343  envMapIntensity: { value: 1 } // temporary
7344  }
7345  ] ),
7346 
7347  vertexShader: ShaderChunk.meshphysical_vert,
7348  fragmentShader: ShaderChunk.meshphysical_frag
7349 
7350  },
7351 
7352  matcap: {
7353 
7354  uniforms: mergeUniforms( [
7355  UniformsLib.common,
7356  UniformsLib.bumpmap,
7357  UniformsLib.normalmap,
7358  UniformsLib.displacementmap,
7359  UniformsLib.fog,
7360  {
7361  matcap: { value: null }
7362  }
7363  ] ),
7364 
7365  vertexShader: ShaderChunk.meshmatcap_vert,
7366  fragmentShader: ShaderChunk.meshmatcap_frag
7367 
7368  },
7369 
7370  points: {
7371 
7372  uniforms: mergeUniforms( [
7373  UniformsLib.points,
7374  UniformsLib.fog
7375  ] ),
7376 
7377  vertexShader: ShaderChunk.points_vert,
7378  fragmentShader: ShaderChunk.points_frag
7379 
7380  },
7381 
7382  dashed: {
7383 
7384  uniforms: mergeUniforms( [
7385  UniformsLib.common,
7386  UniformsLib.fog,
7387  {
7388  scale: { value: 1 },
7389  dashSize: { value: 1 },
7390  totalSize: { value: 2 }
7391  }
7392  ] ),
7393 
7394  vertexShader: ShaderChunk.linedashed_vert,
7395  fragmentShader: ShaderChunk.linedashed_frag
7396 
7397  },
7398 
7399  depth: {
7400 
7401  uniforms: mergeUniforms( [
7402  UniformsLib.common,
7403  UniformsLib.displacementmap
7404  ] ),
7405 
7406  vertexShader: ShaderChunk.depth_vert,
7407  fragmentShader: ShaderChunk.depth_frag
7408 
7409  },
7410 
7411  normal: {
7412 
7413  uniforms: mergeUniforms( [
7414  UniformsLib.common,
7415  UniformsLib.bumpmap,
7416  UniformsLib.normalmap,
7417  UniformsLib.displacementmap,
7418  {
7419  opacity: { value: 1.0 }
7420  }
7421  ] ),
7422 
7423  vertexShader: ShaderChunk.normal_vert,
7424  fragmentShader: ShaderChunk.normal_frag
7425 
7426  },
7427 
7428  sprite: {
7429 
7430  uniforms: mergeUniforms( [
7431  UniformsLib.sprite,
7432  UniformsLib.fog
7433  ] ),
7434 
7435  vertexShader: ShaderChunk.sprite_vert,
7436  fragmentShader: ShaderChunk.sprite_frag
7437 
7438  },
7439 
7440  background: {
7441 
7442  uniforms: {
7443  uvTransform: { value: new Matrix3() },
7444  t2D: { value: null },
7445  },
7446 
7447  vertexShader: ShaderChunk.background_vert,
7448  fragmentShader: ShaderChunk.background_frag
7449 
7450  },
7451  /* -------------------------------------------------------------------------
7452  // Cube map shader
7453  ------------------------------------------------------------------------- */
7454 
7455  cube: {
7456 
7457  uniforms: {
7458  tCube: { value: null },
7459  tFlip: { value: - 1 },
7460  opacity: { value: 1.0 }
7461  },
7462 
7463  vertexShader: ShaderChunk.cube_vert,
7464  fragmentShader: ShaderChunk.cube_frag
7465 
7466  },
7467 
7468  equirect: {
7469 
7470  uniforms: {
7471  tEquirect: { value: null },
7472  },
7473 
7474  vertexShader: ShaderChunk.equirect_vert,
7475  fragmentShader: ShaderChunk.equirect_frag
7476 
7477  },
7478 
7479  distanceRGBA: {
7480 
7481  uniforms: mergeUniforms( [
7482  UniformsLib.common,
7483  UniformsLib.displacementmap,
7484  {
7485  referencePosition: { value: new Vector3() },
7486  nearDistance: { value: 1 },
7487  farDistance: { value: 1000 }
7488  }
7489  ] ),
7490 
7491  vertexShader: ShaderChunk.distanceRGBA_vert,
7492  fragmentShader: ShaderChunk.distanceRGBA_frag
7493 
7494  },
7495 
7496  shadow: {
7497 
7498  uniforms: mergeUniforms( [
7499  UniformsLib.lights,
7500  UniformsLib.fog,
7501  {
7502  color: { value: new Color( 0x00000 ) },
7503  opacity: { value: 1.0 }
7504  },
7505  ] ),
7506 
7507  vertexShader: ShaderChunk.shadow_vert,
7508  fragmentShader: ShaderChunk.shadow_frag
7509 
7510  }
7511 
7512  };
7513 
7514  ShaderLib.physical = {
7515 
7516  uniforms: mergeUniforms( [
7517  ShaderLib.standard.uniforms,
7518  {
7519  clearCoat: { value: 0 },
7520  clearCoatRoughness: { value: 0 }
7521  }
7522  ] ),
7523 
7524  vertexShader: ShaderChunk.meshphysical_vert,
7525  fragmentShader: ShaderChunk.meshphysical_frag
7526 
7527  };
7528 
7533  function WebGLAnimation() {
7534 
7535  var context = null;
7536  var isAnimating = false;
7537  var animationLoop = null;
7538 
7539  function onAnimationFrame( time, frame ) {
7540 
7541  if ( isAnimating === false ) return;
7542 
7543  animationLoop( time, frame );
7544 
7545  context.requestAnimationFrame( onAnimationFrame );
7546 
7547  }
7548 
7549  return {
7550 
7551  start: function () {
7552 
7553  if ( isAnimating === true ) return;
7554  if ( animationLoop === null ) return;
7555 
7556  context.requestAnimationFrame( onAnimationFrame );
7557 
7558  isAnimating = true;
7559 
7560  },
7561 
7562  stop: function () {
7563 
7564  isAnimating = false;
7565 
7566  },
7567 
7568  setAnimationLoop: function ( callback ) {
7569 
7570  animationLoop = callback;
7571 
7572  },
7573 
7574  setContext: function ( value ) {
7575 
7576  context = value;
7577 
7578  }
7579 
7580  };
7581 
7582  }
7583 
7588  function WebGLAttributes( gl ) {
7589 
7590  var buffers = new WeakMap();
7591 
7592  function createBuffer( attribute, bufferType ) {
7593 
7594  var array = attribute.array;
7595  var usage = attribute.dynamic ? 35048 : 35044;
7596 
7597  var buffer = gl.createBuffer();
7598 
7599  gl.bindBuffer( bufferType, buffer );
7600  gl.bufferData( bufferType, array, usage );
7601 
7602  attribute.onUploadCallback();
7603 
7604  var type = 5126;
7605 
7606  if ( array instanceof Float32Array ) {
7607 
7608  type = 5126;
7609 
7610  } else if ( array instanceof Float64Array ) {
7611 
7612  console.warn( 'THREE.WebGLAttributes: Unsupported data buffer format: Float64Array.' );
7613 
7614  } else if ( array instanceof Uint16Array ) {
7615 
7616  type = 5123;
7617 
7618  } else if ( array instanceof Int16Array ) {
7619 
7620  type = 5122;
7621 
7622  } else if ( array instanceof Uint32Array ) {
7623 
7624  type = 5125;
7625 
7626  } else if ( array instanceof Int32Array ) {
7627 
7628  type = 5124;
7629 
7630  } else if ( array instanceof Int8Array ) {
7631 
7632  type = 5120;
7633 
7634  } else if ( array instanceof Uint8Array ) {
7635 
7636  type = 5121;
7637 
7638  }
7639 
7640  return {
7641  buffer: buffer,
7642  type: type,
7643  bytesPerElement: array.BYTES_PER_ELEMENT,
7644  version: attribute.version
7645  };
7646 
7647  }
7648 
7649  function updateBuffer( buffer, attribute, bufferType ) {
7650 
7651  var array = attribute.array;
7652  var updateRange = attribute.updateRange;
7653 
7654  gl.bindBuffer( bufferType, buffer );
7655 
7656  if ( attribute.dynamic === false ) {
7657 
7658  gl.bufferData( bufferType, array, 35044 );
7659 
7660  } else if ( updateRange.count === - 1 ) {
7661 
7662  // Not using update ranges
7663 
7664  gl.bufferSubData( bufferType, 0, array );
7665 
7666  } else if ( updateRange.count === 0 ) {
7667 
7668  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.' );
7669 
7670  } else {
7671 
7672  gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT,
7673  array.subarray( updateRange.offset, updateRange.offset + updateRange.count ) );
7674 
7675  updateRange.count = - 1; // reset range
7676 
7677  }
7678 
7679  }
7680 
7681  //
7682 
7683  function get( attribute ) {
7684 
7685  if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
7686 
7687  return buffers.get( attribute );
7688 
7689  }
7690 
7691  function remove( attribute ) {
7692 
7693  if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
7694 
7695  var data = buffers.get( attribute );
7696 
7697  if ( data ) {
7698 
7699  gl.deleteBuffer( data.buffer );
7700 
7701  buffers.delete( attribute );
7702 
7703  }
7704 
7705  }
7706 
7707  function update( attribute, bufferType ) {
7708 
7709  if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
7710 
7711  var data = buffers.get( attribute );
7712 
7713  if ( data === undefined ) {
7714 
7715  buffers.set( attribute, createBuffer( attribute, bufferType ) );
7716 
7717  } else if ( data.version < attribute.version ) {
7718 
7719  updateBuffer( data.buffer, attribute, bufferType );
7720 
7721  data.version = attribute.version;
7722 
7723  }
7724 
7725  }
7726 
7727  return {
7728 
7729  get: get,
7730  remove: remove,
7731  update: update
7732 
7733  };
7734 
7735  }
7736 
7742  function Face3( a, b, c, normal, color, materialIndex ) {
7743 
7744  this.a = a;
7745  this.b = b;
7746  this.c = c;
7747 
7748  this.normal = ( normal && normal.isVector3 ) ? normal : new Vector3();
7749  this.vertexNormals = Array.isArray( normal ) ? normal : [];
7750 
7751  this.color = ( color && color.isColor ) ? color : new Color();
7752  this.vertexColors = Array.isArray( color ) ? color : [];
7753 
7754  this.materialIndex = materialIndex !== undefined ? materialIndex : 0;
7755 
7756  }
7757 
7758  Object.assign( Face3.prototype, {
7759 
7760  clone: function () {
7761 
7762  return new this.constructor().copy( this );
7763 
7764  },
7765 
7766  copy: function ( source ) {
7767 
7768  this.a = source.a;
7769  this.b = source.b;
7770  this.c = source.c;
7771 
7772  this.normal.copy( source.normal );
7773  this.color.copy( source.color );
7774 
7775  this.materialIndex = source.materialIndex;
7776 
7777  for ( var i = 0, il = source.vertexNormals.length; i < il; i ++ ) {
7778 
7779  this.vertexNormals[ i ] = source.vertexNormals[ i ].clone();
7780 
7781  }
7782 
7783  for ( var i = 0, il = source.vertexColors.length; i < il; i ++ ) {
7784 
7785  this.vertexColors[ i ] = source.vertexColors[ i ].clone();
7786 
7787  }
7788 
7789  return this;
7790 
7791  }
7792 
7793  } );
7794 
7801  function Euler( x, y, z, order ) {
7802 
7803  this._x = x || 0;
7804  this._y = y || 0;
7805  this._z = z || 0;
7806  this._order = order || Euler.DefaultOrder;
7807 
7808  }
7809 
7810  Euler.RotationOrders = [ 'XYZ', 'YZX', 'ZXY', 'XZY', 'YXZ', 'ZYX' ];
7811 
7812  Euler.DefaultOrder = 'XYZ';
7813 
7814  Object.defineProperties( Euler.prototype, {
7815 
7816  x: {
7817 
7818  get: function () {
7819 
7820  return this._x;
7821 
7822  },
7823 
7824  set: function ( value ) {
7825 
7826  this._x = value;
7827  this.onChangeCallback();
7828 
7829  }
7830 
7831  },
7832 
7833  y: {
7834 
7835  get: function () {
7836 
7837  return this._y;
7838 
7839  },
7840 
7841  set: function ( value ) {
7842 
7843  this._y = value;
7844  this.onChangeCallback();
7845 
7846  }
7847 
7848  },
7849 
7850  z: {
7851 
7852  get: function () {
7853 
7854  return this._z;
7855 
7856  },
7857 
7858  set: function ( value ) {
7859 
7860  this._z = value;
7861  this.onChangeCallback();
7862 
7863  }
7864 
7865  },
7866 
7867  order: {
7868 
7869  get: function () {
7870 
7871  return this._order;
7872 
7873  },
7874 
7875  set: function ( value ) {
7876 
7877  this._order = value;
7878  this.onChangeCallback();
7879 
7880  }
7881 
7882  }
7883 
7884  } );
7885 
7886  Object.assign( Euler.prototype, {
7887 
7888  isEuler: true,
7889 
7890  set: function ( x, y, z, order ) {
7891 
7892  this._x = x;
7893  this._y = y;
7894  this._z = z;
7895  this._order = order || this._order;
7896 
7897  this.onChangeCallback();
7898 
7899  return this;
7900 
7901  },
7902 
7903  clone: function () {
7904 
7905  return new this.constructor( this._x, this._y, this._z, this._order );
7906 
7907  },
7908 
7909  copy: function ( euler ) {
7910 
7911  this._x = euler._x;
7912  this._y = euler._y;
7913  this._z = euler._z;
7914  this._order = euler._order;
7915 
7916  this.onChangeCallback();
7917 
7918  return this;
7919 
7920  },
7921 
7922  setFromRotationMatrix: function ( m, order, update ) {
7923 
7924  var clamp = _Math.clamp;
7925 
7926  // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
7927 
7928  var te = m.elements;
7929  var m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ];
7930  var m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ];
7931  var m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
7932 
7933  order = order || this._order;
7934 
7935  if ( order === 'XYZ' ) {
7936 
7937  this._y = Math.asin( clamp( m13, - 1, 1 ) );
7938 
7939  if ( Math.abs( m13 ) < 0.99999 ) {
7940 
7941  this._x = Math.atan2( - m23, m33 );
7942  this._z = Math.atan2( - m12, m11 );
7943 
7944  } else {
7945 
7946  this._x = Math.atan2( m32, m22 );
7947  this._z = 0;
7948 
7949  }
7950 
7951  } else if ( order === 'YXZ' ) {
7952 
7953  this._x = Math.asin( - clamp( m23, - 1, 1 ) );
7954 
7955  if ( Math.abs( m23 ) < 0.99999 ) {
7956 
7957  this._y = Math.atan2( m13, m33 );
7958  this._z = Math.atan2( m21, m22 );
7959 
7960  } else {
7961 
7962  this._y = Math.atan2( - m31, m11 );
7963  this._z = 0;
7964 
7965  }
7966 
7967  } else if ( order === 'ZXY' ) {
7968 
7969  this._x = Math.asin( clamp( m32, - 1, 1 ) );
7970 
7971  if ( Math.abs( m32 ) < 0.99999 ) {
7972 
7973  this._y = Math.atan2( - m31, m33 );
7974  this._z = Math.atan2( - m12, m22 );
7975 
7976  } else {
7977 
7978  this._y = 0;
7979  this._z = Math.atan2( m21, m11 );
7980 
7981  }
7982 
7983  } else if ( order === 'ZYX' ) {
7984 
7985  this._y = Math.asin( - clamp( m31, - 1, 1 ) );
7986 
7987  if ( Math.abs( m31 ) < 0.99999 ) {
7988 
7989  this._x = Math.atan2( m32, m33 );
7990  this._z = Math.atan2( m21, m11 );
7991 
7992  } else {
7993 
7994  this._x = 0;
7995  this._z = Math.atan2( - m12, m22 );
7996 
7997  }
7998 
7999  } else if ( order === 'YZX' ) {
8000 
8001  this._z = Math.asin( clamp( m21, - 1, 1 ) );
8002 
8003  if ( Math.abs( m21 ) < 0.99999 ) {
8004 
8005  this._x = Math.atan2( - m23, m22 );
8006  this._y = Math.atan2( - m31, m11 );
8007 
8008  } else {
8009 
8010  this._x = 0;
8011  this._y = Math.atan2( m13, m33 );
8012 
8013  }
8014 
8015  } else if ( order === 'XZY' ) {
8016 
8017  this._z = Math.asin( - clamp( m12, - 1, 1 ) );
8018 
8019  if ( Math.abs( m12 ) < 0.99999 ) {
8020 
8021  this._x = Math.atan2( m32, m22 );
8022  this._y = Math.atan2( m13, m11 );
8023 
8024  } else {
8025 
8026  this._x = Math.atan2( - m23, m33 );
8027  this._y = 0;
8028 
8029  }
8030 
8031  } else {
8032 
8033  console.warn( 'THREE.Euler: .setFromRotationMatrix() given unsupported order: ' + order );
8034 
8035  }
8036 
8037  this._order = order;
8038 
8039  if ( update !== false ) this.onChangeCallback();
8040 
8041  return this;
8042 
8043  },
8044 
8045  setFromQuaternion: function () {
8046 
8047  var matrix = new Matrix4();
8048 
8049  return function setFromQuaternion( q, order, update ) {
8050 
8051  matrix.makeRotationFromQuaternion( q );
8052 
8053  return this.setFromRotationMatrix( matrix, order, update );
8054 
8055  };
8056 
8057  }(),
8058 
8059  setFromVector3: function ( v, order ) {
8060 
8061  return this.set( v.x, v.y, v.z, order || this._order );
8062 
8063  },
8064 
8065  reorder: function () {
8066 
8067  // WARNING: this discards revolution information -bhouston
8068 
8069  var q = new Quaternion();
8070 
8071  return function reorder( newOrder ) {
8072 
8073  q.setFromEuler( this );
8074 
8075  return this.setFromQuaternion( q, newOrder );
8076 
8077  };
8078 
8079  }(),
8080 
8081  equals: function ( euler ) {
8082 
8083  return ( euler._x === this._x ) && ( euler._y === this._y ) && ( euler._z === this._z ) && ( euler._order === this._order );
8084 
8085  },
8086 
8087  fromArray: function ( array ) {
8088 
8089  this._x = array[ 0 ];
8090  this._y = array[ 1 ];
8091  this._z = array[ 2 ];
8092  if ( array[ 3 ] !== undefined ) this._order = array[ 3 ];
8093 
8094  this.onChangeCallback();
8095 
8096  return this;
8097 
8098  },
8099 
8100  toArray: function ( array, offset ) {
8101 
8102  if ( array === undefined ) array = [];
8103  if ( offset === undefined ) offset = 0;
8104 
8105  array[ offset ] = this._x;
8106  array[ offset + 1 ] = this._y;
8107  array[ offset + 2 ] = this._z;
8108  array[ offset + 3 ] = this._order;
8109 
8110  return array;
8111 
8112  },
8113 
8114  toVector3: function ( optionalResult ) {
8115 
8116  if ( optionalResult ) {
8117 
8118  return optionalResult.set( this._x, this._y, this._z );
8119 
8120  } else {
8121 
8122  return new Vector3( this._x, this._y, this._z );
8123 
8124  }
8125 
8126  },
8127 
8128  onChange: function ( callback ) {
8129 
8130  this.onChangeCallback = callback;
8131 
8132  return this;
8133 
8134  },
8135 
8136  onChangeCallback: function () {}
8137 
8138  } );
8139 
8144  function Layers() {
8145 
8146  this.mask = 1 | 0;
8147 
8148  }
8149 
8150  Object.assign( Layers.prototype, {
8151 
8152  set: function ( channel ) {
8153 
8154  this.mask = 1 << channel | 0;
8155 
8156  },
8157 
8158  enable: function ( channel ) {
8159 
8160  this.mask |= 1 << channel | 0;
8161 
8162  },
8163 
8164  toggle: function ( channel ) {
8165 
8166  this.mask ^= 1 << channel | 0;
8167 
8168  },
8169 
8170  disable: function ( channel ) {
8171 
8172  this.mask &= ~ ( 1 << channel | 0 );
8173 
8174  },
8175 
8176  test: function ( layers ) {
8177 
8178  return ( this.mask & layers.mask ) !== 0;
8179 
8180  }
8181 
8182  } );
8183 
8192  var object3DId = 0;
8193 
8194  function Object3D() {
8195 
8196  Object.defineProperty( this, 'id', { value: object3DId ++ } );
8197 
8198  this.uuid = _Math.generateUUID();
8199 
8200  this.name = '';
8201  this.type = 'Object3D';
8202 
8203  this.parent = null;
8204  this.children = [];
8205 
8206  this.up = Object3D.DefaultUp.clone();
8207 
8208  var position = new Vector3();
8209  var rotation = new Euler();
8210  var quaternion = new Quaternion();
8211  var scale = new Vector3( 1, 1, 1 );
8212 
8213  function onRotationChange() {
8214 
8215  quaternion.setFromEuler( rotation, false );
8216 
8217  }
8218 
8219  function onQuaternionChange() {
8220 
8221  rotation.setFromQuaternion( quaternion, undefined, false );
8222 
8223  }
8224 
8225  rotation.onChange( onRotationChange );
8226  quaternion.onChange( onQuaternionChange );
8227 
8228  Object.defineProperties( this, {
8229  position: {
8230  configurable: true,
8231  enumerable: true,
8232  value: position
8233  },
8234  rotation: {
8235  configurable: true,
8236  enumerable: true,
8237  value: rotation
8238  },
8239  quaternion: {
8240  configurable: true,
8241  enumerable: true,
8242  value: quaternion
8243  },
8244  scale: {
8245  configurable: true,
8246  enumerable: true,
8247  value: scale
8248  },
8249  modelViewMatrix: {
8250  value: new Matrix4()
8251  },
8252  normalMatrix: {
8253  value: new Matrix3()
8254  }
8255  } );
8256 
8257  this.matrix = new Matrix4();
8258  this.matrixWorld = new Matrix4();
8259 
8260  this.matrixAutoUpdate = Object3D.DefaultMatrixAutoUpdate;
8261  this.matrixWorldNeedsUpdate = false;
8262 
8263  this.layers = new Layers();
8264  this.visible = true;
8265 
8266  this.castShadow = false;
8267  this.receiveShadow = false;
8268 
8269  this.frustumCulled = true;
8270  this.renderOrder = 0;
8271 
8272  this.userData = {};
8273 
8274  }
8275 
8276  Object3D.DefaultUp = new Vector3( 0, 1, 0 );
8277  Object3D.DefaultMatrixAutoUpdate = true;
8278 
8279  Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
8280 
8281  constructor: Object3D,
8282 
8283  isObject3D: true,
8284 
8285  onBeforeRender: function () {},
8286  onAfterRender: function () {},
8287 
8288  applyMatrix: function ( matrix ) {
8289 
8290  this.matrix.multiplyMatrices( matrix, this.matrix );
8291 
8292  this.matrix.decompose( this.position, this.quaternion, this.scale );
8293 
8294  },
8295 
8296  applyQuaternion: function ( q ) {
8297 
8298  this.quaternion.premultiply( q );
8299 
8300  return this;
8301 
8302  },
8303 
8304  setRotationFromAxisAngle: function ( axis, angle ) {
8305 
8306  // assumes axis is normalized
8307 
8308  this.quaternion.setFromAxisAngle( axis, angle );
8309 
8310  },
8311 
8312  setRotationFromEuler: function ( euler ) {
8313 
8314  this.quaternion.setFromEuler( euler, true );
8315 
8316  },
8317 
8318  setRotationFromMatrix: function ( m ) {
8319 
8320  // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
8321 
8322  this.quaternion.setFromRotationMatrix( m );
8323 
8324  },
8325 
8326  setRotationFromQuaternion: function ( q ) {
8327 
8328  // assumes q is normalized
8329 
8330  this.quaternion.copy( q );
8331 
8332  },
8333 
8334  rotateOnAxis: function () {
8335 
8336  // rotate object on axis in object space
8337  // axis is assumed to be normalized
8338 
8339  var q1 = new Quaternion();
8340 
8341  return function rotateOnAxis( axis, angle ) {
8342 
8343  q1.setFromAxisAngle( axis, angle );
8344 
8345  this.quaternion.multiply( q1 );
8346 
8347  return this;
8348 
8349  };
8350 
8351  }(),
8352 
8353  rotateOnWorldAxis: function () {
8354 
8355  // rotate object on axis in world space
8356  // axis is assumed to be normalized
8357  // method assumes no rotated parent
8358 
8359  var q1 = new Quaternion();
8360 
8361  return function rotateOnWorldAxis( axis, angle ) {
8362 
8363  q1.setFromAxisAngle( axis, angle );
8364 
8365  this.quaternion.premultiply( q1 );
8366 
8367  return this;
8368 
8369  };
8370 
8371  }(),
8372 
8373  rotateX: function () {
8374 
8375  var v1 = new Vector3( 1, 0, 0 );
8376 
8377  return function rotateX( angle ) {
8378 
8379  return this.rotateOnAxis( v1, angle );
8380 
8381  };
8382 
8383  }(),
8384 
8385  rotateY: function () {
8386 
8387  var v1 = new Vector3( 0, 1, 0 );
8388 
8389  return function rotateY( angle ) {
8390 
8391  return this.rotateOnAxis( v1, angle );
8392 
8393  };
8394 
8395  }(),
8396 
8397  rotateZ: function () {
8398 
8399  var v1 = new Vector3( 0, 0, 1 );
8400 
8401  return function rotateZ( angle ) {
8402 
8403  return this.rotateOnAxis( v1, angle );
8404 
8405  };
8406 
8407  }(),
8408 
8409  translateOnAxis: function () {
8410 
8411  // translate object by distance along axis in object space
8412  // axis is assumed to be normalized
8413 
8414  var v1 = new Vector3();
8415 
8416  return function translateOnAxis( axis, distance ) {
8417 
8418  v1.copy( axis ).applyQuaternion( this.quaternion );
8419 
8420  this.position.add( v1.multiplyScalar( distance ) );
8421 
8422  return this;
8423 
8424  };
8425 
8426  }(),
8427 
8428  translateX: function () {
8429 
8430  var v1 = new Vector3( 1, 0, 0 );
8431 
8432  return function translateX( distance ) {
8433 
8434  return this.translateOnAxis( v1, distance );
8435 
8436  };
8437 
8438  }(),
8439 
8440  translateY: function () {
8441 
8442  var v1 = new Vector3( 0, 1, 0 );
8443 
8444  return function translateY( distance ) {
8445 
8446  return this.translateOnAxis( v1, distance );
8447 
8448  };
8449 
8450  }(),
8451 
8452  translateZ: function () {
8453 
8454  var v1 = new Vector3( 0, 0, 1 );
8455 
8456  return function translateZ( distance ) {
8457 
8458  return this.translateOnAxis( v1, distance );
8459 
8460  };
8461 
8462  }(),
8463 
8464  localToWorld: function ( vector ) {
8465 
8466  return vector.applyMatrix4( this.matrixWorld );
8467 
8468  },
8469 
8470  worldToLocal: function () {
8471 
8472  var m1 = new Matrix4();
8473 
8474  return function worldToLocal( vector ) {
8475 
8476  return vector.applyMatrix4( m1.getInverse( this.matrixWorld ) );
8477 
8478  };
8479 
8480  }(),
8481 
8482  lookAt: function () {
8483 
8484  // This method does not support objects having non-uniformly-scaled parent(s)
8485 
8486  var q1 = new Quaternion();
8487  var m1 = new Matrix4();
8488  var target = new Vector3();
8489  var position = new Vector3();
8490 
8491  return function lookAt( x, y, z ) {
8492 
8493  if ( x.isVector3 ) {
8494 
8495  target.copy( x );
8496 
8497  } else {
8498 
8499  target.set( x, y, z );
8500 
8501  }
8502 
8503  var parent = this.parent;
8504 
8505  this.updateWorldMatrix( true, false );
8506 
8507  position.setFromMatrixPosition( this.matrixWorld );
8508 
8509  if ( this.isCamera || this.isLight ) {
8510 
8511  m1.lookAt( position, target, this.up );
8512 
8513  } else {
8514 
8515  m1.lookAt( target, position, this.up );
8516 
8517  }
8518 
8519  this.quaternion.setFromRotationMatrix( m1 );
8520 
8521  if ( parent ) {
8522 
8523  m1.extractRotation( parent.matrixWorld );
8524  q1.setFromRotationMatrix( m1 );
8525  this.quaternion.premultiply( q1.inverse() );
8526 
8527  }
8528 
8529  };
8530 
8531  }(),
8532 
8533  add: function ( object ) {
8534 
8535  if ( arguments.length > 1 ) {
8536 
8537  for ( var i = 0; i < arguments.length; i ++ ) {
8538 
8539  this.add( arguments[ i ] );
8540 
8541  }
8542 
8543  return this;
8544 
8545  }
8546 
8547  if ( object === this ) {
8548 
8549  console.error( "THREE.Object3D.add: object can't be added as a child of itself.", object );
8550  return this;
8551 
8552  }
8553 
8554  if ( ( object && object.isObject3D ) ) {
8555 
8556  if ( object.parent !== null ) {
8557 
8558  object.parent.remove( object );
8559 
8560  }
8561 
8562  object.parent = this;
8563  object.dispatchEvent( { type: 'added' } );
8564 
8565  this.children.push( object );
8566 
8567  } else {
8568 
8569  console.error( "THREE.Object3D.add: object not an instance of THREE.Object3D.", object );
8570 
8571  }
8572 
8573  return this;
8574 
8575  },
8576 
8577  remove: function ( object ) {
8578 
8579  if ( arguments.length > 1 ) {
8580 
8581  for ( var i = 0; i < arguments.length; i ++ ) {
8582 
8583  this.remove( arguments[ i ] );
8584 
8585  }
8586 
8587  return this;
8588 
8589  }
8590 
8591  var index = this.children.indexOf( object );
8592 
8593  if ( index !== - 1 ) {
8594 
8595  object.parent = null;
8596 
8597  object.dispatchEvent( { type: 'removed' } );
8598 
8599  this.children.splice( index, 1 );
8600 
8601  }
8602 
8603  return this;
8604 
8605  },
8606 
8607  getObjectById: function ( id ) {
8608 
8609  return this.getObjectByProperty( 'id', id );
8610 
8611  },
8612 
8613  getObjectByName: function ( name ) {
8614 
8615  return this.getObjectByProperty( 'name', name );
8616 
8617  },
8618 
8619  getObjectByProperty: function ( name, value ) {
8620 
8621  if ( this[ name ] === value ) return this;
8622 
8623  for ( var i = 0, l = this.children.length; i < l; i ++ ) {
8624 
8625  var child = this.children[ i ];
8626  var object = child.getObjectByProperty( name, value );
8627 
8628  if ( object !== undefined ) {
8629 
8630  return object;
8631 
8632  }
8633 
8634  }
8635 
8636  return undefined;
8637 
8638  },
8639 
8640  getWorldPosition: function ( target ) {
8641 
8642  if ( target === undefined ) {
8643 
8644  console.warn( 'THREE.Object3D: .getWorldPosition() target is now required' );
8645  target = new Vector3();
8646 
8647  }
8648 
8649  this.updateMatrixWorld( true );
8650 
8651  return target.setFromMatrixPosition( this.matrixWorld );
8652 
8653  },
8654 
8655  getWorldQuaternion: function () {
8656 
8657  var position = new Vector3();
8658  var scale = new Vector3();
8659 
8660  return function getWorldQuaternion( target ) {
8661 
8662  if ( target === undefined ) {
8663 
8664  console.warn( 'THREE.Object3D: .getWorldQuaternion() target is now required' );
8665  target = new Quaternion();
8666 
8667  }
8668 
8669  this.updateMatrixWorld( true );
8670 
8671  this.matrixWorld.decompose( position, target, scale );
8672 
8673  return target;
8674 
8675  };
8676 
8677  }(),
8678 
8679  getWorldScale: function () {
8680 
8681  var position = new Vector3();
8682  var quaternion = new Quaternion();
8683 
8684  return function getWorldScale( target ) {
8685 
8686  if ( target === undefined ) {
8687 
8688  console.warn( 'THREE.Object3D: .getWorldScale() target is now required' );
8689  target = new Vector3();
8690 
8691  }
8692 
8693  this.updateMatrixWorld( true );
8694 
8695  this.matrixWorld.decompose( position, quaternion, target );
8696 
8697  return target;
8698 
8699  };
8700 
8701  }(),
8702 
8703  getWorldDirection: function ( target ) {
8704 
8705  if ( target === undefined ) {
8706 
8707  console.warn( 'THREE.Object3D: .getWorldDirection() target is now required' );
8708  target = new Vector3();
8709 
8710  }
8711 
8712  this.updateMatrixWorld( true );
8713 
8714  var e = this.matrixWorld.elements;
8715 
8716  return target.set( e[ 8 ], e[ 9 ], e[ 10 ] ).normalize();
8717 
8718  },
8719 
8720  raycast: function () {},
8721 
8722  traverse: function ( callback ) {
8723 
8724  callback( this );
8725 
8726  var children = this.children;
8727 
8728  for ( var i = 0, l = children.length; i < l; i ++ ) {
8729 
8730  children[ i ].traverse( callback );
8731 
8732  }
8733 
8734  },
8735 
8736  traverseVisible: function ( callback ) {
8737 
8738  if ( this.visible === false ) return;
8739 
8740  callback( this );
8741 
8742  var children = this.children;
8743 
8744  for ( var i = 0, l = children.length; i < l; i ++ ) {
8745 
8746  children[ i ].traverseVisible( callback );
8747 
8748  }
8749 
8750  },
8751 
8752  traverseAncestors: function ( callback ) {
8753 
8754  var parent = this.parent;
8755 
8756  if ( parent !== null ) {
8757 
8758  callback( parent );
8759 
8760  parent.traverseAncestors( callback );
8761 
8762  }
8763 
8764  },
8765 
8766  updateMatrix: function () {
8767 
8768  this.matrix.compose( this.position, this.quaternion, this.scale );
8769 
8770  this.matrixWorldNeedsUpdate = true;
8771 
8772  },
8773 
8774  updateMatrixWorld: function ( force ) {
8775 
8776  if ( this.matrixAutoUpdate ) this.updateMatrix();
8777 
8778  if ( this.matrixWorldNeedsUpdate || force ) {
8779 
8780  if ( this.parent === null ) {
8781 
8782  this.matrixWorld.copy( this.matrix );
8783 
8784  } else {
8785 
8786  this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
8787 
8788  }
8789 
8790  this.matrixWorldNeedsUpdate = false;
8791 
8792  force = true;
8793 
8794  }
8795 
8796  // update children
8797 
8798  var children = this.children;
8799 
8800  for ( var i = 0, l = children.length; i < l; i ++ ) {
8801 
8802  children[ i ].updateMatrixWorld( force );
8803 
8804  }
8805 
8806  },
8807 
8808  updateWorldMatrix: function ( updateParents, updateChildren ) {
8809 
8810  var parent = this.parent;
8811 
8812  if ( updateParents === true && parent !== null ) {
8813 
8814  parent.updateWorldMatrix( true, false );
8815 
8816  }
8817 
8818  if ( this.matrixAutoUpdate ) this.updateMatrix();
8819 
8820  if ( this.parent === null ) {
8821 
8822  this.matrixWorld.copy( this.matrix );
8823 
8824  } else {
8825 
8826  this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
8827 
8828  }
8829 
8830  // update children
8831 
8832  if ( updateChildren === true ) {
8833 
8834  var children = this.children;
8835 
8836  for ( var i = 0, l = children.length; i < l; i ++ ) {
8837 
8838  children[ i ].updateWorldMatrix( false, true );
8839 
8840  }
8841 
8842  }
8843 
8844  },
8845 
8846  toJSON: function ( meta ) {
8847 
8848  // meta is a string when called from JSON.stringify
8849  var isRootObject = ( meta === undefined || typeof meta === 'string' );
8850 
8851  var output = {};
8852 
8853  // meta is a hash used to collect geometries, materials.
8854  // not providing it implies that this is the root object
8855  // being serialized.
8856  if ( isRootObject ) {
8857 
8858  // initialize meta obj
8859  meta = {
8860  geometries: {},
8861  materials: {},
8862  textures: {},
8863  images: {},
8864  shapes: {}
8865  };
8866 
8867  output.metadata = {
8868  version: 4.5,
8869  type: 'Object',
8870  generator: 'Object3D.toJSON'
8871  };
8872 
8873  }
8874 
8875  // standard Object3D serialization
8876 
8877  var object = {};
8878 
8879  object.uuid = this.uuid;
8880  object.type = this.type;
8881 
8882  if ( this.name !== '' ) object.name = this.name;
8883  if ( this.castShadow === true ) object.castShadow = true;
8884  if ( this.receiveShadow === true ) object.receiveShadow = true;
8885  if ( this.visible === false ) object.visible = false;
8886  if ( this.frustumCulled === false ) object.frustumCulled = false;
8887  if ( this.renderOrder !== 0 ) object.renderOrder = this.renderOrder;
8888  if ( JSON.stringify( this.userData ) !== '{}' ) object.userData = this.userData;
8889 
8890  object.layers = this.layers.mask;
8891  object.matrix = this.matrix.toArray();
8892 
8893  if ( this.matrixAutoUpdate === false ) object.matrixAutoUpdate = false;
8894 
8895  // object specific properties
8896 
8897  if ( this.isMesh && this.drawMode !== TrianglesDrawMode ) object.drawMode = this.drawMode;
8898 
8899  //
8900 
8901  function serialize( library, element ) {
8902 
8903  if ( library[ element.uuid ] === undefined ) {
8904 
8905  library[ element.uuid ] = element.toJSON( meta );
8906 
8907  }
8908 
8909  return element.uuid;
8910 
8911  }
8912 
8913  if ( this.isMesh || this.isLine || this.isPoints ) {
8914 
8915  object.geometry = serialize( meta.geometries, this.geometry );
8916 
8917  var parameters = this.geometry.parameters;
8918 
8919  if ( parameters !== undefined && parameters.shapes !== undefined ) {
8920 
8921  var shapes = parameters.shapes;
8922 
8923  if ( Array.isArray( shapes ) ) {
8924 
8925  for ( var i = 0, l = shapes.length; i < l; i ++ ) {
8926 
8927  var shape = shapes[ i ];
8928 
8929  serialize( meta.shapes, shape );
8930 
8931  }
8932 
8933  } else {
8934 
8935  serialize( meta.shapes, shapes );
8936 
8937  }
8938 
8939  }
8940 
8941  }
8942 
8943  if ( this.material !== undefined ) {
8944 
8945  if ( Array.isArray( this.material ) ) {
8946 
8947  var uuids = [];
8948 
8949  for ( var i = 0, l = this.material.length; i < l; i ++ ) {
8950 
8951  uuids.push( serialize( meta.materials, this.material[ i ] ) );
8952 
8953  }
8954 
8955  object.material = uuids;
8956 
8957  } else {
8958 
8959  object.material = serialize( meta.materials, this.material );
8960 
8961  }
8962 
8963  }
8964 
8965  //
8966 
8967  if ( this.children.length > 0 ) {
8968 
8969  object.children = [];
8970 
8971  for ( var i = 0; i < this.children.length; i ++ ) {
8972 
8973  object.children.push( this.children[ i ].toJSON( meta ).object );
8974 
8975  }
8976 
8977  }
8978 
8979  if ( isRootObject ) {
8980 
8981  var geometries = extractFromCache( meta.geometries );
8982  var materials = extractFromCache( meta.materials );
8983  var textures = extractFromCache( meta.textures );
8984  var images = extractFromCache( meta.images );
8985  var shapes = extractFromCache( meta.shapes );
8986 
8987  if ( geometries.length > 0 ) output.geometries = geometries;
8988  if ( materials.length > 0 ) output.materials = materials;
8989  if ( textures.length > 0 ) output.textures = textures;
8990  if ( images.length > 0 ) output.images = images;
8991  if ( shapes.length > 0 ) output.shapes = shapes;
8992 
8993  }
8994 
8995  output.object = object;
8996 
8997  return output;
8998 
8999  // extract data from the cache hash
9000  // remove metadata on each item
9001  // and return as array
9002  function extractFromCache( cache ) {
9003 
9004  var values = [];
9005  for ( var key in cache ) {
9006 
9007  var data = cache[ key ];
9008  delete data.metadata;
9009  values.push( data );
9010 
9011  }
9012  return values;
9013 
9014  }
9015 
9016  },
9017 
9018  clone: function ( recursive ) {
9019 
9020  return new this.constructor().copy( this, recursive );
9021 
9022  },
9023 
9024  copy: function ( source, recursive ) {
9025 
9026  if ( recursive === undefined ) recursive = true;
9027 
9028  this.name = source.name;
9029 
9030  this.up.copy( source.up );
9031 
9032  this.position.copy( source.position );
9033  this.quaternion.copy( source.quaternion );
9034  this.scale.copy( source.scale );
9035 
9036  this.matrix.copy( source.matrix );
9037  this.matrixWorld.copy( source.matrixWorld );
9038 
9039  this.matrixAutoUpdate = source.matrixAutoUpdate;
9040  this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate;
9041 
9042  this.layers.mask = source.layers.mask;
9043  this.visible = source.visible;
9044 
9045  this.castShadow = source.castShadow;
9046  this.receiveShadow = source.receiveShadow;
9047 
9048  this.frustumCulled = source.frustumCulled;
9049  this.renderOrder = source.renderOrder;
9050 
9051  this.userData = JSON.parse( JSON.stringify( source.userData ) );
9052 
9053  if ( recursive === true ) {
9054 
9055  for ( var i = 0; i < source.children.length; i ++ ) {
9056 
9057  var child = source.children[ i ];
9058  this.add( child.clone() );
9059 
9060  }
9061 
9062  }
9063 
9064  return this;
9065 
9066  }
9067 
9068  } );
9069 
9079  var geometryId = 0; // Geometry uses even numbers as Id
9080 
9081  function Geometry() {
9082 
9083  Object.defineProperty( this, 'id', { value: geometryId += 2 } );
9084 
9085  this.uuid = _Math.generateUUID();
9086 
9087  this.name = '';
9088  this.type = 'Geometry';
9089 
9090  this.vertices = [];
9091  this.colors = [];
9092  this.faces = [];
9093  this.faceVertexUvs = [[]];
9094 
9095  this.morphTargets = [];
9096  this.morphNormals = [];
9097 
9098  this.skinWeights = [];
9099  this.skinIndices = [];
9100 
9101  this.lineDistances = [];
9102 
9103  this.boundingBox = null;
9104  this.boundingSphere = null;
9105 
9106  // update flags
9107 
9108  this.elementsNeedUpdate = false;
9109  this.verticesNeedUpdate = false;
9110  this.uvsNeedUpdate = false;
9111  this.normalsNeedUpdate = false;
9112  this.colorsNeedUpdate = false;
9113  this.lineDistancesNeedUpdate = false;
9114  this.groupsNeedUpdate = false;
9115 
9116  }
9117 
9118  Geometry.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
9119 
9120  constructor: Geometry,
9121 
9122  isGeometry: true,
9123 
9124  applyMatrix: function ( matrix ) {
9125 
9126  var normalMatrix = new Matrix3().getNormalMatrix( matrix );
9127 
9128  for ( var i = 0, il = this.vertices.length; i < il; i ++ ) {
9129 
9130  var vertex = this.vertices[ i ];
9131  vertex.applyMatrix4( matrix );
9132 
9133  }
9134 
9135  for ( var i = 0, il = this.faces.length; i < il; i ++ ) {
9136 
9137  var face = this.faces[ i ];
9138  face.normal.applyMatrix3( normalMatrix ).normalize();
9139 
9140  for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {
9141 
9142  face.vertexNormals[ j ].applyMatrix3( normalMatrix ).normalize();
9143 
9144  }
9145 
9146  }
9147 
9148  if ( this.boundingBox !== null ) {
9149 
9150  this.computeBoundingBox();
9151 
9152  }
9153 
9154  if ( this.boundingSphere !== null ) {
9155 
9156  this.computeBoundingSphere();
9157 
9158  }
9159 
9160  this.verticesNeedUpdate = true;
9161  this.normalsNeedUpdate = true;
9162 
9163  return this;
9164 
9165  },
9166 
9167  rotateX: function () {
9168 
9169  // rotate geometry around world x-axis
9170 
9171  var m1 = new Matrix4();
9172 
9173  return function rotateX( angle ) {
9174 
9175  m1.makeRotationX( angle );
9176 
9177  this.applyMatrix( m1 );
9178 
9179  return this;
9180 
9181  };
9182 
9183  }(),
9184 
9185  rotateY: function () {
9186 
9187  // rotate geometry around world y-axis
9188 
9189  var m1 = new Matrix4();
9190 
9191  return function rotateY( angle ) {
9192 
9193  m1.makeRotationY( angle );
9194 
9195  this.applyMatrix( m1 );
9196 
9197  return this;
9198 
9199  };
9200 
9201  }(),
9202 
9203  rotateZ: function () {
9204 
9205  // rotate geometry around world z-axis
9206 
9207  var m1 = new Matrix4();
9208 
9209  return function rotateZ( angle ) {
9210 
9211  m1.makeRotationZ( angle );
9212 
9213  this.applyMatrix( m1 );
9214 
9215  return this;
9216 
9217  };
9218 
9219  }(),
9220 
9221  translate: function () {
9222 
9223  // translate geometry
9224 
9225  var m1 = new Matrix4();
9226 
9227  return function translate( x, y, z ) {
9228 
9229  m1.makeTranslation( x, y, z );
9230 
9231  this.applyMatrix( m1 );
9232 
9233  return this;
9234 
9235  };
9236 
9237  }(),
9238 
9239  scale: function () {
9240 
9241  // scale geometry
9242 
9243  var m1 = new Matrix4();
9244 
9245  return function scale( x, y, z ) {
9246 
9247  m1.makeScale( x, y, z );
9248 
9249  this.applyMatrix( m1 );
9250 
9251  return this;
9252 
9253  };
9254 
9255  }(),
9256 
9257  lookAt: function () {
9258 
9259  var obj = new Object3D();
9260 
9261  return function lookAt( vector ) {
9262 
9263  obj.lookAt( vector );
9264 
9265  obj.updateMatrix();
9266 
9267  this.applyMatrix( obj.matrix );
9268 
9269  };
9270 
9271  }(),
9272 
9273  fromBufferGeometry: function ( geometry ) {
9274 
9275  var scope = this;
9276 
9277  var indices = geometry.index !== null ? geometry.index.array : undefined;
9278  var attributes = geometry.attributes;
9279 
9280  var positions = attributes.position.array;
9281  var normals = attributes.normal !== undefined ? attributes.normal.array : undefined;
9282  var colors = attributes.color !== undefined ? attributes.color.array : undefined;
9283  var uvs = attributes.uv !== undefined ? attributes.uv.array : undefined;
9284  var uvs2 = attributes.uv2 !== undefined ? attributes.uv2.array : undefined;
9285 
9286  if ( uvs2 !== undefined ) this.faceVertexUvs[ 1 ] = [];
9287 
9288  for ( var i = 0, j = 0; i < positions.length; i += 3, j += 2 ) {
9289 
9290  scope.vertices.push( new Vector3().fromArray( positions, i ) );
9291 
9292  if ( colors !== undefined ) {
9293 
9294  scope.colors.push( new Color().fromArray( colors, i ) );
9295 
9296  }
9297 
9298  }
9299 
9300  function addFace( a, b, c, materialIndex ) {
9301 
9302  var vertexColors = ( colors === undefined ) ? [] : [
9303  scope.colors[ a ].clone(),
9304  scope.colors[ b ].clone(),
9305  scope.colors[ c ].clone() ];
9306 
9307  var vertexNormals = ( normals === undefined ) ? [] : [
9308  new Vector3().fromArray( normals, a * 3 ),
9309  new Vector3().fromArray( normals, b * 3 ),
9310  new Vector3().fromArray( normals, c * 3 )
9311  ];
9312 
9313  var face = new Face3( a, b, c, vertexNormals, vertexColors, materialIndex );
9314 
9315  scope.faces.push( face );
9316 
9317  if ( uvs !== undefined ) {
9318 
9319  scope.faceVertexUvs[ 0 ].push( [
9320  new Vector2().fromArray( uvs, a * 2 ),
9321  new Vector2().fromArray( uvs, b * 2 ),
9322  new Vector2().fromArray( uvs, c * 2 )
9323  ] );
9324 
9325  }
9326 
9327  if ( uvs2 !== undefined ) {
9328 
9329  scope.faceVertexUvs[ 1 ].push( [
9330  new Vector2().fromArray( uvs2, a * 2 ),
9331  new Vector2().fromArray( uvs2, b * 2 ),
9332  new Vector2().fromArray( uvs2, c * 2 )
9333  ] );
9334 
9335  }
9336 
9337  }
9338 
9339  var groups = geometry.groups;
9340 
9341  if ( groups.length > 0 ) {
9342 
9343  for ( var i = 0; i < groups.length; i ++ ) {
9344 
9345  var group = groups[ i ];
9346 
9347  var start = group.start;
9348  var count = group.count;
9349 
9350  for ( var j = start, jl = start + count; j < jl; j += 3 ) {
9351 
9352  if ( indices !== undefined ) {
9353 
9354  addFace( indices[ j ], indices[ j + 1 ], indices[ j + 2 ], group.materialIndex );
9355 
9356  } else {
9357 
9358  addFace( j, j + 1, j + 2, group.materialIndex );
9359 
9360  }
9361 
9362  }
9363 
9364  }
9365 
9366  } else {
9367 
9368  if ( indices !== undefined ) {
9369 
9370  for ( var i = 0; i < indices.length; i += 3 ) {
9371 
9372  addFace( indices[ i ], indices[ i + 1 ], indices[ i + 2 ] );
9373 
9374  }
9375 
9376  } else {
9377 
9378  for ( var i = 0; i < positions.length / 3; i += 3 ) {
9379 
9380  addFace( i, i + 1, i + 2 );
9381 
9382  }
9383 
9384  }
9385 
9386  }
9387 
9388  this.computeFaceNormals();
9389 
9390  if ( geometry.boundingBox !== null ) {
9391 
9392  this.boundingBox = geometry.boundingBox.clone();
9393 
9394  }
9395 
9396  if ( geometry.boundingSphere !== null ) {
9397 
9398  this.boundingSphere = geometry.boundingSphere.clone();
9399 
9400  }
9401 
9402  return this;
9403 
9404  },
9405 
9406  center: function () {
9407 
9408  var offset = new Vector3();
9409 
9410  return function center() {
9411 
9412  this.computeBoundingBox();
9413 
9414  this.boundingBox.getCenter( offset ).negate();
9415 
9416  this.translate( offset.x, offset.y, offset.z );
9417 
9418  return this;
9419 
9420  };
9421 
9422  }(),
9423 
9424  normalize: function () {
9425 
9426  this.computeBoundingSphere();
9427 
9428  var center = this.boundingSphere.center;
9429  var radius = this.boundingSphere.radius;
9430 
9431  var s = radius === 0 ? 1 : 1.0 / radius;
9432 
9433  var matrix = new Matrix4();
9434  matrix.set(
9435  s, 0, 0, - s * center.x,
9436  0, s, 0, - s * center.y,
9437  0, 0, s, - s * center.z,
9438  0, 0, 0, 1
9439  );
9440 
9441  this.applyMatrix( matrix );
9442 
9443  return this;
9444 
9445  },
9446 
9447  computeFaceNormals: function () {
9448 
9449  var cb = new Vector3(), ab = new Vector3();
9450 
9451  for ( var f = 0, fl = this.faces.length; f < fl; f ++ ) {
9452 
9453  var face = this.faces[ f ];
9454 
9455  var vA = this.vertices[ face.a ];
9456  var vB = this.vertices[ face.b ];
9457  var vC = this.vertices[ face.c ];
9458 
9459  cb.subVectors( vC, vB );
9460  ab.subVectors( vA, vB );
9461  cb.cross( ab );
9462 
9463  cb.normalize();
9464 
9465  face.normal.copy( cb );
9466 
9467  }
9468 
9469  },
9470 
9471  computeVertexNormals: function ( areaWeighted ) {
9472 
9473  if ( areaWeighted === undefined ) areaWeighted = true;
9474 
9475  var v, vl, f, fl, face, vertices;
9476 
9477  vertices = new Array( this.vertices.length );
9478 
9479  for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
9480 
9481  vertices[ v ] = new Vector3();
9482 
9483  }
9484 
9485  if ( areaWeighted ) {
9486 
9487  // vertex normals weighted by triangle areas
9488  // http://www.iquilezles.org/www/articles/normals/normals.htm
9489 
9490  var vA, vB, vC;
9491  var cb = new Vector3(), ab = new Vector3();
9492 
9493  for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
9494 
9495  face = this.faces[ f ];
9496 
9497  vA = this.vertices[ face.a ];
9498  vB = this.vertices[ face.b ];
9499  vC = this.vertices[ face.c ];
9500 
9501  cb.subVectors( vC, vB );
9502  ab.subVectors( vA, vB );
9503  cb.cross( ab );
9504 
9505  vertices[ face.a ].add( cb );
9506  vertices[ face.b ].add( cb );
9507  vertices[ face.c ].add( cb );
9508 
9509  }
9510 
9511  } else {
9512 
9513  this.computeFaceNormals();
9514 
9515  for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
9516 
9517  face = this.faces[ f ];
9518 
9519  vertices[ face.a ].add( face.normal );
9520  vertices[ face.b ].add( face.normal );
9521  vertices[ face.c ].add( face.normal );
9522 
9523  }
9524 
9525  }
9526 
9527  for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
9528 
9529  vertices[ v ].normalize();
9530 
9531  }
9532 
9533  for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
9534 
9535  face = this.faces[ f ];
9536 
9537  var vertexNormals = face.vertexNormals;
9538 
9539  if ( vertexNormals.length === 3 ) {
9540 
9541  vertexNormals[ 0 ].copy( vertices[ face.a ] );
9542  vertexNormals[ 1 ].copy( vertices[ face.b ] );
9543  vertexNormals[ 2 ].copy( vertices[ face.c ] );
9544 
9545  } else {
9546 
9547  vertexNormals[ 0 ] = vertices[ face.a ].clone();
9548  vertexNormals[ 1 ] = vertices[ face.b ].clone();
9549  vertexNormals[ 2 ] = vertices[ face.c ].clone();
9550 
9551  }
9552 
9553  }
9554 
9555  if ( this.faces.length > 0 ) {
9556 
9557  this.normalsNeedUpdate = true;
9558 
9559  }
9560 
9561  },
9562 
9563  computeFlatVertexNormals: function () {
9564 
9565  var f, fl, face;
9566 
9567  this.computeFaceNormals();
9568 
9569  for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
9570 
9571  face = this.faces[ f ];
9572 
9573  var vertexNormals = face.vertexNormals;
9574 
9575  if ( vertexNormals.length === 3 ) {
9576 
9577  vertexNormals[ 0 ].copy( face.normal );
9578  vertexNormals[ 1 ].copy( face.normal );
9579  vertexNormals[ 2 ].copy( face.normal );
9580 
9581  } else {
9582 
9583  vertexNormals[ 0 ] = face.normal.clone();
9584  vertexNormals[ 1 ] = face.normal.clone();
9585  vertexNormals[ 2 ] = face.normal.clone();
9586 
9587  }
9588 
9589  }
9590 
9591  if ( this.faces.length > 0 ) {
9592 
9593  this.normalsNeedUpdate = true;
9594 
9595  }
9596 
9597  },
9598 
9599  computeMorphNormals: function () {
9600 
9601  var i, il, f, fl, face;
9602 
9603  // save original normals
9604  // - create temp variables on first access
9605  // otherwise just copy (for faster repeated calls)
9606 
9607  for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
9608 
9609  face = this.faces[ f ];
9610 
9611  if ( ! face.__originalFaceNormal ) {
9612 
9613  face.__originalFaceNormal = face.normal.clone();
9614 
9615  } else {
9616 
9617  face.__originalFaceNormal.copy( face.normal );
9618 
9619  }
9620 
9621  if ( ! face.__originalVertexNormals ) face.__originalVertexNormals = [];
9622 
9623  for ( i = 0, il = face.vertexNormals.length; i < il; i ++ ) {
9624 
9625  if ( ! face.__originalVertexNormals[ i ] ) {
9626 
9627  face.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone();
9628 
9629  } else {
9630 
9631  face.__originalVertexNormals[ i ].copy( face.vertexNormals[ i ] );
9632 
9633  }
9634 
9635  }
9636 
9637  }
9638 
9639  // use temp geometry to compute face and vertex normals for each morph
9640 
9641  var tmpGeo = new Geometry();
9642  tmpGeo.faces = this.faces;
9643 
9644  for ( i = 0, il = this.morphTargets.length; i < il; i ++ ) {
9645 
9646  // create on first access
9647 
9648  if ( ! this.morphNormals[ i ] ) {
9649 
9650  this.morphNormals[ i ] = {};
9651  this.morphNormals[ i ].faceNormals = [];
9652  this.morphNormals[ i ].vertexNormals = [];
9653 
9654  var dstNormalsFace = this.morphNormals[ i ].faceNormals;
9655  var dstNormalsVertex = this.morphNormals[ i ].vertexNormals;
9656 
9657  var faceNormal, vertexNormals;
9658 
9659  for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
9660 
9661  faceNormal = new Vector3();
9662  vertexNormals = { a: new Vector3(), b: new Vector3(), c: new Vector3() };
9663 
9664  dstNormalsFace.push( faceNormal );
9665  dstNormalsVertex.push( vertexNormals );
9666 
9667  }
9668 
9669  }
9670 
9671  var morphNormals = this.morphNormals[ i ];
9672 
9673  // set vertices to morph target
9674 
9675  tmpGeo.vertices = this.morphTargets[ i ].vertices;
9676 
9677  // compute morph normals
9678 
9679  tmpGeo.computeFaceNormals();
9680  tmpGeo.computeVertexNormals();
9681 
9682  // store morph normals
9683 
9684  var faceNormal, vertexNormals;
9685 
9686  for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
9687 
9688  face = this.faces[ f ];
9689 
9690  faceNormal = morphNormals.faceNormals[ f ];
9691  vertexNormals = morphNormals.vertexNormals[ f ];
9692 
9693  faceNormal.copy( face.normal );
9694 
9695  vertexNormals.a.copy( face.vertexNormals[ 0 ] );
9696  vertexNormals.b.copy( face.vertexNormals[ 1 ] );
9697  vertexNormals.c.copy( face.vertexNormals[ 2 ] );
9698 
9699  }
9700 
9701  }
9702 
9703  // restore original normals
9704 
9705  for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
9706 
9707  face = this.faces[ f ];
9708 
9709  face.normal = face.__originalFaceNormal;
9710  face.vertexNormals = face.__originalVertexNormals;
9711 
9712  }
9713 
9714  },
9715 
9716  computeBoundingBox: function () {
9717 
9718  if ( this.boundingBox === null ) {
9719 
9720  this.boundingBox = new Box3();
9721 
9722  }
9723 
9724  this.boundingBox.setFromPoints( this.vertices );
9725 
9726  },
9727 
9728  computeBoundingSphere: function () {
9729 
9730  if ( this.boundingSphere === null ) {
9731 
9732  this.boundingSphere = new Sphere();
9733 
9734  }
9735 
9736  this.boundingSphere.setFromPoints( this.vertices );
9737 
9738  },
9739 
9740  merge: function ( geometry, matrix, materialIndexOffset ) {
9741 
9742  if ( ! ( geometry && geometry.isGeometry ) ) {
9743 
9744  console.error( 'THREE.Geometry.merge(): geometry not an instance of THREE.Geometry.', geometry );
9745  return;
9746 
9747  }
9748 
9749  var normalMatrix,
9750  vertexOffset = this.vertices.length,
9751  vertices1 = this.vertices,
9752  vertices2 = geometry.vertices,
9753  faces1 = this.faces,
9754  faces2 = geometry.faces,
9755  uvs1 = this.faceVertexUvs[ 0 ],
9756  uvs2 = geometry.faceVertexUvs[ 0 ],
9757  colors1 = this.colors,
9758  colors2 = geometry.colors;
9759 
9760  if ( materialIndexOffset === undefined ) materialIndexOffset = 0;
9761 
9762  if ( matrix !== undefined ) {
9763 
9764  normalMatrix = new Matrix3().getNormalMatrix( matrix );
9765 
9766  }
9767 
9768  // vertices
9769 
9770  for ( var i = 0, il = vertices2.length; i < il; i ++ ) {
9771 
9772  var vertex = vertices2[ i ];
9773 
9774  var vertexCopy = vertex.clone();
9775 
9776  if ( matrix !== undefined ) vertexCopy.applyMatrix4( matrix );
9777 
9778  vertices1.push( vertexCopy );
9779 
9780  }
9781 
9782  // colors
9783 
9784  for ( var i = 0, il = colors2.length; i < il; i ++ ) {
9785 
9786  colors1.push( colors2[ i ].clone() );
9787 
9788  }
9789 
9790  // faces
9791 
9792  for ( i = 0, il = faces2.length; i < il; i ++ ) {
9793 
9794  var face = faces2[ i ], faceCopy, normal, color,
9795  faceVertexNormals = face.vertexNormals,
9796  faceVertexColors = face.vertexColors;
9797 
9798  faceCopy = new Face3( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset );
9799  faceCopy.normal.copy( face.normal );
9800 
9801  if ( normalMatrix !== undefined ) {
9802 
9803  faceCopy.normal.applyMatrix3( normalMatrix ).normalize();
9804 
9805  }
9806 
9807  for ( var j = 0, jl = faceVertexNormals.length; j < jl; j ++ ) {
9808 
9809  normal = faceVertexNormals[ j ].clone();
9810 
9811  if ( normalMatrix !== undefined ) {
9812 
9813  normal.applyMatrix3( normalMatrix ).normalize();
9814 
9815  }
9816 
9817  faceCopy.vertexNormals.push( normal );
9818 
9819  }
9820 
9821  faceCopy.color.copy( face.color );
9822 
9823  for ( var j = 0, jl = faceVertexColors.length; j < jl; j ++ ) {
9824 
9825  color = faceVertexColors[ j ];
9826  faceCopy.vertexColors.push( color.clone() );
9827 
9828  }
9829 
9830  faceCopy.materialIndex = face.materialIndex + materialIndexOffset;
9831 
9832  faces1.push( faceCopy );
9833 
9834  }
9835 
9836  // uvs
9837 
9838  for ( i = 0, il = uvs2.length; i < il; i ++ ) {
9839 
9840  var uv = uvs2[ i ], uvCopy = [];
9841 
9842  if ( uv === undefined ) {
9843 
9844  continue;
9845 
9846  }
9847 
9848  for ( var j = 0, jl = uv.length; j < jl; j ++ ) {
9849 
9850  uvCopy.push( uv[ j ].clone() );
9851 
9852  }
9853 
9854  uvs1.push( uvCopy );
9855 
9856  }
9857 
9858  },
9859 
9860  mergeMesh: function ( mesh ) {
9861 
9862  if ( ! ( mesh && mesh.isMesh ) ) {
9863 
9864  console.error( 'THREE.Geometry.mergeMesh(): mesh not an instance of THREE.Mesh.', mesh );
9865  return;
9866 
9867  }
9868 
9869  if ( mesh.matrixAutoUpdate ) mesh.updateMatrix();
9870 
9871  this.merge( mesh.geometry, mesh.matrix );
9872 
9873  },
9874 
9875  /*
9876  * Checks for duplicate vertices with hashmap.
9877  * Duplicated vertices are removed
9878  * and faces' vertices are updated.
9879  */
9880 
9881  mergeVertices: function () {
9882 
9883  var verticesMap = {}; // Hashmap for looking up vertices by position coordinates (and making sure they are unique)
9884  var unique = [], changes = [];
9885 
9886  var v, key;
9887  var precisionPoints = 4; // number of decimal points, e.g. 4 for epsilon of 0.0001
9888  var precision = Math.pow( 10, precisionPoints );
9889  var i, il, face;
9890  var indices, j, jl;
9891 
9892  for ( i = 0, il = this.vertices.length; i < il; i ++ ) {
9893 
9894  v = this.vertices[ i ];
9895  key = Math.round( v.x * precision ) + '_' + Math.round( v.y * precision ) + '_' + Math.round( v.z * precision );
9896 
9897  if ( verticesMap[ key ] === undefined ) {
9898 
9899  verticesMap[ key ] = i;
9900  unique.push( this.vertices[ i ] );
9901  changes[ i ] = unique.length - 1;
9902 
9903  } else {
9904 
9905  //console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]);
9906  changes[ i ] = changes[ verticesMap[ key ] ];
9907 
9908  }
9909 
9910  }
9911 
9912 
9913  // if faces are completely degenerate after merging vertices, we
9914  // have to remove them from the geometry.
9915  var faceIndicesToRemove = [];
9916 
9917  for ( i = 0, il = this.faces.length; i < il; i ++ ) {
9918 
9919  face = this.faces[ i ];
9920 
9921  face.a = changes[ face.a ];
9922  face.b = changes[ face.b ];
9923  face.c = changes[ face.c ];
9924 
9925  indices = [ face.a, face.b, face.c ];
9926 
9927  // if any duplicate vertices are found in a Face3
9928  // we have to remove the face as nothing can be saved
9929  for ( var n = 0; n < 3; n ++ ) {
9930 
9931  if ( indices[ n ] === indices[ ( n + 1 ) % 3 ] ) {
9932 
9933  faceIndicesToRemove.push( i );
9934  break;
9935 
9936  }
9937 
9938  }
9939 
9940  }
9941 
9942  for ( i = faceIndicesToRemove.length - 1; i >= 0; i -- ) {
9943 
9944  var idx = faceIndicesToRemove[ i ];
9945 
9946  this.faces.splice( idx, 1 );
9947 
9948  for ( j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) {
9949 
9950  this.faceVertexUvs[ j ].splice( idx, 1 );
9951 
9952  }
9953 
9954  }
9955 
9956  // Use unique set of vertices
9957 
9958  var diff = this.vertices.length - unique.length;
9959  this.vertices = unique;
9960  return diff;
9961 
9962  },
9963 
9964  setFromPoints: function ( points ) {
9965 
9966  this.vertices = [];
9967 
9968  for ( var i = 0, l = points.length; i < l; i ++ ) {
9969 
9970  var point = points[ i ];
9971  this.vertices.push( new Vector3( point.x, point.y, point.z || 0 ) );
9972 
9973  }
9974 
9975  return this;
9976 
9977  },
9978 
9979  sortFacesByMaterialIndex: function () {
9980 
9981  var faces = this.faces;
9982  var length = faces.length;
9983 
9984  // tag faces
9985 
9986  for ( var i = 0; i < length; i ++ ) {
9987 
9988  faces[ i ]._id = i;
9989 
9990  }
9991 
9992  // sort faces
9993 
9994  function materialIndexSort( a, b ) {
9995 
9996  return a.materialIndex - b.materialIndex;
9997 
9998  }
9999 
10000  faces.sort( materialIndexSort );
10001 
10002  // sort uvs
10003 
10004  var uvs1 = this.faceVertexUvs[ 0 ];
10005  var uvs2 = this.faceVertexUvs[ 1 ];
10006 
10007  var newUvs1, newUvs2;
10008 
10009  if ( uvs1 && uvs1.length === length ) newUvs1 = [];
10010  if ( uvs2 && uvs2.length === length ) newUvs2 = [];
10011 
10012  for ( var i = 0; i < length; i ++ ) {
10013 
10014  var id = faces[ i ]._id;
10015 
10016  if ( newUvs1 ) newUvs1.push( uvs1[ id ] );
10017  if ( newUvs2 ) newUvs2.push( uvs2[ id ] );
10018 
10019  }
10020 
10021  if ( newUvs1 ) this.faceVertexUvs[ 0 ] = newUvs1;
10022  if ( newUvs2 ) this.faceVertexUvs[ 1 ] = newUvs2;
10023 
10024  },
10025 
10026  toJSON: function () {
10027 
10028  var data = {
10029  metadata: {
10030  version: 4.5,
10031  type: 'Geometry',
10032  generator: 'Geometry.toJSON'
10033  }
10034  };
10035 
10036  // standard Geometry serialization
10037 
10038  data.uuid = this.uuid;
10039  data.type = this.type;
10040  if ( this.name !== '' ) data.name = this.name;
10041 
10042  if ( this.parameters !== undefined ) {
10043 
10044  var parameters = this.parameters;
10045 
10046  for ( var key in parameters ) {
10047 
10048  if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ];
10049 
10050  }
10051 
10052  return data;
10053 
10054  }
10055 
10056  var vertices = [];
10057 
10058  for ( var i = 0; i < this.vertices.length; i ++ ) {
10059 
10060  var vertex = this.vertices[ i ];
10061  vertices.push( vertex.x, vertex.y, vertex.z );
10062 
10063  }
10064 
10065  var faces = [];
10066  var normals = [];
10067  var normalsHash = {};
10068  var colors = [];
10069  var colorsHash = {};
10070  var uvs = [];
10071  var uvsHash = {};
10072 
10073  for ( var i = 0; i < this.faces.length; i ++ ) {
10074 
10075  var face = this.faces[ i ];
10076 
10077  var hasMaterial = true;
10078  var hasFaceUv = false; // deprecated
10079  var hasFaceVertexUv = this.faceVertexUvs[ 0 ][ i ] !== undefined;
10080  var hasFaceNormal = face.normal.length() > 0;
10081  var hasFaceVertexNormal = face.vertexNormals.length > 0;
10082  var hasFaceColor = face.color.r !== 1 || face.color.g !== 1 || face.color.b !== 1;
10083  var hasFaceVertexColor = face.vertexColors.length > 0;
10084 
10085  var faceType = 0;
10086 
10087  faceType = setBit( faceType, 0, 0 ); // isQuad
10088  faceType = setBit( faceType, 1, hasMaterial );
10089  faceType = setBit( faceType, 2, hasFaceUv );
10090  faceType = setBit( faceType, 3, hasFaceVertexUv );
10091  faceType = setBit( faceType, 4, hasFaceNormal );
10092  faceType = setBit( faceType, 5, hasFaceVertexNormal );
10093  faceType = setBit( faceType, 6, hasFaceColor );
10094  faceType = setBit( faceType, 7, hasFaceVertexColor );
10095 
10096  faces.push( faceType );
10097  faces.push( face.a, face.b, face.c );
10098  faces.push( face.materialIndex );
10099 
10100  if ( hasFaceVertexUv ) {
10101 
10102  var faceVertexUvs = this.faceVertexUvs[ 0 ][ i ];
10103 
10104  faces.push(
10105  getUvIndex( faceVertexUvs[ 0 ] ),
10106  getUvIndex( faceVertexUvs[ 1 ] ),
10107  getUvIndex( faceVertexUvs[ 2 ] )
10108  );
10109 
10110  }
10111 
10112  if ( hasFaceNormal ) {
10113 
10114  faces.push( getNormalIndex( face.normal ) );
10115 
10116  }
10117 
10118  if ( hasFaceVertexNormal ) {
10119 
10120  var vertexNormals = face.vertexNormals;
10121 
10122  faces.push(
10123  getNormalIndex( vertexNormals[ 0 ] ),
10124  getNormalIndex( vertexNormals[ 1 ] ),
10125  getNormalIndex( vertexNormals[ 2 ] )
10126  );
10127 
10128  }
10129 
10130  if ( hasFaceColor ) {
10131 
10132  faces.push( getColorIndex( face.color ) );
10133 
10134  }
10135 
10136  if ( hasFaceVertexColor ) {
10137 
10138  var vertexColors = face.vertexColors;
10139 
10140  faces.push(
10141  getColorIndex( vertexColors[ 0 ] ),
10142  getColorIndex( vertexColors[ 1 ] ),
10143  getColorIndex( vertexColors[ 2 ] )
10144  );
10145 
10146  }
10147 
10148  }
10149 
10150  function setBit( value, position, enabled ) {
10151 
10152  return enabled ? value | ( 1 << position ) : value & ( ~ ( 1 << position ) );
10153 
10154  }
10155 
10156  function getNormalIndex( normal ) {
10157 
10158  var hash = normal.x.toString() + normal.y.toString() + normal.z.toString();
10159 
10160  if ( normalsHash[ hash ] !== undefined ) {
10161 
10162  return normalsHash[ hash ];
10163 
10164  }
10165 
10166  normalsHash[ hash ] = normals.length / 3;
10167  normals.push( normal.x, normal.y, normal.z );
10168 
10169  return normalsHash[ hash ];
10170 
10171  }
10172 
10173  function getColorIndex( color ) {
10174 
10175  var hash = color.r.toString() + color.g.toString() + color.b.toString();
10176 
10177  if ( colorsHash[ hash ] !== undefined ) {
10178 
10179  return colorsHash[ hash ];
10180 
10181  }
10182 
10183  colorsHash[ hash ] = colors.length;
10184  colors.push( color.getHex() );
10185 
10186  return colorsHash[ hash ];
10187 
10188  }
10189 
10190  function getUvIndex( uv ) {
10191 
10192  var hash = uv.x.toString() + uv.y.toString();
10193 
10194  if ( uvsHash[ hash ] !== undefined ) {
10195 
10196  return uvsHash[ hash ];
10197 
10198  }
10199 
10200  uvsHash[ hash ] = uvs.length / 2;
10201  uvs.push( uv.x, uv.y );
10202 
10203  return uvsHash[ hash ];
10204 
10205  }
10206 
10207  data.data = {};
10208 
10209  data.data.vertices = vertices;
10210  data.data.normals = normals;
10211  if ( colors.length > 0 ) data.data.colors = colors;
10212  if ( uvs.length > 0 ) data.data.uvs = [ uvs ]; // temporal backward compatibility
10213  data.data.faces = faces;
10214 
10215  return data;
10216 
10217  },
10218 
10219  clone: function () {
10220 
10221  /*
10222  // Handle primitives
10223 
10224  var parameters = this.parameters;
10225 
10226  if ( parameters !== undefined ) {
10227 
10228  var values = [];
10229 
10230  for ( var key in parameters ) {
10231 
10232  values.push( parameters[ key ] );
10233 
10234  }
10235 
10236  var geometry = Object.create( this.constructor.prototype );
10237  this.constructor.apply( geometry, values );
10238  return geometry;
10239 
10240  }
10241 
10242  return new this.constructor().copy( this );
10243  */
10244 
10245  return new Geometry().copy( this );
10246 
10247  },
10248 
10249  copy: function ( source ) {
10250 
10251  var i, il, j, jl, k, kl;
10252 
10253  // reset
10254 
10255  this.vertices = [];
10256  this.colors = [];
10257  this.faces = [];
10258  this.faceVertexUvs = [[]];
10259  this.morphTargets = [];
10260  this.morphNormals = [];
10261  this.skinWeights = [];
10262  this.skinIndices = [];
10263  this.lineDistances = [];
10264  this.boundingBox = null;
10265  this.boundingSphere = null;
10266 
10267  // name
10268 
10269  this.name = source.name;
10270 
10271  // vertices
10272 
10273  var vertices = source.vertices;
10274 
10275  for ( i = 0, il = vertices.length; i < il; i ++ ) {
10276 
10277  this.vertices.push( vertices[ i ].clone() );
10278 
10279  }
10280 
10281  // colors
10282 
10283  var colors = source.colors;
10284 
10285  for ( i = 0, il = colors.length; i < il; i ++ ) {
10286 
10287  this.colors.push( colors[ i ].clone() );
10288 
10289  }
10290 
10291  // faces
10292 
10293  var faces = source.faces;
10294 
10295  for ( i = 0, il = faces.length; i < il; i ++ ) {
10296 
10297  this.faces.push( faces[ i ].clone() );
10298 
10299  }
10300 
10301  // face vertex uvs
10302 
10303  for ( i = 0, il = source.faceVertexUvs.length; i < il; i ++ ) {
10304 
10305  var faceVertexUvs = source.faceVertexUvs[ i ];
10306 
10307  if ( this.faceVertexUvs[ i ] === undefined ) {
10308 
10309  this.faceVertexUvs[ i ] = [];
10310 
10311  }
10312 
10313  for ( j = 0, jl = faceVertexUvs.length; j < jl; j ++ ) {
10314 
10315  var uvs = faceVertexUvs[ j ], uvsCopy = [];
10316 
10317  for ( k = 0, kl = uvs.length; k < kl; k ++ ) {
10318 
10319  var uv = uvs[ k ];
10320 
10321  uvsCopy.push( uv.clone() );
10322 
10323  }
10324 
10325  this.faceVertexUvs[ i ].push( uvsCopy );
10326 
10327  }
10328 
10329  }
10330 
10331  // morph targets
10332 
10333  var morphTargets = source.morphTargets;
10334 
10335  for ( i = 0, il = morphTargets.length; i < il; i ++ ) {
10336 
10337  var morphTarget = {};
10338  morphTarget.name = morphTargets[ i ].name;
10339 
10340  // vertices
10341 
10342  if ( morphTargets[ i ].vertices !== undefined ) {
10343 
10344  morphTarget.vertices = [];
10345 
10346  for ( j = 0, jl = morphTargets[ i ].vertices.length; j < jl; j ++ ) {
10347 
10348  morphTarget.vertices.push( morphTargets[ i ].vertices[ j ].clone() );
10349 
10350  }
10351 
10352  }
10353 
10354  // normals
10355 
10356  if ( morphTargets[ i ].normals !== undefined ) {
10357 
10358  morphTarget.normals = [];
10359 
10360  for ( j = 0, jl = morphTargets[ i ].normals.length; j < jl; j ++ ) {
10361 
10362  morphTarget.normals.push( morphTargets[ i ].normals[ j ].clone() );
10363 
10364  }
10365 
10366  }
10367 
10368  this.morphTargets.push( morphTarget );
10369 
10370  }
10371 
10372  // morph normals
10373 
10374  var morphNormals = source.morphNormals;
10375 
10376  for ( i = 0, il = morphNormals.length; i < il; i ++ ) {
10377 
10378  var morphNormal = {};
10379 
10380  // vertex normals
10381 
10382  if ( morphNormals[ i ].vertexNormals !== undefined ) {
10383 
10384  morphNormal.vertexNormals = [];
10385 
10386  for ( j = 0, jl = morphNormals[ i ].vertexNormals.length; j < jl; j ++ ) {
10387 
10388  var srcVertexNormal = morphNormals[ i ].vertexNormals[ j ];
10389  var destVertexNormal = {};
10390 
10391  destVertexNormal.a = srcVertexNormal.a.clone();
10392  destVertexNormal.b = srcVertexNormal.b.clone();
10393  destVertexNormal.c = srcVertexNormal.c.clone();
10394 
10395  morphNormal.vertexNormals.push( destVertexNormal );
10396 
10397  }
10398 
10399  }
10400 
10401  // face normals
10402 
10403  if ( morphNormals[ i ].faceNormals !== undefined ) {
10404 
10405  morphNormal.faceNormals = [];
10406 
10407  for ( j = 0, jl = morphNormals[ i ].faceNormals.length; j < jl; j ++ ) {
10408 
10409  morphNormal.faceNormals.push( morphNormals[ i ].faceNormals[ j ].clone() );
10410 
10411  }
10412 
10413  }
10414 
10415  this.morphNormals.push( morphNormal );
10416 
10417  }
10418 
10419  // skin weights
10420 
10421  var skinWeights = source.skinWeights;
10422 
10423  for ( i = 0, il = skinWeights.length; i < il; i ++ ) {
10424 
10425  this.skinWeights.push( skinWeights[ i ].clone() );
10426 
10427  }
10428 
10429  // skin indices
10430 
10431  var skinIndices = source.skinIndices;
10432 
10433  for ( i = 0, il = skinIndices.length; i < il; i ++ ) {
10434 
10435  this.skinIndices.push( skinIndices[ i ].clone() );
10436 
10437  }
10438 
10439  // line distances
10440 
10441  var lineDistances = source.lineDistances;
10442 
10443  for ( i = 0, il = lineDistances.length; i < il; i ++ ) {
10444 
10445  this.lineDistances.push( lineDistances[ i ] );
10446 
10447  }
10448 
10449  // bounding box
10450 
10451  var boundingBox = source.boundingBox;
10452 
10453  if ( boundingBox !== null ) {
10454 
10455  this.boundingBox = boundingBox.clone();
10456 
10457  }
10458 
10459  // bounding sphere
10460 
10461  var boundingSphere = source.boundingSphere;
10462 
10463  if ( boundingSphere !== null ) {
10464 
10465  this.boundingSphere = boundingSphere.clone();
10466 
10467  }
10468 
10469  // update flags
10470 
10471  this.elementsNeedUpdate = source.elementsNeedUpdate;
10472  this.verticesNeedUpdate = source.verticesNeedUpdate;
10473  this.uvsNeedUpdate = source.uvsNeedUpdate;
10474  this.normalsNeedUpdate = source.normalsNeedUpdate;
10475  this.colorsNeedUpdate = source.colorsNeedUpdate;
10476  this.lineDistancesNeedUpdate = source.lineDistancesNeedUpdate;
10477  this.groupsNeedUpdate = source.groupsNeedUpdate;
10478 
10479  return this;
10480 
10481  },
10482 
10483  dispose: function () {
10484 
10485  this.dispatchEvent( { type: 'dispose' } );
10486 
10487  }
10488 
10489  } );
10490 
10495  function BufferAttribute( array, itemSize, normalized ) {
10496 
10497  if ( Array.isArray( array ) ) {
10498 
10499  throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' );
10500 
10501  }
10502 
10503  this.name = '';
10504 
10505  this.array = array;
10506  this.itemSize = itemSize;
10507  this.count = array !== undefined ? array.length / itemSize : 0;
10508  this.normalized = normalized === true;
10509 
10510  this.dynamic = false;
10511  this.updateRange = { offset: 0, count: - 1 };
10512 
10513  this.version = 0;
10514 
10515  }
10516 
10517  Object.defineProperty( BufferAttribute.prototype, 'needsUpdate', {
10518 
10519  set: function ( value ) {
10520 
10521  if ( value === true ) this.version ++;
10522 
10523  }
10524 
10525  } );
10526 
10527  Object.assign( BufferAttribute.prototype, {
10528 
10529  isBufferAttribute: true,
10530 
10531  onUploadCallback: function () {},
10532 
10533  setArray: function ( array ) {
10534 
10535  if ( Array.isArray( array ) ) {
10536 
10537  throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' );
10538 
10539  }
10540 
10541  this.count = array !== undefined ? array.length / this.itemSize : 0;
10542  this.array = array;
10543 
10544  return this;
10545 
10546  },
10547 
10548  setDynamic: function ( value ) {
10549 
10550  this.dynamic = value;
10551 
10552  return this;
10553 
10554  },
10555 
10556  copy: function ( source ) {
10557 
10558  this.name = source.name;
10559  this.array = new source.array.constructor( source.array );
10560  this.itemSize = source.itemSize;
10561  this.count = source.count;
10562  this.normalized = source.normalized;
10563 
10564  this.dynamic = source.dynamic;
10565 
10566  return this;
10567 
10568  },
10569 
10570  copyAt: function ( index1, attribute, index2 ) {
10571 
10572  index1 *= this.itemSize;
10573  index2 *= attribute.itemSize;
10574 
10575  for ( var i = 0, l = this.itemSize; i < l; i ++ ) {
10576 
10577  this.array[ index1 + i ] = attribute.array[ index2 + i ];
10578 
10579  }
10580 
10581  return this;
10582 
10583  },
10584 
10585  copyArray: function ( array ) {
10586 
10587  this.array.set( array );
10588 
10589  return this;
10590 
10591  },
10592 
10593  copyColorsArray: function ( colors ) {
10594 
10595  var array = this.array, offset = 0;
10596 
10597  for ( var i = 0, l = colors.length; i < l; i ++ ) {
10598 
10599  var color = colors[ i ];
10600 
10601  if ( color === undefined ) {
10602 
10603  console.warn( 'THREE.BufferAttribute.copyColorsArray(): color is undefined', i );
10604  color = new Color();
10605 
10606  }
10607 
10608  array[ offset ++ ] = color.r;
10609  array[ offset ++ ] = color.g;
10610  array[ offset ++ ] = color.b;
10611 
10612  }
10613 
10614  return this;
10615 
10616  },
10617 
10618  copyVector2sArray: function ( vectors ) {
10619 
10620  var array = this.array, offset = 0;
10621 
10622  for ( var i = 0, l = vectors.length; i < l; i ++ ) {
10623 
10624  var vector = vectors[ i ];
10625 
10626  if ( vector === undefined ) {
10627 
10628  console.warn( 'THREE.BufferAttribute.copyVector2sArray(): vector is undefined', i );
10629  vector = new Vector2();
10630 
10631  }
10632 
10633  array[ offset ++ ] = vector.x;
10634  array[ offset ++ ] = vector.y;
10635 
10636  }
10637 
10638  return this;
10639 
10640  },
10641 
10642  copyVector3sArray: function ( vectors ) {
10643 
10644  var array = this.array, offset = 0;
10645 
10646  for ( var i = 0, l = vectors.length; i < l; i ++ ) {
10647 
10648  var vector = vectors[ i ];
10649 
10650  if ( vector === undefined ) {
10651 
10652  console.warn( 'THREE.BufferAttribute.copyVector3sArray(): vector is undefined', i );
10653  vector = new Vector3();
10654 
10655  }
10656 
10657  array[ offset ++ ] = vector.x;
10658  array[ offset ++ ] = vector.y;
10659  array[ offset ++ ] = vector.z;
10660 
10661  }
10662 
10663  return this;
10664 
10665  },
10666 
10667  copyVector4sArray: function ( vectors ) {
10668 
10669  var array = this.array, offset = 0;
10670 
10671  for ( var i = 0, l = vectors.length; i < l; i ++ ) {
10672 
10673  var vector = vectors[ i ];
10674 
10675  if ( vector === undefined ) {
10676 
10677  console.warn( 'THREE.BufferAttribute.copyVector4sArray(): vector is undefined', i );
10678  vector = new Vector4();
10679 
10680  }
10681 
10682  array[ offset ++ ] = vector.x;
10683  array[ offset ++ ] = vector.y;
10684  array[ offset ++ ] = vector.z;
10685  array[ offset ++ ] = vector.w;
10686 
10687  }
10688 
10689  return this;
10690 
10691  },
10692 
10693  set: function ( value, offset ) {
10694 
10695  if ( offset === undefined ) offset = 0;
10696 
10697  this.array.set( value, offset );
10698 
10699  return this;
10700 
10701  },
10702 
10703  getX: function ( index ) {
10704 
10705  return this.array[ index * this.itemSize ];
10706 
10707  },
10708 
10709  setX: function ( index, x ) {
10710 
10711  this.array[ index * this.itemSize ] = x;
10712 
10713  return this;
10714 
10715  },
10716 
10717  getY: function ( index ) {
10718 
10719  return this.array[ index * this.itemSize + 1 ];
10720 
10721  },
10722 
10723  setY: function ( index, y ) {
10724 
10725  this.array[ index * this.itemSize + 1 ] = y;
10726 
10727  return this;
10728 
10729  },
10730 
10731  getZ: function ( index ) {
10732 
10733  return this.array[ index * this.itemSize + 2 ];
10734 
10735  },
10736 
10737  setZ: function ( index, z ) {
10738 
10739  this.array[ index * this.itemSize + 2 ] = z;
10740 
10741  return this;
10742 
10743  },
10744 
10745  getW: function ( index ) {
10746 
10747  return this.array[ index * this.itemSize + 3 ];
10748 
10749  },
10750 
10751  setW: function ( index, w ) {
10752 
10753  this.array[ index * this.itemSize + 3 ] = w;
10754 
10755  return this;
10756 
10757  },
10758 
10759  setXY: function ( index, x, y ) {
10760 
10761  index *= this.itemSize;
10762 
10763  this.array[ index + 0 ] = x;
10764  this.array[ index + 1 ] = y;
10765 
10766  return this;
10767 
10768  },
10769 
10770  setXYZ: function ( index, x, y, z ) {
10771 
10772  index *= this.itemSize;
10773 
10774  this.array[ index + 0 ] = x;
10775  this.array[ index + 1 ] = y;
10776  this.array[ index + 2 ] = z;
10777 
10778  return this;
10779 
10780  },
10781 
10782  setXYZW: function ( index, x, y, z, w ) {
10783 
10784  index *= this.itemSize;
10785 
10786  this.array[ index + 0 ] = x;
10787  this.array[ index + 1 ] = y;
10788  this.array[ index + 2 ] = z;
10789  this.array[ index + 3 ] = w;
10790 
10791  return this;
10792 
10793  },
10794 
10795  onUpload: function ( callback ) {
10796 
10797  this.onUploadCallback = callback;
10798 
10799  return this;
10800 
10801  },
10802 
10803  clone: function () {
10804 
10805  return new this.constructor( this.array, this.itemSize ).copy( this );
10806 
10807  }
10808 
10809  } );
10810 
10811  //
10812 
10813  function Int8BufferAttribute( array, itemSize, normalized ) {
10814 
10815  BufferAttribute.call( this, new Int8Array( array ), itemSize, normalized );
10816 
10817  }
10818 
10819  Int8BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
10820  Int8BufferAttribute.prototype.constructor = Int8BufferAttribute;
10821 
10822 
10823  function Uint8BufferAttribute( array, itemSize, normalized ) {
10824 
10825  BufferAttribute.call( this, new Uint8Array( array ), itemSize, normalized );
10826 
10827  }
10828 
10829  Uint8BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
10830  Uint8BufferAttribute.prototype.constructor = Uint8BufferAttribute;
10831 
10832 
10833  function Uint8ClampedBufferAttribute( array, itemSize, normalized ) {
10834 
10835  BufferAttribute.call( this, new Uint8ClampedArray( array ), itemSize, normalized );
10836 
10837  }
10838 
10839  Uint8ClampedBufferAttribute.prototype = Object.create( BufferAttribute.prototype );
10840  Uint8ClampedBufferAttribute.prototype.constructor = Uint8ClampedBufferAttribute;
10841 
10842 
10843  function Int16BufferAttribute( array, itemSize, normalized ) {
10844 
10845  BufferAttribute.call( this, new Int16Array( array ), itemSize, normalized );
10846 
10847  }
10848 
10849  Int16BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
10850  Int16BufferAttribute.prototype.constructor = Int16BufferAttribute;
10851 
10852 
10853  function Uint16BufferAttribute( array, itemSize, normalized ) {
10854 
10855  BufferAttribute.call( this, new Uint16Array( array ), itemSize, normalized );
10856 
10857  }
10858 
10859  Uint16BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
10860  Uint16BufferAttribute.prototype.constructor = Uint16BufferAttribute;
10861 
10862 
10863  function Int32BufferAttribute( array, itemSize, normalized ) {
10864 
10865  BufferAttribute.call( this, new Int32Array( array ), itemSize, normalized );
10866 
10867  }
10868 
10869  Int32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
10870  Int32BufferAttribute.prototype.constructor = Int32BufferAttribute;
10871 
10872 
10873  function Uint32BufferAttribute( array, itemSize, normalized ) {
10874 
10875  BufferAttribute.call( this, new Uint32Array( array ), itemSize, normalized );
10876 
10877  }
10878 
10879  Uint32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
10880  Uint32BufferAttribute.prototype.constructor = Uint32BufferAttribute;
10881 
10882 
10883  function Float32BufferAttribute( array, itemSize, normalized ) {
10884 
10885  BufferAttribute.call( this, new Float32Array( array ), itemSize, normalized );
10886 
10887  }
10888 
10889  Float32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
10890  Float32BufferAttribute.prototype.constructor = Float32BufferAttribute;
10891 
10892 
10893  function Float64BufferAttribute( array, itemSize, normalized ) {
10894 
10895  BufferAttribute.call( this, new Float64Array( array ), itemSize, normalized );
10896 
10897  }
10898 
10899  Float64BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
10900  Float64BufferAttribute.prototype.constructor = Float64BufferAttribute;
10901 
10906  function DirectGeometry() {
10907 
10908  this.vertices = [];
10909  this.normals = [];
10910  this.colors = [];
10911  this.uvs = [];
10912  this.uvs2 = [];
10913 
10914  this.groups = [];
10915 
10916  this.morphTargets = {};
10917 
10918  this.skinWeights = [];
10919  this.skinIndices = [];
10920 
10921  // this.lineDistances = [];
10922 
10923  this.boundingBox = null;
10924  this.boundingSphere = null;
10925 
10926  // update flags
10927 
10928  this.verticesNeedUpdate = false;
10929  this.normalsNeedUpdate = false;
10930  this.colorsNeedUpdate = false;
10931  this.uvsNeedUpdate = false;
10932  this.groupsNeedUpdate = false;
10933 
10934  }
10935 
10936  Object.assign( DirectGeometry.prototype, {
10937 
10938  computeGroups: function ( geometry ) {
10939 
10940  var group;
10941  var groups = [];
10942  var materialIndex = undefined;
10943 
10944  var faces = geometry.faces;
10945 
10946  for ( var i = 0; i < faces.length; i ++ ) {
10947 
10948  var face = faces[ i ];
10949 
10950  // materials
10951 
10952  if ( face.materialIndex !== materialIndex ) {
10953 
10954  materialIndex = face.materialIndex;
10955 
10956  if ( group !== undefined ) {
10957 
10958  group.count = ( i * 3 ) - group.start;
10959  groups.push( group );
10960 
10961  }
10962 
10963  group = {
10964  start: i * 3,
10965  materialIndex: materialIndex
10966  };
10967 
10968  }
10969 
10970  }
10971 
10972  if ( group !== undefined ) {
10973 
10974  group.count = ( i * 3 ) - group.start;
10975  groups.push( group );
10976 
10977  }
10978 
10979  this.groups = groups;
10980 
10981  },
10982 
10983  fromGeometry: function ( geometry ) {
10984 
10985  var faces = geometry.faces;
10986  var vertices = geometry.vertices;
10987  var faceVertexUvs = geometry.faceVertexUvs;
10988 
10989  var hasFaceVertexUv = faceVertexUvs[ 0 ] && faceVertexUvs[ 0 ].length > 0;
10990  var hasFaceVertexUv2 = faceVertexUvs[ 1 ] && faceVertexUvs[ 1 ].length > 0;
10991 
10992  // morphs
10993 
10994  var morphTargets = geometry.morphTargets;
10995  var morphTargetsLength = morphTargets.length;
10996 
10997  var morphTargetsPosition;
10998 
10999  if ( morphTargetsLength > 0 ) {
11000 
11001  morphTargetsPosition = [];
11002 
11003  for ( var i = 0; i < morphTargetsLength; i ++ ) {
11004 
11005  morphTargetsPosition[ i ] = {
11006  name: morphTargets[ i ].name,
11007  data: []
11008  };
11009 
11010  }
11011 
11012  this.morphTargets.position = morphTargetsPosition;
11013 
11014  }
11015 
11016  var morphNormals = geometry.morphNormals;
11017  var morphNormalsLength = morphNormals.length;
11018 
11019  var morphTargetsNormal;
11020 
11021  if ( morphNormalsLength > 0 ) {
11022 
11023  morphTargetsNormal = [];
11024 
11025  for ( var i = 0; i < morphNormalsLength; i ++ ) {
11026 
11027  morphTargetsNormal[ i ] = {
11028  name: morphNormals[ i ].name,
11029  data: []
11030  };
11031 
11032  }
11033 
11034  this.morphTargets.normal = morphTargetsNormal;
11035 
11036  }
11037 
11038  // skins
11039 
11040  var skinIndices = geometry.skinIndices;
11041  var skinWeights = geometry.skinWeights;
11042 
11043  var hasSkinIndices = skinIndices.length === vertices.length;
11044  var hasSkinWeights = skinWeights.length === vertices.length;
11045 
11046  //
11047 
11048  if ( vertices.length > 0 && faces.length === 0 ) {
11049 
11050  console.error( 'THREE.DirectGeometry: Faceless geometries are not supported.' );
11051 
11052  }
11053 
11054  for ( var i = 0; i < faces.length; i ++ ) {
11055 
11056  var face = faces[ i ];
11057 
11058  this.vertices.push( vertices[ face.a ], vertices[ face.b ], vertices[ face.c ] );
11059 
11060  var vertexNormals = face.vertexNormals;
11061 
11062  if ( vertexNormals.length === 3 ) {
11063 
11064  this.normals.push( vertexNormals[ 0 ], vertexNormals[ 1 ], vertexNormals[ 2 ] );
11065 
11066  } else {
11067 
11068  var normal = face.normal;
11069 
11070  this.normals.push( normal, normal, normal );
11071 
11072  }
11073 
11074  var vertexColors = face.vertexColors;
11075 
11076  if ( vertexColors.length === 3 ) {
11077 
11078  this.colors.push( vertexColors[ 0 ], vertexColors[ 1 ], vertexColors[ 2 ] );
11079 
11080  } else {
11081 
11082  var color = face.color;
11083 
11084  this.colors.push( color, color, color );
11085 
11086  }
11087 
11088  if ( hasFaceVertexUv === true ) {
11089 
11090  var vertexUvs = faceVertexUvs[ 0 ][ i ];
11091 
11092  if ( vertexUvs !== undefined ) {
11093 
11094  this.uvs.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] );
11095 
11096  } else {
11097 
11098  console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv ', i );
11099 
11100  this.uvs.push( new Vector2(), new Vector2(), new Vector2() );
11101 
11102  }
11103 
11104  }
11105 
11106  if ( hasFaceVertexUv2 === true ) {
11107 
11108  var vertexUvs = faceVertexUvs[ 1 ][ i ];
11109 
11110  if ( vertexUvs !== undefined ) {
11111 
11112  this.uvs2.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] );
11113 
11114  } else {
11115 
11116  console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv2 ', i );
11117 
11118  this.uvs2.push( new Vector2(), new Vector2(), new Vector2() );
11119 
11120  }
11121 
11122  }
11123 
11124  // morphs
11125 
11126  for ( var j = 0; j < morphTargetsLength; j ++ ) {
11127 
11128  var morphTarget = morphTargets[ j ].vertices;
11129 
11130  morphTargetsPosition[ j ].data.push( morphTarget[ face.a ], morphTarget[ face.b ], morphTarget[ face.c ] );
11131 
11132  }
11133 
11134  for ( var j = 0; j < morphNormalsLength; j ++ ) {
11135 
11136  var morphNormal = morphNormals[ j ].vertexNormals[ i ];
11137 
11138  morphTargetsNormal[ j ].data.push( morphNormal.a, morphNormal.b, morphNormal.c );
11139 
11140  }
11141 
11142  // skins
11143 
11144  if ( hasSkinIndices ) {
11145 
11146  this.skinIndices.push( skinIndices[ face.a ], skinIndices[ face.b ], skinIndices[ face.c ] );
11147 
11148  }
11149 
11150  if ( hasSkinWeights ) {
11151 
11152  this.skinWeights.push( skinWeights[ face.a ], skinWeights[ face.b ], skinWeights[ face.c ] );
11153 
11154  }
11155 
11156  }
11157 
11158  this.computeGroups( geometry );
11159 
11160  this.verticesNeedUpdate = geometry.verticesNeedUpdate;
11161  this.normalsNeedUpdate = geometry.normalsNeedUpdate;
11162  this.colorsNeedUpdate = geometry.colorsNeedUpdate;
11163  this.uvsNeedUpdate = geometry.uvsNeedUpdate;
11164  this.groupsNeedUpdate = geometry.groupsNeedUpdate;
11165 
11166  return this;
11167 
11168  }
11169 
11170  } );
11171 
11176  function arrayMax( array ) {
11177 
11178  if ( array.length === 0 ) return - Infinity;
11179 
11180  var max = array[ 0 ];
11181 
11182  for ( var i = 1, l = array.length; i < l; ++ i ) {
11183 
11184  if ( array[ i ] > max ) max = array[ i ];
11185 
11186  }
11187 
11188  return max;
11189 
11190  }
11191 
11197  var bufferGeometryId = 1; // BufferGeometry uses odd numbers as Id
11198 
11199  function BufferGeometry() {
11200 
11201  Object.defineProperty( this, 'id', { value: bufferGeometryId += 2 } );
11202 
11203  this.uuid = _Math.generateUUID();
11204 
11205  this.name = '';
11206  this.type = 'BufferGeometry';
11207 
11208  this.index = null;
11209  this.attributes = {};
11210 
11211  this.morphAttributes = {};
11212 
11213  this.groups = [];
11214 
11215  this.boundingBox = null;
11216  this.boundingSphere = null;
11217 
11218  this.drawRange = { start: 0, count: Infinity };
11219 
11220  this.userData = {};
11221 
11222  }
11223 
11224  BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
11225 
11226  constructor: BufferGeometry,
11227 
11228  isBufferGeometry: true,
11229 
11230  getIndex: function () {
11231 
11232  return this.index;
11233 
11234  },
11235 
11236  setIndex: function ( index ) {
11237 
11238  if ( Array.isArray( index ) ) {
11239 
11240  this.index = new ( arrayMax( index ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 );
11241 
11242  } else {
11243 
11244  this.index = index;
11245 
11246  }
11247 
11248  },
11249 
11250  addAttribute: function ( name, attribute ) {
11251 
11252  if ( ! ( attribute && attribute.isBufferAttribute ) && ! ( attribute && attribute.isInterleavedBufferAttribute ) ) {
11253 
11254  console.warn( 'THREE.BufferGeometry: .addAttribute() now expects ( name, attribute ).' );
11255 
11256  return this.addAttribute( name, new BufferAttribute( arguments[ 1 ], arguments[ 2 ] ) );
11257 
11258  }
11259 
11260  if ( name === 'index' ) {
11261 
11262  console.warn( 'THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute.' );
11263  this.setIndex( attribute );
11264 
11265  return this;
11266 
11267  }
11268 
11269  this.attributes[ name ] = attribute;
11270 
11271  return this;
11272 
11273  },
11274 
11275  getAttribute: function ( name ) {
11276 
11277  return this.attributes[ name ];
11278 
11279  },
11280 
11281  removeAttribute: function ( name ) {
11282 
11283  delete this.attributes[ name ];
11284 
11285  return this;
11286 
11287  },
11288 
11289  addGroup: function ( start, count, materialIndex ) {
11290 
11291  this.groups.push( {
11292 
11293  start: start,
11294  count: count,
11295  materialIndex: materialIndex !== undefined ? materialIndex : 0
11296 
11297  } );
11298 
11299  },
11300 
11301  clearGroups: function () {
11302 
11303  this.groups = [];
11304 
11305  },
11306 
11307  setDrawRange: function ( start, count ) {
11308 
11309  this.drawRange.start = start;
11310  this.drawRange.count = count;
11311 
11312  },
11313 
11314  applyMatrix: function ( matrix ) {
11315 
11316  var position = this.attributes.position;
11317 
11318  if ( position !== undefined ) {
11319 
11320  matrix.applyToBufferAttribute( position );
11321  position.needsUpdate = true;
11322 
11323  }
11324 
11325  var normal = this.attributes.normal;
11326 
11327  if ( normal !== undefined ) {
11328 
11329  var normalMatrix = new Matrix3().getNormalMatrix( matrix );
11330 
11331  normalMatrix.applyToBufferAttribute( normal );
11332  normal.needsUpdate = true;
11333 
11334  }
11335 
11336  var tangent = this.attributes.tangent;
11337 
11338  if ( tangent !== undefined ) {
11339 
11340  var normalMatrix = new Matrix3().getNormalMatrix( matrix );
11341 
11342  // Tangent is vec4, but the '.w' component is a sign value (+1/-1).
11343  normalMatrix.applyToBufferAttribute( tangent );
11344  tangent.needsUpdate = true;
11345 
11346  }
11347 
11348  if ( this.boundingBox !== null ) {
11349 
11350  this.computeBoundingBox();
11351 
11352  }
11353 
11354  if ( this.boundingSphere !== null ) {
11355 
11356  this.computeBoundingSphere();
11357 
11358  }
11359 
11360  return this;
11361 
11362  },
11363 
11364  rotateX: function () {
11365 
11366  // rotate geometry around world x-axis
11367 
11368  var m1 = new Matrix4();
11369 
11370  return function rotateX( angle ) {
11371 
11372  m1.makeRotationX( angle );
11373 
11374  this.applyMatrix( m1 );
11375 
11376  return this;
11377 
11378  };
11379 
11380  }(),
11381 
11382  rotateY: function () {
11383 
11384  // rotate geometry around world y-axis
11385 
11386  var m1 = new Matrix4();
11387 
11388  return function rotateY( angle ) {
11389 
11390  m1.makeRotationY( angle );
11391 
11392  this.applyMatrix( m1 );
11393 
11394  return this;
11395 
11396  };
11397 
11398  }(),
11399 
11400  rotateZ: function () {
11401 
11402  // rotate geometry around world z-axis
11403 
11404  var m1 = new Matrix4();
11405 
11406  return function rotateZ( angle ) {
11407 
11408  m1.makeRotationZ( angle );
11409 
11410  this.applyMatrix( m1 );
11411 
11412  return this;
11413 
11414  };
11415 
11416  }(),
11417 
11418  translate: function () {
11419 
11420  // translate geometry
11421 
11422  var m1 = new Matrix4();
11423 
11424  return function translate( x, y, z ) {
11425 
11426  m1.makeTranslation( x, y, z );
11427 
11428  this.applyMatrix( m1 );
11429 
11430  return this;
11431 
11432  };
11433 
11434  }(),
11435 
11436  scale: function () {
11437 
11438  // scale geometry
11439 
11440  var m1 = new Matrix4();
11441 
11442  return function scale( x, y, z ) {
11443 
11444  m1.makeScale( x, y, z );
11445 
11446  this.applyMatrix( m1 );
11447 
11448  return this;
11449 
11450  };
11451 
11452  }(),
11453 
11454  lookAt: function () {
11455 
11456  var obj = new Object3D();
11457 
11458  return function lookAt( vector ) {
11459 
11460  obj.lookAt( vector );
11461 
11462  obj.updateMatrix();
11463 
11464  this.applyMatrix( obj.matrix );
11465 
11466  };
11467 
11468  }(),
11469 
11470  center: function () {
11471 
11472  var offset = new Vector3();
11473 
11474  return function center() {
11475 
11476  this.computeBoundingBox();
11477 
11478  this.boundingBox.getCenter( offset ).negate();
11479 
11480  this.translate( offset.x, offset.y, offset.z );
11481 
11482  return this;
11483 
11484  };
11485 
11486  }(),
11487 
11488  setFromObject: function ( object ) {
11489 
11490  // console.log( 'THREE.BufferGeometry.setFromObject(). Converting', object, this );
11491 
11492  var geometry = object.geometry;
11493 
11494  if ( object.isPoints || object.isLine ) {
11495 
11496  var positions = new Float32BufferAttribute( geometry.vertices.length * 3, 3 );
11497  var colors = new Float32BufferAttribute( geometry.colors.length * 3, 3 );
11498 
11499  this.addAttribute( 'position', positions.copyVector3sArray( geometry.vertices ) );
11500  this.addAttribute( 'color', colors.copyColorsArray( geometry.colors ) );
11501 
11502  if ( geometry.lineDistances && geometry.lineDistances.length === geometry.vertices.length ) {
11503 
11504  var lineDistances = new Float32BufferAttribute( geometry.lineDistances.length, 1 );
11505 
11506  this.addAttribute( 'lineDistance', lineDistances.copyArray( geometry.lineDistances ) );
11507 
11508  }
11509 
11510  if ( geometry.boundingSphere !== null ) {
11511 
11512  this.boundingSphere = geometry.boundingSphere.clone();
11513 
11514  }
11515 
11516  if ( geometry.boundingBox !== null ) {
11517 
11518  this.boundingBox = geometry.boundingBox.clone();
11519 
11520  }
11521 
11522  } else if ( object.isMesh ) {
11523 
11524  if ( geometry && geometry.isGeometry ) {
11525 
11526  this.fromGeometry( geometry );
11527 
11528  }
11529 
11530  }
11531 
11532  return this;
11533 
11534  },
11535 
11536  setFromPoints: function ( points ) {
11537 
11538  var position = [];
11539 
11540  for ( var i = 0, l = points.length; i < l; i ++ ) {
11541 
11542  var point = points[ i ];
11543  position.push( point.x, point.y, point.z || 0 );
11544 
11545  }
11546 
11547  this.addAttribute( 'position', new Float32BufferAttribute( position, 3 ) );
11548 
11549  return this;
11550 
11551  },
11552 
11553  updateFromObject: function ( object ) {
11554 
11555  var geometry = object.geometry;
11556 
11557  if ( object.isMesh ) {
11558 
11559  var direct = geometry.__directGeometry;
11560 
11561  if ( geometry.elementsNeedUpdate === true ) {
11562 
11563  direct = undefined;
11564  geometry.elementsNeedUpdate = false;
11565 
11566  }
11567 
11568  if ( direct === undefined ) {
11569 
11570  return this.fromGeometry( geometry );
11571 
11572  }
11573 
11574  direct.verticesNeedUpdate = geometry.verticesNeedUpdate;
11575  direct.normalsNeedUpdate = geometry.normalsNeedUpdate;
11576  direct.colorsNeedUpdate = geometry.colorsNeedUpdate;
11577  direct.uvsNeedUpdate = geometry.uvsNeedUpdate;
11578  direct.groupsNeedUpdate = geometry.groupsNeedUpdate;
11579 
11580  geometry.verticesNeedUpdate = false;
11581  geometry.normalsNeedUpdate = false;
11582  geometry.colorsNeedUpdate = false;
11583  geometry.uvsNeedUpdate = false;
11584  geometry.groupsNeedUpdate = false;
11585 
11586  geometry = direct;
11587 
11588  }
11589 
11590  var attribute;
11591 
11592  if ( geometry.verticesNeedUpdate === true ) {
11593 
11594  attribute = this.attributes.position;
11595 
11596  if ( attribute !== undefined ) {
11597 
11598  attribute.copyVector3sArray( geometry.vertices );
11599  attribute.needsUpdate = true;
11600 
11601  }
11602 
11603  geometry.verticesNeedUpdate = false;
11604 
11605  }
11606 
11607  if ( geometry.normalsNeedUpdate === true ) {
11608 
11609  attribute = this.attributes.normal;
11610 
11611  if ( attribute !== undefined ) {
11612 
11613  attribute.copyVector3sArray( geometry.normals );
11614  attribute.needsUpdate = true;
11615 
11616  }
11617 
11618  geometry.normalsNeedUpdate = false;
11619 
11620  }
11621 
11622  if ( geometry.colorsNeedUpdate === true ) {
11623 
11624  attribute = this.attributes.color;
11625 
11626  if ( attribute !== undefined ) {
11627 
11628  attribute.copyColorsArray( geometry.colors );
11629  attribute.needsUpdate = true;
11630 
11631  }
11632 
11633  geometry.colorsNeedUpdate = false;
11634 
11635  }
11636 
11637  if ( geometry.uvsNeedUpdate ) {
11638 
11639  attribute = this.attributes.uv;
11640 
11641  if ( attribute !== undefined ) {
11642 
11643  attribute.copyVector2sArray( geometry.uvs );
11644  attribute.needsUpdate = true;
11645 
11646  }
11647 
11648  geometry.uvsNeedUpdate = false;
11649 
11650  }
11651 
11652  if ( geometry.lineDistancesNeedUpdate ) {
11653 
11654  attribute = this.attributes.lineDistance;
11655 
11656  if ( attribute !== undefined ) {
11657 
11658  attribute.copyArray( geometry.lineDistances );
11659  attribute.needsUpdate = true;
11660 
11661  }
11662 
11663  geometry.lineDistancesNeedUpdate = false;
11664 
11665  }
11666 
11667  if ( geometry.groupsNeedUpdate ) {
11668 
11669  geometry.computeGroups( object.geometry );
11670  this.groups = geometry.groups;
11671 
11672  geometry.groupsNeedUpdate = false;
11673 
11674  }
11675 
11676  return this;
11677 
11678  },
11679 
11680  fromGeometry: function ( geometry ) {
11681 
11682  geometry.__directGeometry = new DirectGeometry().fromGeometry( geometry );
11683 
11684  return this.fromDirectGeometry( geometry.__directGeometry );
11685 
11686  },
11687 
11688  fromDirectGeometry: function ( geometry ) {
11689 
11690  var positions = new Float32Array( geometry.vertices.length * 3 );
11691  this.addAttribute( 'position', new BufferAttribute( positions, 3 ).copyVector3sArray( geometry.vertices ) );
11692 
11693  if ( geometry.normals.length > 0 ) {
11694 
11695  var normals = new Float32Array( geometry.normals.length * 3 );
11696  this.addAttribute( 'normal', new BufferAttribute( normals, 3 ).copyVector3sArray( geometry.normals ) );
11697 
11698  }
11699 
11700  if ( geometry.colors.length > 0 ) {
11701 
11702  var colors = new Float32Array( geometry.colors.length * 3 );
11703  this.addAttribute( 'color', new BufferAttribute( colors, 3 ).copyColorsArray( geometry.colors ) );
11704 
11705  }
11706 
11707  if ( geometry.uvs.length > 0 ) {
11708 
11709  var uvs = new Float32Array( geometry.uvs.length * 2 );
11710  this.addAttribute( 'uv', new BufferAttribute( uvs, 2 ).copyVector2sArray( geometry.uvs ) );
11711 
11712  }
11713 
11714  if ( geometry.uvs2.length > 0 ) {
11715 
11716  var uvs2 = new Float32Array( geometry.uvs2.length * 2 );
11717  this.addAttribute( 'uv2', new BufferAttribute( uvs2, 2 ).copyVector2sArray( geometry.uvs2 ) );
11718 
11719  }
11720 
11721  // groups
11722 
11723  this.groups = geometry.groups;
11724 
11725  // morphs
11726 
11727  for ( var name in geometry.morphTargets ) {
11728 
11729  var array = [];
11730  var morphTargets = geometry.morphTargets[ name ];
11731 
11732  for ( var i = 0, l = morphTargets.length; i < l; i ++ ) {
11733 
11734  var morphTarget = morphTargets[ i ];
11735 
11736  var attribute = new Float32BufferAttribute( morphTarget.data.length * 3, 3 );
11737  attribute.name = morphTarget.name;
11738 
11739  array.push( attribute.copyVector3sArray( morphTarget.data ) );
11740 
11741  }
11742 
11743  this.morphAttributes[ name ] = array;
11744 
11745  }
11746 
11747  // skinning
11748 
11749  if ( geometry.skinIndices.length > 0 ) {
11750 
11751  var skinIndices = new Float32BufferAttribute( geometry.skinIndices.length * 4, 4 );
11752  this.addAttribute( 'skinIndex', skinIndices.copyVector4sArray( geometry.skinIndices ) );
11753 
11754  }
11755 
11756  if ( geometry.skinWeights.length > 0 ) {
11757 
11758  var skinWeights = new Float32BufferAttribute( geometry.skinWeights.length * 4, 4 );
11759  this.addAttribute( 'skinWeight', skinWeights.copyVector4sArray( geometry.skinWeights ) );
11760 
11761  }
11762 
11763  //
11764 
11765  if ( geometry.boundingSphere !== null ) {
11766 
11767  this.boundingSphere = geometry.boundingSphere.clone();
11768 
11769  }
11770 
11771  if ( geometry.boundingBox !== null ) {
11772 
11773  this.boundingBox = geometry.boundingBox.clone();
11774 
11775  }
11776 
11777  return this;
11778 
11779  },
11780 
11781  computeBoundingBox: function () {
11782 
11783  if ( this.boundingBox === null ) {
11784 
11785  this.boundingBox = new Box3();
11786 
11787  }
11788 
11789  var position = this.attributes.position;
11790 
11791  if ( position !== undefined ) {
11792 
11793  this.boundingBox.setFromBufferAttribute( position );
11794 
11795  } else {
11796 
11797  this.boundingBox.makeEmpty();
11798 
11799  }
11800 
11801  if ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) {
11802 
11803  console.error( 'THREE.BufferGeometry.computeBoundingBox: Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this );
11804 
11805  }
11806 
11807  },
11808 
11809  computeBoundingSphere: function () {
11810 
11811  var box = new Box3();
11812  var vector = new Vector3();
11813 
11814  return function computeBoundingSphere() {
11815 
11816  if ( this.boundingSphere === null ) {
11817 
11818  this.boundingSphere = new Sphere();
11819 
11820  }
11821 
11822  var position = this.attributes.position;
11823 
11824  if ( position ) {
11825 
11826  var center = this.boundingSphere.center;
11827 
11828  box.setFromBufferAttribute( position );
11829  box.getCenter( center );
11830 
11831  // hoping to find a boundingSphere with a radius smaller than the
11832  // boundingSphere of the boundingBox: sqrt(3) smaller in the best case
11833 
11834  var maxRadiusSq = 0;
11835 
11836  for ( var i = 0, il = position.count; i < il; i ++ ) {
11837 
11838  vector.x = position.getX( i );
11839  vector.y = position.getY( i );
11840  vector.z = position.getZ( i );
11841  maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( vector ) );
11842 
11843  }
11844 
11845  this.boundingSphere.radius = Math.sqrt( maxRadiusSq );
11846 
11847  if ( isNaN( this.boundingSphere.radius ) ) {
11848 
11849  console.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this );
11850 
11851  }
11852 
11853  }
11854 
11855  };
11856 
11857  }(),
11858 
11859  computeFaceNormals: function () {
11860 
11861  // backwards compatibility
11862 
11863  },
11864 
11865  computeVertexNormals: function () {
11866 
11867  var index = this.index;
11868  var attributes = this.attributes;
11869 
11870  if ( attributes.position ) {
11871 
11872  var positions = attributes.position.array;
11873 
11874  if ( attributes.normal === undefined ) {
11875 
11876  this.addAttribute( 'normal', new BufferAttribute( new Float32Array( positions.length ), 3 ) );
11877 
11878  } else {
11879 
11880  // reset existing normals to zero
11881 
11882  var array = attributes.normal.array;
11883 
11884  for ( var i = 0, il = array.length; i < il; i ++ ) {
11885 
11886  array[ i ] = 0;
11887 
11888  }
11889 
11890  }
11891 
11892  var normals = attributes.normal.array;
11893 
11894  var vA, vB, vC;
11895  var pA = new Vector3(), pB = new Vector3(), pC = new Vector3();
11896  var cb = new Vector3(), ab = new Vector3();
11897 
11898  // indexed elements
11899 
11900  if ( index ) {
11901 
11902  var indices = index.array;
11903 
11904  for ( var i = 0, il = index.count; i < il; i += 3 ) {
11905 
11906  vA = indices[ i + 0 ] * 3;
11907  vB = indices[ i + 1 ] * 3;
11908  vC = indices[ i + 2 ] * 3;
11909 
11910  pA.fromArray( positions, vA );
11911  pB.fromArray( positions, vB );
11912  pC.fromArray( positions, vC );
11913 
11914  cb.subVectors( pC, pB );
11915  ab.subVectors( pA, pB );
11916  cb.cross( ab );
11917 
11918  normals[ vA ] += cb.x;
11919  normals[ vA + 1 ] += cb.y;
11920  normals[ vA + 2 ] += cb.z;
11921 
11922  normals[ vB ] += cb.x;
11923  normals[ vB + 1 ] += cb.y;
11924  normals[ vB + 2 ] += cb.z;
11925 
11926  normals[ vC ] += cb.x;
11927  normals[ vC + 1 ] += cb.y;
11928  normals[ vC + 2 ] += cb.z;
11929 
11930  }
11931 
11932  } else {
11933 
11934  // non-indexed elements (unconnected triangle soup)
11935 
11936  for ( var i = 0, il = positions.length; i < il; i += 9 ) {
11937 
11938  pA.fromArray( positions, i );
11939  pB.fromArray( positions, i + 3 );
11940  pC.fromArray( positions, i + 6 );
11941 
11942  cb.subVectors( pC, pB );
11943  ab.subVectors( pA, pB );
11944  cb.cross( ab );
11945 
11946  normals[ i ] = cb.x;
11947  normals[ i + 1 ] = cb.y;
11948  normals[ i + 2 ] = cb.z;
11949 
11950  normals[ i + 3 ] = cb.x;
11951  normals[ i + 4 ] = cb.y;
11952  normals[ i + 5 ] = cb.z;
11953 
11954  normals[ i + 6 ] = cb.x;
11955  normals[ i + 7 ] = cb.y;
11956  normals[ i + 8 ] = cb.z;
11957 
11958  }
11959 
11960  }
11961 
11962  this.normalizeNormals();
11963 
11964  attributes.normal.needsUpdate = true;
11965 
11966  }
11967 
11968  },
11969 
11970  merge: function ( geometry, offset ) {
11971 
11972  if ( ! ( geometry && geometry.isBufferGeometry ) ) {
11973 
11974  console.error( 'THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.', geometry );
11975  return;
11976 
11977  }
11978 
11979  if ( offset === undefined ) {
11980 
11981  offset = 0;
11982 
11983  console.warn(
11984  'THREE.BufferGeometry.merge(): Overwriting original geometry, starting at offset=0. '
11985  + 'Use BufferGeometryUtils.mergeBufferGeometries() for lossless merge.'
11986  );
11987 
11988  }
11989 
11990  var attributes = this.attributes;
11991 
11992  for ( var key in attributes ) {
11993 
11994  if ( geometry.attributes[ key ] === undefined ) continue;
11995 
11996  var attribute1 = attributes[ key ];
11997  var attributeArray1 = attribute1.array;
11998 
11999  var attribute2 = geometry.attributes[ key ];
12000  var attributeArray2 = attribute2.array;
12001 
12002  var attributeSize = attribute2.itemSize;
12003 
12004  for ( var i = 0, j = attributeSize * offset; i < attributeArray2.length; i ++, j ++ ) {
12005 
12006  attributeArray1[ j ] = attributeArray2[ i ];
12007 
12008  }
12009 
12010  }
12011 
12012  return this;
12013 
12014  },
12015 
12016  normalizeNormals: function () {
12017 
12018  var vector = new Vector3();
12019 
12020  return function normalizeNormals() {
12021 
12022  var normals = this.attributes.normal;
12023 
12024  for ( var i = 0, il = normals.count; i < il; i ++ ) {
12025 
12026  vector.x = normals.getX( i );
12027  vector.y = normals.getY( i );
12028  vector.z = normals.getZ( i );
12029 
12030  vector.normalize();
12031 
12032  normals.setXYZ( i, vector.x, vector.y, vector.z );
12033 
12034  }
12035 
12036  };
12037 
12038  }(),
12039 
12040  toNonIndexed: function () {
12041 
12042  function convertBufferAttribute( attribute, indices ) {
12043 
12044  var array = attribute.array;
12045  var itemSize = attribute.itemSize;
12046 
12047  var array2 = new array.constructor( indices.length * itemSize );
12048 
12049  var index = 0, index2 = 0;
12050 
12051  for ( var i = 0, l = indices.length; i < l; i ++ ) {
12052 
12053  index = indices[ i ] * itemSize;
12054 
12055  for ( var j = 0; j < itemSize; j ++ ) {
12056 
12057  array2[ index2 ++ ] = array[ index ++ ];
12058 
12059  }
12060 
12061  }
12062 
12063  return new BufferAttribute( array2, itemSize );
12064 
12065  }
12066 
12067  //
12068 
12069  if ( this.index === null ) {
12070 
12071  console.warn( 'THREE.BufferGeometry.toNonIndexed(): Geometry is already non-indexed.' );
12072  return this;
12073 
12074  }
12075 
12076  var geometry2 = new BufferGeometry();
12077 
12078  var indices = this.index.array;
12079  var attributes = this.attributes;
12080 
12081  // attributes
12082 
12083  for ( var name in attributes ) {
12084 
12085  var attribute = attributes[ name ];
12086 
12087  var newAttribute = convertBufferAttribute( attribute, indices );
12088 
12089  geometry2.addAttribute( name, newAttribute );
12090 
12091  }
12092 
12093  // morph attributes
12094 
12095  var morphAttributes = this.morphAttributes;
12096 
12097  for ( name in morphAttributes ) {
12098 
12099  var morphArray = [];
12100  var morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes
12101 
12102  for ( var i = 0, il = morphAttribute.length; i < il; i ++ ) {
12103 
12104  var attribute = morphAttribute[ i ];
12105 
12106  var newAttribute = convertBufferAttribute( attribute, indices );
12107 
12108  morphArray.push( newAttribute );
12109 
12110  }
12111 
12112  geometry2.morphAttributes[ name ] = morphArray;
12113 
12114  }
12115 
12116  // groups
12117 
12118  var groups = this.groups;
12119 
12120  for ( var i = 0, l = groups.length; i < l; i ++ ) {
12121 
12122  var group = groups[ i ];
12123  geometry2.addGroup( group.start, group.count, group.materialIndex );
12124 
12125  }
12126 
12127  return geometry2;
12128 
12129  },
12130 
12131  toJSON: function () {
12132 
12133  var data = {
12134  metadata: {
12135  version: 4.5,
12136  type: 'BufferGeometry',
12137  generator: 'BufferGeometry.toJSON'
12138  }
12139  };
12140 
12141  // standard BufferGeometry serialization
12142 
12143  data.uuid = this.uuid;
12144  data.type = this.type;
12145  if ( this.name !== '' ) data.name = this.name;
12146  if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData;
12147 
12148  if ( this.parameters !== undefined ) {
12149 
12150  var parameters = this.parameters;
12151 
12152  for ( var key in parameters ) {
12153 
12154  if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ];
12155 
12156  }
12157 
12158  return data;
12159 
12160  }
12161 
12162  data.data = { attributes: {} };
12163 
12164  var index = this.index;
12165 
12166  if ( index !== null ) {
12167 
12168  data.data.index = {
12169  type: index.array.constructor.name,
12170  array: Array.prototype.slice.call( index.array )
12171  };
12172 
12173  }
12174 
12175  var attributes = this.attributes;
12176 
12177  for ( var key in attributes ) {
12178 
12179  var attribute = attributes[ key ];
12180 
12181  var attributeData = {
12182  itemSize: attribute.itemSize,
12183  type: attribute.array.constructor.name,
12184  array: Array.prototype.slice.call( attribute.array ),
12185  normalized: attribute.normalized
12186  };
12187 
12188  if ( attribute.name !== '' ) attributeData.name = attribute.name;
12189 
12190  data.data.attributes[ key ] = attributeData;
12191 
12192  }
12193 
12194  var morphAttributes = {};
12195  var hasMorphAttributes = false;
12196 
12197  for ( var key in this.morphAttributes ) {
12198 
12199  var attributeArray = this.morphAttributes[ key ];
12200 
12201  var array = [];
12202 
12203  for ( var i = 0, il = attributeArray.length; i < il; i ++ ) {
12204 
12205  var attribute = attributeArray[ i ];
12206 
12207  var attributeData = {
12208  itemSize: attribute.itemSize,
12209  type: attribute.array.constructor.name,
12210  array: Array.prototype.slice.call( attribute.array ),
12211  normalized: attribute.normalized
12212  };
12213 
12214  if ( attribute.name !== '' ) attributeData.name = attribute.name;
12215 
12216  array.push( attributeData );
12217 
12218  }
12219 
12220  if ( array.length > 0 ) {
12221 
12222  morphAttributes[ key ] = array;
12223 
12224  hasMorphAttributes = true;
12225 
12226  }
12227 
12228  }
12229 
12230  if ( hasMorphAttributes ) data.data.morphAttributes = morphAttributes;
12231 
12232  var groups = this.groups;
12233 
12234  if ( groups.length > 0 ) {
12235 
12236  data.data.groups = JSON.parse( JSON.stringify( groups ) );
12237 
12238  }
12239 
12240  var boundingSphere = this.boundingSphere;
12241 
12242  if ( boundingSphere !== null ) {
12243 
12244  data.data.boundingSphere = {
12245  center: boundingSphere.center.toArray(),
12246  radius: boundingSphere.radius
12247  };
12248 
12249  }
12250 
12251  return data;
12252 
12253  },
12254 
12255  clone: function () {
12256 
12257  /*
12258  // Handle primitives
12259 
12260  var parameters = this.parameters;
12261 
12262  if ( parameters !== undefined ) {
12263 
12264  var values = [];
12265 
12266  for ( var key in parameters ) {
12267 
12268  values.push( parameters[ key ] );
12269 
12270  }
12271 
12272  var geometry = Object.create( this.constructor.prototype );
12273  this.constructor.apply( geometry, values );
12274  return geometry;
12275 
12276  }
12277 
12278  return new this.constructor().copy( this );
12279  */
12280 
12281  return new BufferGeometry().copy( this );
12282 
12283  },
12284 
12285  copy: function ( source ) {
12286 
12287  var name, i, l;
12288 
12289  // reset
12290 
12291  this.index = null;
12292  this.attributes = {};
12293  this.morphAttributes = {};
12294  this.groups = [];
12295  this.boundingBox = null;
12296  this.boundingSphere = null;
12297 
12298  // name
12299 
12300  this.name = source.name;
12301 
12302  // index
12303 
12304  var index = source.index;
12305 
12306  if ( index !== null ) {
12307 
12308  this.setIndex( index.clone() );
12309 
12310  }
12311 
12312  // attributes
12313 
12314  var attributes = source.attributes;
12315 
12316  for ( name in attributes ) {
12317 
12318  var attribute = attributes[ name ];
12319  this.addAttribute( name, attribute.clone() );
12320 
12321  }
12322 
12323  // morph attributes
12324 
12325  var morphAttributes = source.morphAttributes;
12326 
12327  for ( name in morphAttributes ) {
12328 
12329  var array = [];
12330  var morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes
12331 
12332  for ( i = 0, l = morphAttribute.length; i < l; i ++ ) {
12333 
12334  array.push( morphAttribute[ i ].clone() );
12335 
12336  }
12337 
12338  this.morphAttributes[ name ] = array;
12339 
12340  }
12341 
12342  // groups
12343 
12344  var groups = source.groups;
12345 
12346  for ( i = 0, l = groups.length; i < l; i ++ ) {
12347 
12348  var group = groups[ i ];
12349  this.addGroup( group.start, group.count, group.materialIndex );
12350 
12351  }
12352 
12353  // bounding box
12354 
12355  var boundingBox = source.boundingBox;
12356 
12357  if ( boundingBox !== null ) {
12358 
12359  this.boundingBox = boundingBox.clone();
12360 
12361  }
12362 
12363  // bounding sphere
12364 
12365  var boundingSphere = source.boundingSphere;
12366 
12367  if ( boundingSphere !== null ) {
12368 
12369  this.boundingSphere = boundingSphere.clone();
12370 
12371  }
12372 
12373  // draw range
12374 
12375  this.drawRange.start = source.drawRange.start;
12376  this.drawRange.count = source.drawRange.count;
12377 
12378  // user data
12379 
12380  this.userData = source.userData;
12381 
12382  return this;
12383 
12384  },
12385 
12386  dispose: function () {
12387 
12388  this.dispatchEvent( { type: 'dispose' } );
12389 
12390  }
12391 
12392  } );
12393 
12399  // BoxGeometry
12400 
12401  function BoxGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) {
12402 
12403  Geometry.call( this );
12404 
12405  this.type = 'BoxGeometry';
12406 
12407  this.parameters = {
12408  width: width,
12409  height: height,
12410  depth: depth,
12411  widthSegments: widthSegments,
12412  heightSegments: heightSegments,
12413  depthSegments: depthSegments
12414  };
12415 
12416  this.fromBufferGeometry( new BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) );
12417  this.mergeVertices();
12418 
12419  }
12420 
12421  BoxGeometry.prototype = Object.create( Geometry.prototype );
12422  BoxGeometry.prototype.constructor = BoxGeometry;
12423 
12424  // BoxBufferGeometry
12425 
12426  function BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) {
12427 
12428  BufferGeometry.call( this );
12429 
12430  this.type = 'BoxBufferGeometry';
12431 
12432  this.parameters = {
12433  width: width,
12434  height: height,
12435  depth: depth,
12436  widthSegments: widthSegments,
12437  heightSegments: heightSegments,
12438  depthSegments: depthSegments
12439  };
12440 
12441  var scope = this;
12442 
12443  width = width || 1;
12444  height = height || 1;
12445  depth = depth || 1;
12446 
12447  // segments
12448 
12449  widthSegments = Math.floor( widthSegments ) || 1;
12450  heightSegments = Math.floor( heightSegments ) || 1;
12451  depthSegments = Math.floor( depthSegments ) || 1;
12452 
12453  // buffers
12454 
12455  var indices = [];
12456  var vertices = [];
12457  var normals = [];
12458  var uvs = [];
12459 
12460  // helper variables
12461 
12462  var numberOfVertices = 0;
12463  var groupStart = 0;
12464 
12465  // build each side of the box geometry
12466 
12467  buildPlane( 'z', 'y', 'x', - 1, - 1, depth, height, width, depthSegments, heightSegments, 0 ); // px
12468  buildPlane( 'z', 'y', 'x', 1, - 1, depth, height, - width, depthSegments, heightSegments, 1 ); // nx
12469  buildPlane( 'x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2 ); // py
12470  buildPlane( 'x', 'z', 'y', 1, - 1, width, depth, - height, widthSegments, depthSegments, 3 ); // ny
12471  buildPlane( 'x', 'y', 'z', 1, - 1, width, height, depth, widthSegments, heightSegments, 4 ); // pz
12472  buildPlane( 'x', 'y', 'z', - 1, - 1, width, height, - depth, widthSegments, heightSegments, 5 ); // nz
12473 
12474  // build geometry
12475 
12476  this.setIndex( indices );
12477  this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
12478  this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
12479  this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
12480 
12481  function buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) {
12482 
12483  var segmentWidth = width / gridX;
12484  var segmentHeight = height / gridY;
12485 
12486  var widthHalf = width / 2;
12487  var heightHalf = height / 2;
12488  var depthHalf = depth / 2;
12489 
12490  var gridX1 = gridX + 1;
12491  var gridY1 = gridY + 1;
12492 
12493  var vertexCounter = 0;
12494  var groupCount = 0;
12495 
12496  var ix, iy;
12497 
12498  var vector = new Vector3();
12499 
12500  // generate vertices, normals and uvs
12501 
12502  for ( iy = 0; iy < gridY1; iy ++ ) {
12503 
12504  var y = iy * segmentHeight - heightHalf;
12505 
12506  for ( ix = 0; ix < gridX1; ix ++ ) {
12507 
12508  var x = ix * segmentWidth - widthHalf;
12509 
12510  // set values to correct vector component
12511 
12512  vector[ u ] = x * udir;
12513  vector[ v ] = y * vdir;
12514  vector[ w ] = depthHalf;
12515 
12516  // now apply vector to vertex buffer
12517 
12518  vertices.push( vector.x, vector.y, vector.z );
12519 
12520  // set values to correct vector component
12521 
12522  vector[ u ] = 0;
12523  vector[ v ] = 0;
12524  vector[ w ] = depth > 0 ? 1 : - 1;
12525 
12526  // now apply vector to normal buffer
12527 
12528  normals.push( vector.x, vector.y, vector.z );
12529 
12530  // uvs
12531 
12532  uvs.push( ix / gridX );
12533  uvs.push( 1 - ( iy / gridY ) );
12534 
12535  // counters
12536 
12537  vertexCounter += 1;
12538 
12539  }
12540 
12541  }
12542 
12543  // indices
12544 
12545  // 1. you need three indices to draw a single face
12546  // 2. a single segment consists of two faces
12547  // 3. so we need to generate six (2*3) indices per segment
12548 
12549  for ( iy = 0; iy < gridY; iy ++ ) {
12550 
12551  for ( ix = 0; ix < gridX; ix ++ ) {
12552 
12553  var a = numberOfVertices + ix + gridX1 * iy;
12554  var b = numberOfVertices + ix + gridX1 * ( iy + 1 );
12555  var c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 );
12556  var d = numberOfVertices + ( ix + 1 ) + gridX1 * iy;
12557 
12558  // faces
12559 
12560  indices.push( a, b, d );
12561  indices.push( b, c, d );
12562 
12563  // increase counter
12564 
12565  groupCount += 6;
12566 
12567  }
12568 
12569  }
12570 
12571  // add a group to the geometry. this will ensure multi material support
12572 
12573  scope.addGroup( groupStart, groupCount, materialIndex );
12574 
12575  // calculate new start value for groups
12576 
12577  groupStart += groupCount;
12578 
12579  // update total number of vertices
12580 
12581  numberOfVertices += vertexCounter;
12582 
12583  }
12584 
12585  }
12586 
12587  BoxBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
12588  BoxBufferGeometry.prototype.constructor = BoxBufferGeometry;
12589 
12595  // PlaneGeometry
12596 
12597  function PlaneGeometry( width, height, widthSegments, heightSegments ) {
12598 
12599  Geometry.call( this );
12600 
12601  this.type = 'PlaneGeometry';
12602 
12603  this.parameters = {
12604  width: width,
12605  height: height,
12606  widthSegments: widthSegments,
12607  heightSegments: heightSegments
12608  };
12609 
12610  this.fromBufferGeometry( new PlaneBufferGeometry( width, height, widthSegments, heightSegments ) );
12611  this.mergeVertices();
12612 
12613  }
12614 
12615  PlaneGeometry.prototype = Object.create( Geometry.prototype );
12616  PlaneGeometry.prototype.constructor = PlaneGeometry;
12617 
12618  // PlaneBufferGeometry
12619 
12620  function PlaneBufferGeometry( width, height, widthSegments, heightSegments ) {
12621 
12622  BufferGeometry.call( this );
12623 
12624  this.type = 'PlaneBufferGeometry';
12625 
12626  this.parameters = {
12627  width: width,
12628  height: height,
12629  widthSegments: widthSegments,
12630  heightSegments: heightSegments
12631  };
12632 
12633  width = width || 1;
12634  height = height || 1;
12635 
12636  var width_half = width / 2;
12637  var height_half = height / 2;
12638 
12639  var gridX = Math.floor( widthSegments ) || 1;
12640  var gridY = Math.floor( heightSegments ) || 1;
12641 
12642  var gridX1 = gridX + 1;
12643  var gridY1 = gridY + 1;
12644 
12645  var segment_width = width / gridX;
12646  var segment_height = height / gridY;
12647 
12648  var ix, iy;
12649 
12650  // buffers
12651 
12652  var indices = [];
12653  var vertices = [];
12654  var normals = [];
12655  var uvs = [];
12656 
12657  // generate vertices, normals and uvs
12658 
12659  for ( iy = 0; iy < gridY1; iy ++ ) {
12660 
12661  var y = iy * segment_height - height_half;
12662 
12663  for ( ix = 0; ix < gridX1; ix ++ ) {
12664 
12665  var x = ix * segment_width - width_half;
12666 
12667  vertices.push( x, - y, 0 );
12668 
12669  normals.push( 0, 0, 1 );
12670 
12671  uvs.push( ix / gridX );
12672  uvs.push( 1 - ( iy / gridY ) );
12673 
12674  }
12675 
12676  }
12677 
12678  // indices
12679 
12680  for ( iy = 0; iy < gridY; iy ++ ) {
12681 
12682  for ( ix = 0; ix < gridX; ix ++ ) {
12683 
12684  var a = ix + gridX1 * iy;
12685  var b = ix + gridX1 * ( iy + 1 );
12686  var c = ( ix + 1 ) + gridX1 * ( iy + 1 );
12687  var d = ( ix + 1 ) + gridX1 * iy;
12688 
12689  // faces
12690 
12691  indices.push( a, b, d );
12692  indices.push( b, c, d );
12693 
12694  }
12695 
12696  }
12697 
12698  // build geometry
12699 
12700  this.setIndex( indices );
12701  this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
12702  this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
12703  this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
12704 
12705  }
12706 
12707  PlaneBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
12708  PlaneBufferGeometry.prototype.constructor = PlaneBufferGeometry;
12709 
12715  var materialId = 0;
12716 
12717  function Material() {
12718 
12719  Object.defineProperty( this, 'id', { value: materialId ++ } );
12720 
12721  this.uuid = _Math.generateUUID();
12722 
12723  this.name = '';
12724  this.type = 'Material';
12725 
12726  this.fog = true;
12727  this.lights = true;
12728 
12729  this.blending = NormalBlending;
12730  this.side = FrontSide;
12731  this.flatShading = false;
12732  this.vertexTangents = false;
12733  this.vertexColors = NoColors; // THREE.NoColors, THREE.VertexColors, THREE.FaceColors
12734 
12735  this.opacity = 1;
12736  this.transparent = false;
12737 
12738  this.blendSrc = SrcAlphaFactor;
12739  this.blendDst = OneMinusSrcAlphaFactor;
12740  this.blendEquation = AddEquation;
12741  this.blendSrcAlpha = null;
12742  this.blendDstAlpha = null;
12743  this.blendEquationAlpha = null;
12744 
12745  this.depthFunc = LessEqualDepth;
12746  this.depthTest = true;
12747  this.depthWrite = true;
12748 
12749  this.clippingPlanes = null;
12750  this.clipIntersection = false;
12751  this.clipShadows = false;
12752 
12753  this.shadowSide = null;
12754 
12755  this.colorWrite = true;
12756 
12757  this.precision = null; // override the renderer's default precision for this material
12758 
12759  this.polygonOffset = false;
12760  this.polygonOffsetFactor = 0;
12761  this.polygonOffsetUnits = 0;
12762 
12763  this.dithering = false;
12764 
12765  this.alphaTest = 0;
12766  this.premultipliedAlpha = false;
12767 
12768  this.visible = true;
12769 
12770  this.userData = {};
12771 
12772  this.needsUpdate = true;
12773 
12774  }
12775 
12776  Material.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
12777 
12778  constructor: Material,
12779 
12780  isMaterial: true,
12781 
12782  onBeforeCompile: function () {},
12783 
12784  setValues: function ( values ) {
12785 
12786  if ( values === undefined ) return;
12787 
12788  for ( var key in values ) {
12789 
12790  var newValue = values[ key ];
12791 
12792  if ( newValue === undefined ) {
12793 
12794  console.warn( "THREE.Material: '" + key + "' parameter is undefined." );
12795  continue;
12796 
12797  }
12798 
12799  // for backward compatability if shading is set in the constructor
12800  if ( key === 'shading' ) {
12801 
12802  console.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );
12803  this.flatShading = ( newValue === FlatShading ) ? true : false;
12804  continue;
12805 
12806  }
12807 
12808  var currentValue = this[ key ];
12809 
12810  if ( currentValue === undefined ) {
12811 
12812  console.warn( "THREE." + this.type + ": '" + key + "' is not a property of this material." );
12813  continue;
12814 
12815  }
12816 
12817  if ( currentValue && currentValue.isColor ) {
12818 
12819  currentValue.set( newValue );
12820 
12821  } else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) {
12822 
12823  currentValue.copy( newValue );
12824 
12825  } else {
12826 
12827  this[ key ] = newValue;
12828 
12829  }
12830 
12831  }
12832 
12833  },
12834 
12835  toJSON: function ( meta ) {
12836 
12837  var isRoot = ( meta === undefined || typeof meta === 'string' );
12838 
12839  if ( isRoot ) {
12840 
12841  meta = {
12842  textures: {},
12843  images: {}
12844  };
12845 
12846  }
12847 
12848  var data = {
12849  metadata: {
12850  version: 4.5,
12851  type: 'Material',
12852  generator: 'Material.toJSON'
12853  }
12854  };
12855 
12856  // standard Material serialization
12857  data.uuid = this.uuid;
12858  data.type = this.type;
12859 
12860  if ( this.name !== '' ) data.name = this.name;
12861 
12862  if ( this.color && this.color.isColor ) data.color = this.color.getHex();
12863 
12864  if ( this.roughness !== undefined ) data.roughness = this.roughness;
12865  if ( this.metalness !== undefined ) data.metalness = this.metalness;
12866 
12867  if ( this.emissive && this.emissive.isColor ) data.emissive = this.emissive.getHex();
12868  if ( this.emissiveIntensity !== 1 ) data.emissiveIntensity = this.emissiveIntensity;
12869 
12870  if ( this.specular && this.specular.isColor ) data.specular = this.specular.getHex();
12871  if ( this.shininess !== undefined ) data.shininess = this.shininess;
12872  if ( this.clearCoat !== undefined ) data.clearCoat = this.clearCoat;
12873  if ( this.clearCoatRoughness !== undefined ) data.clearCoatRoughness = this.clearCoatRoughness;
12874 
12875  if ( this.map && this.map.isTexture ) data.map = this.map.toJSON( meta ).uuid;
12876  if ( this.alphaMap && this.alphaMap.isTexture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid;
12877  if ( this.lightMap && this.lightMap.isTexture ) data.lightMap = this.lightMap.toJSON( meta ).uuid;
12878 
12879  if ( this.aoMap && this.aoMap.isTexture ) {
12880 
12881  data.aoMap = this.aoMap.toJSON( meta ).uuid;
12882  data.aoMapIntensity = this.aoMapIntensity;
12883 
12884  }
12885 
12886  if ( this.bumpMap && this.bumpMap.isTexture ) {
12887 
12888  data.bumpMap = this.bumpMap.toJSON( meta ).uuid;
12889  data.bumpScale = this.bumpScale;
12890 
12891  }
12892 
12893  if ( this.normalMap && this.normalMap.isTexture ) {
12894 
12895  data.normalMap = this.normalMap.toJSON( meta ).uuid;
12896  data.normalMapType = this.normalMapType;
12897  data.normalScale = this.normalScale.toArray();
12898 
12899  }
12900 
12901  if ( this.displacementMap && this.displacementMap.isTexture ) {
12902 
12903  data.displacementMap = this.displacementMap.toJSON( meta ).uuid;
12904  data.displacementScale = this.displacementScale;
12905  data.displacementBias = this.displacementBias;
12906 
12907  }
12908 
12909  if ( this.roughnessMap && this.roughnessMap.isTexture ) data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid;
12910  if ( this.metalnessMap && this.metalnessMap.isTexture ) data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid;
12911 
12912  if ( this.emissiveMap && this.emissiveMap.isTexture ) data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid;
12913  if ( this.specularMap && this.specularMap.isTexture ) data.specularMap = this.specularMap.toJSON( meta ).uuid;
12914 
12915  if ( this.envMap && this.envMap.isTexture ) {
12916 
12917  data.envMap = this.envMap.toJSON( meta ).uuid;
12918  data.reflectivity = this.reflectivity; // Scale behind envMap
12919 
12920  if ( this.combine !== undefined ) data.combine = this.combine;
12921  if ( this.envMapIntensity !== undefined ) data.envMapIntensity = this.envMapIntensity;
12922 
12923  }
12924 
12925  if ( this.gradientMap && this.gradientMap.isTexture ) {
12926 
12927  data.gradientMap = this.gradientMap.toJSON( meta ).uuid;
12928 
12929  }
12930 
12931  if ( this.size !== undefined ) data.size = this.size;
12932  if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation;
12933 
12934  if ( this.blending !== NormalBlending ) data.blending = this.blending;
12935  if ( this.flatShading === true ) data.flatShading = this.flatShading;
12936  if ( this.side !== FrontSide ) data.side = this.side;
12937  if ( this.vertexColors !== NoColors ) data.vertexColors = this.vertexColors;
12938 
12939  if ( this.opacity < 1 ) data.opacity = this.opacity;
12940  if ( this.transparent === true ) data.transparent = this.transparent;
12941 
12942  data.depthFunc = this.depthFunc;
12943  data.depthTest = this.depthTest;
12944  data.depthWrite = this.depthWrite;
12945 
12946  // rotation (SpriteMaterial)
12947  if ( this.rotation !== 0 ) data.rotation = this.rotation;
12948 
12949  if ( this.polygonOffset === true ) data.polygonOffset = true;
12950  if ( this.polygonOffsetFactor !== 0 ) data.polygonOffsetFactor = this.polygonOffsetFactor;
12951  if ( this.polygonOffsetUnits !== 0 ) data.polygonOffsetUnits = this.polygonOffsetUnits;
12952 
12953  if ( this.linewidth !== 1 ) data.linewidth = this.linewidth;
12954  if ( this.dashSize !== undefined ) data.dashSize = this.dashSize;
12955  if ( this.gapSize !== undefined ) data.gapSize = this.gapSize;
12956  if ( this.scale !== undefined ) data.scale = this.scale;
12957 
12958  if ( this.dithering === true ) data.dithering = true;
12959 
12960  if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest;
12961  if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = this.premultipliedAlpha;
12962 
12963  if ( this.wireframe === true ) data.wireframe = this.wireframe;
12964  if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth;
12965  if ( this.wireframeLinecap !== 'round' ) data.wireframeLinecap = this.wireframeLinecap;
12966  if ( this.wireframeLinejoin !== 'round' ) data.wireframeLinejoin = this.wireframeLinejoin;
12967 
12968  if ( this.morphTargets === true ) data.morphTargets = true;
12969  if ( this.skinning === true ) data.skinning = true;
12970 
12971  if ( this.visible === false ) data.visible = false;
12972  if ( JSON.stringify( this.userData ) !== '{}' ) data.userData = this.userData;
12973 
12974  // TODO: Copied from Object3D.toJSON
12975 
12976  function extractFromCache( cache ) {
12977 
12978  var values = [];
12979 
12980  for ( var key in cache ) {
12981 
12982  var data = cache[ key ];
12983  delete data.metadata;
12984  values.push( data );
12985 
12986  }
12987 
12988  return values;
12989 
12990  }
12991 
12992  if ( isRoot ) {
12993 
12994  var textures = extractFromCache( meta.textures );
12995  var images = extractFromCache( meta.images );
12996 
12997  if ( textures.length > 0 ) data.textures = textures;
12998  if ( images.length > 0 ) data.images = images;
12999 
13000  }
13001 
13002  return data;
13003 
13004  },
13005 
13006  clone: function () {
13007 
13008  return new this.constructor().copy( this );
13009 
13010  },
13011 
13012  copy: function ( source ) {
13013 
13014  this.name = source.name;
13015 
13016  this.fog = source.fog;
13017  this.lights = source.lights;
13018 
13019  this.blending = source.blending;
13020  this.side = source.side;
13021  this.flatShading = source.flatShading;
13022  this.vertexColors = source.vertexColors;
13023 
13024  this.opacity = source.opacity;
13025  this.transparent = source.transparent;
13026 
13027  this.blendSrc = source.blendSrc;
13028  this.blendDst = source.blendDst;
13029  this.blendEquation = source.blendEquation;
13030  this.blendSrcAlpha = source.blendSrcAlpha;
13031  this.blendDstAlpha = source.blendDstAlpha;
13032  this.blendEquationAlpha = source.blendEquationAlpha;
13033 
13034  this.depthFunc = source.depthFunc;
13035  this.depthTest = source.depthTest;
13036  this.depthWrite = source.depthWrite;
13037 
13038  this.colorWrite = source.colorWrite;
13039 
13040  this.precision = source.precision;
13041 
13042  this.polygonOffset = source.polygonOffset;
13043  this.polygonOffsetFactor = source.polygonOffsetFactor;
13044  this.polygonOffsetUnits = source.polygonOffsetUnits;
13045 
13046  this.dithering = source.dithering;
13047 
13048  this.alphaTest = source.alphaTest;
13049  this.premultipliedAlpha = source.premultipliedAlpha;
13050 
13051  this.visible = source.visible;
13052  this.userData = JSON.parse( JSON.stringify( source.userData ) );
13053 
13054  this.clipShadows = source.clipShadows;
13055  this.clipIntersection = source.clipIntersection;
13056 
13057  var srcPlanes = source.clippingPlanes,
13058  dstPlanes = null;
13059 
13060  if ( srcPlanes !== null ) {
13061 
13062  var n = srcPlanes.length;
13063  dstPlanes = new Array( n );
13064 
13065  for ( var i = 0; i !== n; ++ i )
13066  dstPlanes[ i ] = srcPlanes[ i ].clone();
13067 
13068  }
13069 
13070  this.clippingPlanes = dstPlanes;
13071 
13072  this.shadowSide = source.shadowSide;
13073 
13074  return this;
13075 
13076  },
13077 
13078  dispose: function () {
13079 
13080  this.dispatchEvent( { type: 'dispose' } );
13081 
13082  }
13083 
13084  } );
13085 
13086  var default_vertex = "void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}";
13087 
13088  var default_fragment = "void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}";
13089 
13111  function ShaderMaterial( parameters ) {
13112 
13113  Material.call( this );
13114 
13115  this.type = 'ShaderMaterial';
13116 
13117  this.defines = {};
13118  this.uniforms = {};
13119 
13120  this.vertexShader = default_vertex;
13121  this.fragmentShader = default_fragment;
13122 
13123  this.linewidth = 1;
13124 
13125  this.wireframe = false;
13126  this.wireframeLinewidth = 1;
13127 
13128  this.fog = false; // set to use scene fog
13129  this.lights = false; // set to use scene lights
13130  this.clipping = false; // set to use user-defined clipping planes
13131 
13132  this.skinning = false; // set to use skinning attribute streams
13133  this.morphTargets = false; // set to use morph targets
13134  this.morphNormals = false; // set to use morph normals
13135 
13136  this.extensions = {
13137  derivatives: false, // set to use derivatives
13138  fragDepth: false, // set to use fragment depth values
13139  drawBuffers: false, // set to use draw buffers
13140  shaderTextureLOD: false // set to use shader texture LOD
13141  };
13142 
13143  // When rendered geometry doesn't include these attributes but the material does,
13144  // use these default values in WebGL. This avoids errors when buffer data is missing.
13145  this.defaultAttributeValues = {
13146  'color': [ 1, 1, 1 ],
13147  'uv': [ 0, 0 ],
13148  'uv2': [ 0, 0 ]
13149  };
13150 
13151  this.index0AttributeName = undefined;
13152  this.uniformsNeedUpdate = false;
13153 
13154  if ( parameters !== undefined ) {
13155 
13156  if ( parameters.attributes !== undefined ) {
13157 
13158  console.error( 'THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead.' );
13159 
13160  }
13161 
13162  this.setValues( parameters );
13163 
13164  }
13165 
13166  }
13167 
13168  ShaderMaterial.prototype = Object.create( Material.prototype );
13169  ShaderMaterial.prototype.constructor = ShaderMaterial;
13170 
13171  ShaderMaterial.prototype.isShaderMaterial = true;
13172 
13173  ShaderMaterial.prototype.copy = function ( source ) {
13174 
13175  Material.prototype.copy.call( this, source );
13176 
13177  this.fragmentShader = source.fragmentShader;
13178  this.vertexShader = source.vertexShader;
13179 
13180  this.uniforms = cloneUniforms( source.uniforms );
13181 
13182  this.defines = Object.assign( {}, source.defines );
13183 
13184  this.wireframe = source.wireframe;
13185  this.wireframeLinewidth = source.wireframeLinewidth;
13186 
13187  this.lights = source.lights;
13188  this.clipping = source.clipping;
13189 
13190  this.skinning = source.skinning;
13191 
13192  this.morphTargets = source.morphTargets;
13193  this.morphNormals = source.morphNormals;
13194 
13195  this.extensions = source.extensions;
13196 
13197  return this;
13198 
13199  };
13200 
13201  ShaderMaterial.prototype.toJSON = function ( meta ) {
13202 
13203  var data = Material.prototype.toJSON.call( this, meta );
13204 
13205  data.uniforms = {};
13206 
13207  for ( var name in this.uniforms ) {
13208 
13209  var uniform = this.uniforms[ name ];
13210  var value = uniform.value;
13211 
13212  if ( value && value.isTexture ) {
13213 
13214  data.uniforms[ name ] = {
13215  type: 't',
13216  value: value.toJSON( meta ).uuid
13217  };
13218 
13219  } else if ( value && value.isColor ) {
13220 
13221  data.uniforms[ name ] = {
13222  type: 'c',
13223  value: value.getHex()
13224  };
13225 
13226  } else if ( value && value.isVector2 ) {
13227 
13228  data.uniforms[ name ] = {
13229  type: 'v2',
13230  value: value.toArray()
13231  };
13232 
13233  } else if ( value && value.isVector3 ) {
13234 
13235  data.uniforms[ name ] = {
13236  type: 'v3',
13237  value: value.toArray()
13238  };
13239 
13240  } else if ( value && value.isVector4 ) {
13241 
13242  data.uniforms[ name ] = {
13243  type: 'v4',
13244  value: value.toArray()
13245  };
13246 
13247  } else if ( value && value.isMatrix3 ) {
13248 
13249  data.uniforms[ name ] = {
13250  type: 'm3',
13251  value: value.toArray()
13252  };
13253 
13254  } else if ( value && value.isMatrix4 ) {
13255 
13256  data.uniforms[ name ] = {
13257  type: 'm4',
13258  value: value.toArray()
13259  };
13260 
13261  } else {
13262 
13263  data.uniforms[ name ] = {
13264  value: value
13265  };
13266 
13267  // note: the array variants v2v, v3v, v4v, m4v and tv are not supported so far
13268 
13269  }
13270 
13271  }
13272 
13273  if ( Object.keys( this.defines ).length > 0 ) data.defines = this.defines;
13274 
13275  data.vertexShader = this.vertexShader;
13276  data.fragmentShader = this.fragmentShader;
13277 
13278  var extensions = {};
13279 
13280  for ( var key in this.extensions ) {
13281 
13282  if ( this.extensions[ key ] === true ) extensions[ key ] = true;
13283 
13284  }
13285 
13286  if ( Object.keys( extensions ).length > 0 ) data.extensions = extensions;
13287 
13288  return data;
13289 
13290  };
13291 
13296  function Ray( origin, direction ) {
13297 
13298  this.origin = ( origin !== undefined ) ? origin : new Vector3();
13299  this.direction = ( direction !== undefined ) ? direction : new Vector3();
13300 
13301  }
13302 
13303  Object.assign( Ray.prototype, {
13304 
13305  set: function ( origin, direction ) {
13306 
13307  this.origin.copy( origin );
13308  this.direction.copy( direction );
13309 
13310  return this;
13311 
13312  },
13313 
13314  clone: function () {
13315 
13316  return new this.constructor().copy( this );
13317 
13318  },
13319 
13320  copy: function ( ray ) {
13321 
13322  this.origin.copy( ray.origin );
13323  this.direction.copy( ray.direction );
13324 
13325  return this;
13326 
13327  },
13328 
13329  at: function ( t, target ) {
13330 
13331  if ( target === undefined ) {
13332 
13333  console.warn( 'THREE.Ray: .at() target is now required' );
13334  target = new Vector3();
13335 
13336  }
13337 
13338  return target.copy( this.direction ).multiplyScalar( t ).add( this.origin );
13339 
13340  },
13341 
13342  lookAt: function ( v ) {
13343 
13344  this.direction.copy( v ).sub( this.origin ).normalize();
13345 
13346  return this;
13347 
13348  },
13349 
13350  recast: function () {
13351 
13352  var v1 = new Vector3();
13353 
13354  return function recast( t ) {
13355 
13356  this.origin.copy( this.at( t, v1 ) );
13357 
13358  return this;
13359 
13360  };
13361 
13362  }(),
13363 
13364  closestPointToPoint: function ( point, target ) {
13365 
13366  if ( target === undefined ) {
13367 
13368  console.warn( 'THREE.Ray: .closestPointToPoint() target is now required' );
13369  target = new Vector3();
13370 
13371  }
13372 
13373  target.subVectors( point, this.origin );
13374 
13375  var directionDistance = target.dot( this.direction );
13376 
13377  if ( directionDistance < 0 ) {
13378 
13379  return target.copy( this.origin );
13380 
13381  }
13382 
13383  return target.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );
13384 
13385  },
13386 
13387  distanceToPoint: function ( point ) {
13388 
13389  return Math.sqrt( this.distanceSqToPoint( point ) );
13390 
13391  },
13392 
13393  distanceSqToPoint: function () {
13394 
13395  var v1 = new Vector3();
13396 
13397  return function distanceSqToPoint( point ) {
13398 
13399  var directionDistance = v1.subVectors( point, this.origin ).dot( this.direction );
13400 
13401  // point behind the ray
13402 
13403  if ( directionDistance < 0 ) {
13404 
13405  return this.origin.distanceToSquared( point );
13406 
13407  }
13408 
13409  v1.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );
13410 
13411  return v1.distanceToSquared( point );
13412 
13413  };
13414 
13415  }(),
13416 
13417  distanceSqToSegment: function () {
13418 
13419  var segCenter = new Vector3();
13420  var segDir = new Vector3();
13421  var diff = new Vector3();
13422 
13423  return function distanceSqToSegment( v0, v1, optionalPointOnRay, optionalPointOnSegment ) {
13424 
13425  // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteDistRaySegment.h
13426  // It returns the min distance between the ray and the segment
13427  // defined by v0 and v1
13428  // It can also set two optional targets :
13429  // - The closest point on the ray
13430  // - The closest point on the segment
13431 
13432  segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 );
13433  segDir.copy( v1 ).sub( v0 ).normalize();
13434  diff.copy( this.origin ).sub( segCenter );
13435 
13436  var segExtent = v0.distanceTo( v1 ) * 0.5;
13437  var a01 = - this.direction.dot( segDir );
13438  var b0 = diff.dot( this.direction );
13439  var b1 = - diff.dot( segDir );
13440  var c = diff.lengthSq();
13441  var det = Math.abs( 1 - a01 * a01 );
13442  var s0, s1, sqrDist, extDet;
13443 
13444  if ( det > 0 ) {
13445 
13446  // The ray and segment are not parallel.
13447 
13448  s0 = a01 * b1 - b0;
13449  s1 = a01 * b0 - b1;
13450  extDet = segExtent * det;
13451 
13452  if ( s0 >= 0 ) {
13453 
13454  if ( s1 >= - extDet ) {
13455 
13456  if ( s1 <= extDet ) {
13457 
13458  // region 0
13459  // Minimum at interior points of ray and segment.
13460 
13461  var invDet = 1 / det;
13462  s0 *= invDet;
13463  s1 *= invDet;
13464  sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c;
13465 
13466  } else {
13467 
13468  // region 1
13469 
13470  s1 = segExtent;
13471  s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
13472  sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
13473 
13474  }
13475 
13476  } else {
13477 
13478  // region 5
13479 
13480  s1 = - segExtent;
13481  s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
13482  sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
13483 
13484  }
13485 
13486  } else {
13487 
13488  if ( s1 <= - extDet ) {
13489 
13490  // region 4
13491 
13492  s0 = Math.max( 0, - ( - a01 * segExtent + b0 ) );
13493  s1 = ( s0 > 0 ) ? - segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
13494  sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
13495 
13496  } else if ( s1 <= extDet ) {
13497 
13498  // region 3
13499 
13500  s0 = 0;
13501  s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent );
13502  sqrDist = s1 * ( s1 + 2 * b1 ) + c;
13503 
13504  } else {
13505 
13506  // region 2
13507 
13508  s0 = Math.max( 0, - ( a01 * segExtent + b0 ) );
13509  s1 = ( s0 > 0 ) ? segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
13510  sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
13511 
13512  }
13513 
13514  }
13515 
13516  } else {
13517 
13518  // Ray and segment are parallel.
13519 
13520  s1 = ( a01 > 0 ) ? - segExtent : segExtent;
13521  s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
13522  sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
13523 
13524  }
13525 
13526  if ( optionalPointOnRay ) {
13527 
13528  optionalPointOnRay.copy( this.direction ).multiplyScalar( s0 ).add( this.origin );
13529 
13530  }
13531 
13532  if ( optionalPointOnSegment ) {
13533 
13534  optionalPointOnSegment.copy( segDir ).multiplyScalar( s1 ).add( segCenter );
13535 
13536  }
13537 
13538  return sqrDist;
13539 
13540  };
13541 
13542  }(),
13543 
13544  intersectSphere: function () {
13545 
13546  var v1 = new Vector3();
13547 
13548  return function intersectSphere( sphere, target ) {
13549 
13550  v1.subVectors( sphere.center, this.origin );
13551  var tca = v1.dot( this.direction );
13552  var d2 = v1.dot( v1 ) - tca * tca;
13553  var radius2 = sphere.radius * sphere.radius;
13554 
13555  if ( d2 > radius2 ) return null;
13556 
13557  var thc = Math.sqrt( radius2 - d2 );
13558 
13559  // t0 = first intersect point - entrance on front of sphere
13560  var t0 = tca - thc;
13561 
13562  // t1 = second intersect point - exit point on back of sphere
13563  var t1 = tca + thc;
13564 
13565  // test to see if both t0 and t1 are behind the ray - if so, return null
13566  if ( t0 < 0 && t1 < 0 ) return null;
13567 
13568  // test to see if t0 is behind the ray:
13569  // if it is, the ray is inside the sphere, so return the second exit point scaled by t1,
13570  // in order to always return an intersect point that is in front of the ray.
13571  if ( t0 < 0 ) return this.at( t1, target );
13572 
13573  // else t0 is in front of the ray, so return the first collision point scaled by t0
13574  return this.at( t0, target );
13575 
13576  };
13577 
13578  }(),
13579 
13580  intersectsSphere: function ( sphere ) {
13581 
13582  return this.distanceSqToPoint( sphere.center ) <= ( sphere.radius * sphere.radius );
13583 
13584  },
13585 
13586  distanceToPlane: function ( plane ) {
13587 
13588  var denominator = plane.normal.dot( this.direction );
13589 
13590  if ( denominator === 0 ) {
13591 
13592  // line is coplanar, return origin
13593  if ( plane.distanceToPoint( this.origin ) === 0 ) {
13594 
13595  return 0;
13596 
13597  }
13598 
13599  // Null is preferable to undefined since undefined means.... it is undefined
13600 
13601  return null;
13602 
13603  }
13604 
13605  var t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator;
13606 
13607  // Return if the ray never intersects the plane
13608 
13609  return t >= 0 ? t : null;
13610 
13611  },
13612 
13613  intersectPlane: function ( plane, target ) {
13614 
13615  var t = this.distanceToPlane( plane );
13616 
13617  if ( t === null ) {
13618 
13619  return null;
13620 
13621  }
13622 
13623  return this.at( t, target );
13624 
13625  },
13626 
13627  intersectsPlane: function ( plane ) {
13628 
13629  // check if the ray lies on the plane first
13630 
13631  var distToPoint = plane.distanceToPoint( this.origin );
13632 
13633  if ( distToPoint === 0 ) {
13634 
13635  return true;
13636 
13637  }
13638 
13639  var denominator = plane.normal.dot( this.direction );
13640 
13641  if ( denominator * distToPoint < 0 ) {
13642 
13643  return true;
13644 
13645  }
13646 
13647  // ray origin is behind the plane (and is pointing behind it)
13648 
13649  return false;
13650 
13651  },
13652 
13653  intersectBox: function ( box, target ) {
13654 
13655  var tmin, tmax, tymin, tymax, tzmin, tzmax;
13656 
13657  var invdirx = 1 / this.direction.x,
13658  invdiry = 1 / this.direction.y,
13659  invdirz = 1 / this.direction.z;
13660 
13661  var origin = this.origin;
13662 
13663  if ( invdirx >= 0 ) {
13664 
13665  tmin = ( box.min.x - origin.x ) * invdirx;
13666  tmax = ( box.max.x - origin.x ) * invdirx;
13667 
13668  } else {
13669 
13670  tmin = ( box.max.x - origin.x ) * invdirx;
13671  tmax = ( box.min.x - origin.x ) * invdirx;
13672 
13673  }
13674 
13675  if ( invdiry >= 0 ) {
13676 
13677  tymin = ( box.min.y - origin.y ) * invdiry;
13678  tymax = ( box.max.y - origin.y ) * invdiry;
13679 
13680  } else {
13681 
13682  tymin = ( box.max.y - origin.y ) * invdiry;
13683  tymax = ( box.min.y - origin.y ) * invdiry;
13684 
13685  }
13686 
13687  if ( ( tmin > tymax ) || ( tymin > tmax ) ) return null;
13688 
13689  // These lines also handle the case where tmin or tmax is NaN
13690  // (result of 0 * Infinity). x !== x returns true if x is NaN
13691 
13692  if ( tymin > tmin || tmin !== tmin ) tmin = tymin;
13693 
13694  if ( tymax < tmax || tmax !== tmax ) tmax = tymax;
13695 
13696  if ( invdirz >= 0 ) {
13697 
13698  tzmin = ( box.min.z - origin.z ) * invdirz;
13699  tzmax = ( box.max.z - origin.z ) * invdirz;
13700 
13701  } else {
13702 
13703  tzmin = ( box.max.z - origin.z ) * invdirz;
13704  tzmax = ( box.min.z - origin.z ) * invdirz;
13705 
13706  }
13707 
13708  if ( ( tmin > tzmax ) || ( tzmin > tmax ) ) return null;
13709 
13710  if ( tzmin > tmin || tmin !== tmin ) tmin = tzmin;
13711 
13712  if ( tzmax < tmax || tmax !== tmax ) tmax = tzmax;
13713 
13714  //return point closest to the ray (positive side)
13715 
13716  if ( tmax < 0 ) return null;
13717 
13718  return this.at( tmin >= 0 ? tmin : tmax, target );
13719 
13720  },
13721 
13722  intersectsBox: ( function () {
13723 
13724  var v = new Vector3();
13725 
13726  return function intersectsBox( box ) {
13727 
13728  return this.intersectBox( box, v ) !== null;
13729 
13730  };
13731 
13732  } )(),
13733 
13734  intersectTriangle: function () {
13735 
13736  // Compute the offset origin, edges, and normal.
13737  var diff = new Vector3();
13738  var edge1 = new Vector3();
13739  var edge2 = new Vector3();
13740  var normal = new Vector3();
13741 
13742  return function intersectTriangle( a, b, c, backfaceCulling, target ) {
13743 
13744  // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h
13745 
13746  edge1.subVectors( b, a );
13747  edge2.subVectors( c, a );
13748  normal.crossVectors( edge1, edge2 );
13749 
13750  // Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction,
13751  // E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by
13752  // |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2))
13753  // |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q))
13754  // |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N)
13755  var DdN = this.direction.dot( normal );
13756  var sign;
13757 
13758  if ( DdN > 0 ) {
13759 
13760  if ( backfaceCulling ) return null;
13761  sign = 1;
13762 
13763  } else if ( DdN < 0 ) {
13764 
13765  sign = - 1;
13766  DdN = - DdN;
13767 
13768  } else {
13769 
13770  return null;
13771 
13772  }
13773 
13774  diff.subVectors( this.origin, a );
13775  var DdQxE2 = sign * this.direction.dot( edge2.crossVectors( diff, edge2 ) );
13776 
13777  // b1 < 0, no intersection
13778  if ( DdQxE2 < 0 ) {
13779 
13780  return null;
13781 
13782  }
13783 
13784  var DdE1xQ = sign * this.direction.dot( edge1.cross( diff ) );
13785 
13786  // b2 < 0, no intersection
13787  if ( DdE1xQ < 0 ) {
13788 
13789  return null;
13790 
13791  }
13792 
13793  // b1+b2 > 1, no intersection
13794  if ( DdQxE2 + DdE1xQ > DdN ) {
13795 
13796  return null;
13797 
13798  }
13799 
13800  // Line intersects triangle, check if ray does.
13801  var QdN = - sign * diff.dot( normal );
13802 
13803  // t < 0, no intersection
13804  if ( QdN < 0 ) {
13805 
13806  return null;
13807 
13808  }
13809 
13810  // Ray intersects triangle.
13811  return this.at( QdN / DdN, target );
13812 
13813  };
13814 
13815  }(),
13816 
13817  applyMatrix4: function ( matrix4 ) {
13818 
13819  this.origin.applyMatrix4( matrix4 );
13820  this.direction.transformDirection( matrix4 );
13821 
13822  return this;
13823 
13824  },
13825 
13826  equals: function ( ray ) {
13827 
13828  return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction );
13829 
13830  }
13831 
13832  } );
13833 
13839  function Triangle( a, b, c ) {
13840 
13841  this.a = ( a !== undefined ) ? a : new Vector3();
13842  this.b = ( b !== undefined ) ? b : new Vector3();
13843  this.c = ( c !== undefined ) ? c : new Vector3();
13844 
13845  }
13846 
13847  Object.assign( Triangle, {
13848 
13849  getNormal: function () {
13850 
13851  var v0 = new Vector3();
13852 
13853  return function getNormal( a, b, c, target ) {
13854 
13855  if ( target === undefined ) {
13856 
13857  console.warn( 'THREE.Triangle: .getNormal() target is now required' );
13858  target = new Vector3();
13859 
13860  }
13861 
13862  target.subVectors( c, b );
13863  v0.subVectors( a, b );
13864  target.cross( v0 );
13865 
13866  var targetLengthSq = target.lengthSq();
13867  if ( targetLengthSq > 0 ) {
13868 
13869  return target.multiplyScalar( 1 / Math.sqrt( targetLengthSq ) );
13870 
13871  }
13872 
13873  return target.set( 0, 0, 0 );
13874 
13875  };
13876 
13877  }(),
13878 
13879  // static/instance method to calculate barycentric coordinates
13880  // based on: http://www.blackpawn.com/texts/pointinpoly/default.html
13881  getBarycoord: function () {
13882 
13883  var v0 = new Vector3();
13884  var v1 = new Vector3();
13885  var v2 = new Vector3();
13886 
13887  return function getBarycoord( point, a, b, c, target ) {
13888 
13889  v0.subVectors( c, a );
13890  v1.subVectors( b, a );
13891  v2.subVectors( point, a );
13892 
13893  var dot00 = v0.dot( v0 );
13894  var dot01 = v0.dot( v1 );
13895  var dot02 = v0.dot( v2 );
13896  var dot11 = v1.dot( v1 );
13897  var dot12 = v1.dot( v2 );
13898 
13899  var denom = ( dot00 * dot11 - dot01 * dot01 );
13900 
13901  if ( target === undefined ) {
13902 
13903  console.warn( 'THREE.Triangle: .getBarycoord() target is now required' );
13904  target = new Vector3();
13905 
13906  }
13907 
13908  // collinear or singular triangle
13909  if ( denom === 0 ) {
13910 
13911  // arbitrary location outside of triangle?
13912  // not sure if this is the best idea, maybe should be returning undefined
13913  return target.set( - 2, - 1, - 1 );
13914 
13915  }
13916 
13917  var invDenom = 1 / denom;
13918  var u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;
13919  var v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;
13920 
13921  // barycentric coordinates must always sum to 1
13922  return target.set( 1 - u - v, v, u );
13923 
13924  };
13925 
13926  }(),
13927 
13928  containsPoint: function () {
13929 
13930  var v1 = new Vector3();
13931 
13932  return function containsPoint( point, a, b, c ) {
13933 
13934  Triangle.getBarycoord( point, a, b, c, v1 );
13935 
13936  return ( v1.x >= 0 ) && ( v1.y >= 0 ) && ( ( v1.x + v1.y ) <= 1 );
13937 
13938  };
13939 
13940  }(),
13941 
13942  getUV: function () {
13943 
13944  var barycoord = new Vector3();
13945 
13946  return function getUV( point, p1, p2, p3, uv1, uv2, uv3, target ) {
13947 
13948  this.getBarycoord( point, p1, p2, p3, barycoord );
13949 
13950  target.set( 0, 0 );
13951  target.addScaledVector( uv1, barycoord.x );
13952  target.addScaledVector( uv2, barycoord.y );
13953  target.addScaledVector( uv3, barycoord.z );
13954 
13955  return target;
13956 
13957  };
13958 
13959  }()
13960 
13961  } );
13962 
13963  Object.assign( Triangle.prototype, {
13964 
13965  set: function ( a, b, c ) {
13966 
13967  this.a.copy( a );
13968  this.b.copy( b );
13969  this.c.copy( c );
13970 
13971  return this;
13972 
13973  },
13974 
13975  setFromPointsAndIndices: function ( points, i0, i1, i2 ) {
13976 
13977  this.a.copy( points[ i0 ] );
13978  this.b.copy( points[ i1 ] );
13979  this.c.copy( points[ i2 ] );
13980 
13981  return this;
13982 
13983  },
13984 
13985  clone: function () {
13986 
13987  return new this.constructor().copy( this );
13988 
13989  },
13990 
13991  copy: function ( triangle ) {
13992 
13993  this.a.copy( triangle.a );
13994  this.b.copy( triangle.b );
13995  this.c.copy( triangle.c );
13996 
13997  return this;
13998 
13999  },
14000 
14001  getArea: function () {
14002 
14003  var v0 = new Vector3();
14004  var v1 = new Vector3();
14005 
14006  return function getArea() {
14007 
14008  v0.subVectors( this.c, this.b );
14009  v1.subVectors( this.a, this.b );
14010 
14011  return v0.cross( v1 ).length() * 0.5;
14012 
14013  };
14014 
14015  }(),
14016 
14017  getMidpoint: function ( target ) {
14018 
14019  if ( target === undefined ) {
14020 
14021  console.warn( 'THREE.Triangle: .getMidpoint() target is now required' );
14022  target = new Vector3();
14023 
14024  }
14025 
14026  return target.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 );
14027 
14028  },
14029 
14030  getNormal: function ( target ) {
14031 
14032  return Triangle.getNormal( this.a, this.b, this.c, target );
14033 
14034  },
14035 
14036  getPlane: function ( target ) {
14037 
14038  if ( target === undefined ) {
14039 
14040  console.warn( 'THREE.Triangle: .getPlane() target is now required' );
14041  target = new Vector3();
14042 
14043  }
14044 
14045  return target.setFromCoplanarPoints( this.a, this.b, this.c );
14046 
14047  },
14048 
14049  getBarycoord: function ( point, target ) {
14050 
14051  return Triangle.getBarycoord( point, this.a, this.b, this.c, target );
14052 
14053  },
14054 
14055  containsPoint: function ( point ) {
14056 
14057  return Triangle.containsPoint( point, this.a, this.b, this.c );
14058 
14059  },
14060 
14061  getUV: function ( point, uv1, uv2, uv3, result ) {
14062 
14063  return Triangle.getUV( point, this.a, this.b, this.c, uv1, uv2, uv3, result );
14064 
14065  },
14066 
14067  intersectsBox: function ( box ) {
14068 
14069  return box.intersectsTriangle( this );
14070 
14071  },
14072 
14073  closestPointToPoint: function () {
14074 
14075  var vab = new Vector3();
14076  var vac = new Vector3();
14077  var vbc = new Vector3();
14078  var vap = new Vector3();
14079  var vbp = new Vector3();
14080  var vcp = new Vector3();
14081 
14082  return function closestPointToPoint( p, target ) {
14083 
14084  if ( target === undefined ) {
14085 
14086  console.warn( 'THREE.Triangle: .closestPointToPoint() target is now required' );
14087  target = new Vector3();
14088 
14089  }
14090 
14091  var a = this.a, b = this.b, c = this.c;
14092  var v, w;
14093 
14094  // algorithm thanks to Real-Time Collision Detection by Christer Ericson,
14095  // published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc.,
14096  // under the accompanying license; see chapter 5.1.5 for detailed explanation.
14097  // basically, we're distinguishing which of the voronoi regions of the triangle
14098  // the point lies in with the minimum amount of redundant computation.
14099 
14100  vab.subVectors( b, a );
14101  vac.subVectors( c, a );
14102  vap.subVectors( p, a );
14103  var d1 = vab.dot( vap );
14104  var d2 = vac.dot( vap );
14105  if ( d1 <= 0 && d2 <= 0 ) {
14106 
14107  // vertex region of A; barycentric coords (1, 0, 0)
14108  return target.copy( a );
14109 
14110  }
14111 
14112  vbp.subVectors( p, b );
14113  var d3 = vab.dot( vbp );
14114  var d4 = vac.dot( vbp );
14115  if ( d3 >= 0 && d4 <= d3 ) {
14116 
14117  // vertex region of B; barycentric coords (0, 1, 0)
14118  return target.copy( b );
14119 
14120  }
14121 
14122  var vc = d1 * d4 - d3 * d2;
14123  if ( vc <= 0 && d1 >= 0 && d3 <= 0 ) {
14124 
14125  v = d1 / ( d1 - d3 );
14126  // edge region of AB; barycentric coords (1-v, v, 0)
14127  return target.copy( a ).addScaledVector( vab, v );
14128 
14129  }
14130 
14131  vcp.subVectors( p, c );
14132  var d5 = vab.dot( vcp );
14133  var d6 = vac.dot( vcp );
14134  if ( d6 >= 0 && d5 <= d6 ) {
14135 
14136  // vertex region of C; barycentric coords (0, 0, 1)
14137  return target.copy( c );
14138 
14139  }
14140 
14141  var vb = d5 * d2 - d1 * d6;
14142  if ( vb <= 0 && d2 >= 0 && d6 <= 0 ) {
14143 
14144  w = d2 / ( d2 - d6 );
14145  // edge region of AC; barycentric coords (1-w, 0, w)
14146  return target.copy( a ).addScaledVector( vac, w );
14147 
14148  }
14149 
14150  var va = d3 * d6 - d5 * d4;
14151  if ( va <= 0 && ( d4 - d3 ) >= 0 && ( d5 - d6 ) >= 0 ) {
14152 
14153  vbc.subVectors( c, b );
14154  w = ( d4 - d3 ) / ( ( d4 - d3 ) + ( d5 - d6 ) );
14155  // edge region of BC; barycentric coords (0, 1-w, w)
14156  return target.copy( b ).addScaledVector( vbc, w ); // edge region of BC
14157 
14158  }
14159 
14160  // face region
14161  var denom = 1 / ( va + vb + vc );
14162  // u = va * denom
14163  v = vb * denom;
14164  w = vc * denom;
14165  return target.copy( a ).addScaledVector( vab, v ).addScaledVector( vac, w );
14166 
14167  };
14168 
14169  }(),
14170 
14171  equals: function ( triangle ) {
14172 
14173  return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c );
14174 
14175  }
14176 
14177  } );
14178 
14214  function MeshBasicMaterial( parameters ) {
14215 
14216  Material.call( this );
14217 
14218  this.type = 'MeshBasicMaterial';
14219 
14220  this.color = new Color( 0xffffff ); // emissive
14221 
14222  this.map = null;
14223 
14224  this.lightMap = null;
14225  this.lightMapIntensity = 1.0;
14226 
14227  this.aoMap = null;
14228  this.aoMapIntensity = 1.0;
14229 
14230  this.specularMap = null;
14231 
14232  this.alphaMap = null;
14233 
14234  this.envMap = null;
14235  this.combine = MultiplyOperation;
14236  this.reflectivity = 1;
14237  this.refractionRatio = 0.98;
14238 
14239  this.wireframe = false;
14240  this.wireframeLinewidth = 1;
14241  this.wireframeLinecap = 'round';
14242  this.wireframeLinejoin = 'round';
14243 
14244  this.skinning = false;
14245  this.morphTargets = false;
14246 
14247  this.lights = false;
14248 
14249  this.setValues( parameters );
14250 
14251  }
14252 
14253  MeshBasicMaterial.prototype = Object.create( Material.prototype );
14254  MeshBasicMaterial.prototype.constructor = MeshBasicMaterial;
14255 
14256  MeshBasicMaterial.prototype.isMeshBasicMaterial = true;
14257 
14258  MeshBasicMaterial.prototype.copy = function ( source ) {
14259 
14260  Material.prototype.copy.call( this, source );
14261 
14262  this.color.copy( source.color );
14263 
14264  this.map = source.map;
14265 
14266  this.lightMap = source.lightMap;
14267  this.lightMapIntensity = source.lightMapIntensity;
14268 
14269  this.aoMap = source.aoMap;
14270  this.aoMapIntensity = source.aoMapIntensity;
14271 
14272  this.specularMap = source.specularMap;
14273 
14274  this.alphaMap = source.alphaMap;
14275 
14276  this.envMap = source.envMap;
14277  this.combine = source.combine;
14278  this.reflectivity = source.reflectivity;
14279  this.refractionRatio = source.refractionRatio;
14280 
14281  this.wireframe = source.wireframe;
14282  this.wireframeLinewidth = source.wireframeLinewidth;
14283  this.wireframeLinecap = source.wireframeLinecap;
14284  this.wireframeLinejoin = source.wireframeLinejoin;
14285 
14286  this.skinning = source.skinning;
14287  this.morphTargets = source.morphTargets;
14288 
14289  return this;
14290 
14291  };
14292 
14300  function Mesh( geometry, material ) {
14301 
14302  Object3D.call( this );
14303 
14304  this.type = 'Mesh';
14305 
14306  this.geometry = geometry !== undefined ? geometry : new BufferGeometry();
14307  this.material = material !== undefined ? material : new MeshBasicMaterial( { color: Math.random() * 0xffffff } );
14308 
14309  this.drawMode = TrianglesDrawMode;
14310 
14311  this.updateMorphTargets();
14312 
14313  }
14314 
14315  Mesh.prototype = Object.assign( Object.create( Object3D.prototype ), {
14316 
14317  constructor: Mesh,
14318 
14319  isMesh: true,
14320 
14321  setDrawMode: function ( value ) {
14322 
14323  this.drawMode = value;
14324 
14325  },
14326 
14327  copy: function ( source ) {
14328 
14329  Object3D.prototype.copy.call( this, source );
14330 
14331  this.drawMode = source.drawMode;
14332 
14333  if ( source.morphTargetInfluences !== undefined ) {
14334 
14335  this.morphTargetInfluences = source.morphTargetInfluences.slice();
14336 
14337  }
14338 
14339  if ( source.morphTargetDictionary !== undefined ) {
14340 
14341  this.morphTargetDictionary = Object.assign( {}, source.morphTargetDictionary );
14342 
14343  }
14344 
14345  return this;
14346 
14347  },
14348 
14349  updateMorphTargets: function () {
14350 
14351  var geometry = this.geometry;
14352  var m, ml, name;
14353 
14354  if ( geometry.isBufferGeometry ) {
14355 
14356  var morphAttributes = geometry.morphAttributes;
14357  var keys = Object.keys( morphAttributes );
14358 
14359  if ( keys.length > 0 ) {
14360 
14361  var morphAttribute = morphAttributes[ keys[ 0 ] ];
14362 
14363  if ( morphAttribute !== undefined ) {
14364 
14365  this.morphTargetInfluences = [];
14366  this.morphTargetDictionary = {};
14367 
14368  for ( m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
14369 
14370  name = morphAttribute[ m ].name || String( m );
14371 
14372  this.morphTargetInfluences.push( 0 );
14373  this.morphTargetDictionary[ name ] = m;
14374 
14375  }
14376 
14377  }
14378 
14379  }
14380 
14381  } else {
14382 
14383  var morphTargets = geometry.morphTargets;
14384 
14385  if ( morphTargets !== undefined && morphTargets.length > 0 ) {
14386 
14387  console.error( 'THREE.Mesh.updateMorphTargets() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );
14388 
14389  }
14390 
14391  }
14392 
14393  },
14394 
14395  raycast: ( function () {
14396 
14397  var inverseMatrix = new Matrix4();
14398  var ray = new Ray();
14399  var sphere = new Sphere();
14400 
14401  var vA = new Vector3();
14402  var vB = new Vector3();
14403  var vC = new Vector3();
14404 
14405  var tempA = new Vector3();
14406  var tempB = new Vector3();
14407  var tempC = new Vector3();
14408 
14409  var uvA = new Vector2();
14410  var uvB = new Vector2();
14411  var uvC = new Vector2();
14412 
14413  var intersectionPoint = new Vector3();
14414  var intersectionPointWorld = new Vector3();
14415 
14416  function checkIntersection( object, material, raycaster, ray, pA, pB, pC, point ) {
14417 
14418  var intersect;
14419 
14420  if ( material.side === BackSide ) {
14421 
14422  intersect = ray.intersectTriangle( pC, pB, pA, true, point );
14423 
14424  } else {
14425 
14426  intersect = ray.intersectTriangle( pA, pB, pC, material.side !== DoubleSide, point );
14427 
14428  }
14429 
14430  if ( intersect === null ) return null;
14431 
14432  intersectionPointWorld.copy( point );
14433  intersectionPointWorld.applyMatrix4( object.matrixWorld );
14434 
14435  var distance = raycaster.ray.origin.distanceTo( intersectionPointWorld );
14436 
14437  if ( distance < raycaster.near || distance > raycaster.far ) return null;
14438 
14439  return {
14440  distance: distance,
14441  point: intersectionPointWorld.clone(),
14442  object: object
14443  };
14444 
14445  }
14446 
14447  function checkBufferGeometryIntersection( object, material, raycaster, ray, position, uv, a, b, c ) {
14448 
14449  vA.fromBufferAttribute( position, a );
14450  vB.fromBufferAttribute( position, b );
14451  vC.fromBufferAttribute( position, c );
14452 
14453  var intersection = checkIntersection( object, material, raycaster, ray, vA, vB, vC, intersectionPoint );
14454 
14455  if ( intersection ) {
14456 
14457  if ( uv ) {
14458 
14459  uvA.fromBufferAttribute( uv, a );
14460  uvB.fromBufferAttribute( uv, b );
14461  uvC.fromBufferAttribute( uv, c );
14462 
14463  intersection.uv = Triangle.getUV( intersectionPoint, vA, vB, vC, uvA, uvB, uvC, new Vector2() );
14464 
14465  }
14466 
14467  var face = new Face3( a, b, c );
14468  Triangle.getNormal( vA, vB, vC, face.normal );
14469 
14470  intersection.face = face;
14471 
14472  }
14473 
14474  return intersection;
14475 
14476  }
14477 
14478  return function raycast( raycaster, intersects ) {
14479 
14480  var geometry = this.geometry;
14481  var material = this.material;
14482  var matrixWorld = this.matrixWorld;
14483 
14484  if ( material === undefined ) return;
14485 
14486  // Checking boundingSphere distance to ray
14487 
14488  if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
14489 
14490  sphere.copy( geometry.boundingSphere );
14491  sphere.applyMatrix4( matrixWorld );
14492 
14493  if ( raycaster.ray.intersectsSphere( sphere ) === false ) return;
14494 
14495  //
14496 
14497  inverseMatrix.getInverse( matrixWorld );
14498  ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix );
14499 
14500  // Check boundingBox before continuing
14501 
14502  if ( geometry.boundingBox !== null ) {
14503 
14504  if ( ray.intersectsBox( geometry.boundingBox ) === false ) return;
14505 
14506  }
14507 
14508  var intersection;
14509 
14510  if ( geometry.isBufferGeometry ) {
14511 
14512  var a, b, c;
14513  var index = geometry.index;
14514  var position = geometry.attributes.position;
14515  var uv = geometry.attributes.uv;
14516  var groups = geometry.groups;
14517  var drawRange = geometry.drawRange;
14518  var i, j, il, jl;
14519  var group, groupMaterial;
14520  var start, end;
14521 
14522  if ( index !== null ) {
14523 
14524  // indexed buffer geometry
14525 
14526  if ( Array.isArray( material ) ) {
14527 
14528  for ( i = 0, il = groups.length; i < il; i ++ ) {
14529 
14530  group = groups[ i ];
14531  groupMaterial = material[ group.materialIndex ];
14532 
14533  start = Math.max( group.start, drawRange.start );
14534  end = Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) );
14535 
14536  for ( j = start, jl = end; j < jl; j += 3 ) {
14537 
14538  a = index.getX( j );
14539  b = index.getX( j + 1 );
14540  c = index.getX( j + 2 );
14541 
14542  intersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, ray, position, uv, a, b, c );
14543 
14544  if ( intersection ) {
14545 
14546  intersection.faceIndex = Math.floor( j / 3 ); // triangle number in indexed buffer semantics
14547  intersection.face.materialIndex = group.materialIndex;
14548  intersects.push( intersection );
14549 
14550  }
14551 
14552  }
14553 
14554  }
14555 
14556  } else {
14557 
14558  start = Math.max( 0, drawRange.start );
14559  end = Math.min( index.count, ( drawRange.start + drawRange.count ) );
14560 
14561  for ( i = start, il = end; i < il; i += 3 ) {
14562 
14563  a = index.getX( i );
14564  b = index.getX( i + 1 );
14565  c = index.getX( i + 2 );
14566 
14567  intersection = checkBufferGeometryIntersection( this, material, raycaster, ray, position, uv, a, b, c );
14568 
14569  if ( intersection ) {
14570 
14571  intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indexed buffer semantics
14572  intersects.push( intersection );
14573 
14574  }
14575 
14576  }
14577 
14578  }
14579 
14580  } else if ( position !== undefined ) {
14581 
14582  // non-indexed buffer geometry
14583 
14584  if ( Array.isArray( material ) ) {
14585 
14586  for ( i = 0, il = groups.length; i < il; i ++ ) {
14587 
14588  group = groups[ i ];
14589  groupMaterial = material[ group.materialIndex ];
14590 
14591  start = Math.max( group.start, drawRange.start );
14592  end = Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) );
14593 
14594  for ( j = start, jl = end; j < jl; j += 3 ) {
14595 
14596  a = j;
14597  b = j + 1;
14598  c = j + 2;
14599 
14600  intersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, ray, position, uv, a, b, c );
14601 
14602  if ( intersection ) {
14603 
14604  intersection.faceIndex = Math.floor( j / 3 ); // triangle number in non-indexed buffer semantics
14605  intersection.face.materialIndex = group.materialIndex;
14606  intersects.push( intersection );
14607 
14608  }
14609 
14610  }
14611 
14612  }
14613 
14614  } else {
14615 
14616  start = Math.max( 0, drawRange.start );
14617  end = Math.min( position.count, ( drawRange.start + drawRange.count ) );
14618 
14619  for ( i = start, il = end; i < il; i += 3 ) {
14620 
14621  a = i;
14622  b = i + 1;
14623  c = i + 2;
14624 
14625  intersection = checkBufferGeometryIntersection( this, material, raycaster, ray, position, uv, a, b, c );
14626 
14627  if ( intersection ) {
14628 
14629  intersection.faceIndex = Math.floor( i / 3 ); // triangle number in non-indexed buffer semantics
14630  intersects.push( intersection );
14631 
14632  }
14633 
14634  }
14635 
14636  }
14637 
14638  }
14639 
14640  } else if ( geometry.isGeometry ) {
14641 
14642  var fvA, fvB, fvC;
14643  var isMultiMaterial = Array.isArray( material );
14644 
14645  var vertices = geometry.vertices;
14646  var faces = geometry.faces;
14647  var uvs;
14648 
14649  var faceVertexUvs = geometry.faceVertexUvs[ 0 ];
14650  if ( faceVertexUvs.length > 0 ) uvs = faceVertexUvs;
14651 
14652  for ( var f = 0, fl = faces.length; f < fl; f ++ ) {
14653 
14654  var face = faces[ f ];
14655  var faceMaterial = isMultiMaterial ? material[ face.materialIndex ] : material;
14656 
14657  if ( faceMaterial === undefined ) continue;
14658 
14659  fvA = vertices[ face.a ];
14660  fvB = vertices[ face.b ];
14661  fvC = vertices[ face.c ];
14662 
14663  if ( faceMaterial.morphTargets === true ) {
14664 
14665  var morphTargets = geometry.morphTargets;
14666  var morphInfluences = this.morphTargetInfluences;
14667 
14668  vA.set( 0, 0, 0 );
14669  vB.set( 0, 0, 0 );
14670  vC.set( 0, 0, 0 );
14671 
14672  for ( var t = 0, tl = morphTargets.length; t < tl; t ++ ) {
14673 
14674  var influence = morphInfluences[ t ];
14675 
14676  if ( influence === 0 ) continue;
14677 
14678  var targets = morphTargets[ t ].vertices;
14679 
14680  vA.addScaledVector( tempA.subVectors( targets[ face.a ], fvA ), influence );
14681  vB.addScaledVector( tempB.subVectors( targets[ face.b ], fvB ), influence );
14682  vC.addScaledVector( tempC.subVectors( targets[ face.c ], fvC ), influence );
14683 
14684  }
14685 
14686  vA.add( fvA );
14687  vB.add( fvB );
14688  vC.add( fvC );
14689 
14690  fvA = vA;
14691  fvB = vB;
14692  fvC = vC;
14693 
14694  }
14695 
14696  intersection = checkIntersection( this, faceMaterial, raycaster, ray, fvA, fvB, fvC, intersectionPoint );
14697 
14698  if ( intersection ) {
14699 
14700  if ( uvs && uvs[ f ] ) {
14701 
14702  var uvs_f = uvs[ f ];
14703  uvA.copy( uvs_f[ 0 ] );
14704  uvB.copy( uvs_f[ 1 ] );
14705  uvC.copy( uvs_f[ 2 ] );
14706 
14707  intersection.uv = Triangle.getUV( intersectionPoint, fvA, fvB, fvC, uvA, uvB, uvC, new Vector2() );
14708 
14709  }
14710 
14711  intersection.face = face;
14712  intersection.faceIndex = f;
14713  intersects.push( intersection );
14714 
14715  }
14716 
14717  }
14718 
14719  }
14720 
14721  };
14722 
14723  }() ),
14724 
14725  clone: function () {
14726 
14727  return new this.constructor( this.geometry, this.material ).copy( this );
14728 
14729  }
14730 
14731  } );
14732 
14737  function WebGLBackground( renderer, state, objects, premultipliedAlpha ) {
14738 
14739  var clearColor = new Color( 0x000000 );
14740  var clearAlpha = 0;
14741 
14742  var planeMesh;
14743  var boxMesh;
14744  // Store the current background texture and its `version`
14745  // so we can recompile the material accordingly.
14746  var currentBackground = null;
14747  var currentBackgroundVersion = 0;
14748 
14749  function render( renderList, scene, camera, forceClear ) {
14750 
14751  var background = scene.background;
14752 
14753  if ( background === null ) {
14754 
14755  setClear( clearColor, clearAlpha );
14756  currentBackground = null;
14757  currentBackgroundVersion = 0;
14758 
14759  } else if ( background && background.isColor ) {
14760 
14761  setClear( background, 1 );
14762  forceClear = true;
14763  currentBackground = null;
14764  currentBackgroundVersion = 0;
14765 
14766  }
14767 
14768  if ( renderer.autoClear || forceClear ) {
14769 
14770  renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil );
14771 
14772  }
14773 
14774  if ( background && ( background.isCubeTexture || background.isWebGLRenderTargetCube ) ) {
14775 
14776  if ( boxMesh === undefined ) {
14777 
14778  boxMesh = new Mesh(
14779  new BoxBufferGeometry( 1, 1, 1 ),
14780  new ShaderMaterial( {
14781  type: 'BackgroundCubeMaterial',
14782  uniforms: cloneUniforms( ShaderLib.cube.uniforms ),
14783  vertexShader: ShaderLib.cube.vertexShader,
14784  fragmentShader: ShaderLib.cube.fragmentShader,
14785  side: BackSide,
14786  depthTest: false,
14787  depthWrite: false,
14788  fog: false
14789  } )
14790  );
14791 
14792  boxMesh.geometry.removeAttribute( 'normal' );
14793  boxMesh.geometry.removeAttribute( 'uv' );
14794 
14795  boxMesh.onBeforeRender = function ( renderer, scene, camera ) {
14796 
14797  this.matrixWorld.copyPosition( camera.matrixWorld );
14798 
14799  };
14800 
14801  // enable code injection for non-built-in material
14802  Object.defineProperty( boxMesh.material, 'map', {
14803 
14804  get: function () {
14805 
14806  return this.uniforms.tCube.value;
14807 
14808  }
14809 
14810  } );
14811 
14812  objects.update( boxMesh );
14813 
14814  }
14815 
14816  var texture = background.isWebGLRenderTargetCube ? background.texture : background;
14817  boxMesh.material.uniforms.tCube.value = texture;
14818  boxMesh.material.uniforms.tFlip.value = ( background.isWebGLRenderTargetCube ) ? 1 : - 1;
14819 
14820  if ( currentBackground !== background ||
14821  currentBackgroundVersion !== texture.version ) {
14822 
14823  boxMesh.material.needsUpdate = true;
14824 
14825  currentBackground = background;
14826  currentBackgroundVersion = texture.version;
14827 
14828  }
14829 
14830  // push to the pre-sorted opaque render list
14831  renderList.unshift( boxMesh, boxMesh.geometry, boxMesh.material, 0, 0, null );
14832 
14833  } else if ( background && background.isTexture ) {
14834 
14835  if ( planeMesh === undefined ) {
14836 
14837  planeMesh = new Mesh(
14838  new PlaneBufferGeometry( 2, 2 ),
14839  new ShaderMaterial( {
14840  type: 'BackgroundMaterial',
14841  uniforms: cloneUniforms( ShaderLib.background.uniforms ),
14842  vertexShader: ShaderLib.background.vertexShader,
14843  fragmentShader: ShaderLib.background.fragmentShader,
14844  side: FrontSide,
14845  depthTest: false,
14846  depthWrite: false,
14847  fog: false
14848  } )
14849  );
14850 
14851  planeMesh.geometry.removeAttribute( 'normal' );
14852 
14853  // enable code injection for non-built-in material
14854  Object.defineProperty( planeMesh.material, 'map', {
14855 
14856  get: function () {
14857 
14858  return this.uniforms.t2D.value;
14859 
14860  }
14861 
14862  } );
14863 
14864  objects.update( planeMesh );
14865 
14866  }
14867 
14868  planeMesh.material.uniforms.t2D.value = background;
14869 
14870  if ( background.matrixAutoUpdate === true ) {
14871 
14872  background.updateMatrix();
14873 
14874  }
14875 
14876  planeMesh.material.uniforms.uvTransform.value.copy( background.matrix );
14877 
14878  if ( currentBackground !== background ||
14879  currentBackgroundVersion !== background.version ) {
14880 
14881  planeMesh.material.needsUpdate = true;
14882 
14883  currentBackground = background;
14884  currentBackgroundVersion = background.version;
14885 
14886  }
14887 
14888 
14889  // push to the pre-sorted opaque render list
14890  renderList.unshift( planeMesh, planeMesh.geometry, planeMesh.material, 0, 0, null );
14891 
14892  }
14893 
14894  }
14895 
14896  function setClear( color, alpha ) {
14897 
14898  state.buffers.color.setClear( color.r, color.g, color.b, alpha, premultipliedAlpha );
14899 
14900  }
14901 
14902  return {
14903 
14904  getClearColor: function () {
14905 
14906  return clearColor;
14907 
14908  },
14909  setClearColor: function ( color, alpha ) {
14910 
14911  clearColor.set( color );
14912  clearAlpha = alpha !== undefined ? alpha : 1;
14913  setClear( clearColor, clearAlpha );
14914 
14915  },
14916  getClearAlpha: function () {
14917 
14918  return clearAlpha;
14919 
14920  },
14921  setClearAlpha: function ( alpha ) {
14922 
14923  clearAlpha = alpha;
14924  setClear( clearColor, clearAlpha );
14925 
14926  },
14927  render: render
14928 
14929  };
14930 
14931  }
14932 
14937  function WebGLBufferRenderer( gl, extensions, info, capabilities ) {
14938 
14939  var mode;
14940 
14941  function setMode( value ) {
14942 
14943  mode = value;
14944 
14945  }
14946 
14947  function render( start, count ) {
14948 
14949  gl.drawArrays( mode, start, count );
14950 
14951  info.update( count, mode );
14952 
14953  }
14954 
14955  function renderInstances( geometry, start, count ) {
14956 
14957  var extension;
14958 
14959  if ( capabilities.isWebGL2 ) {
14960 
14961  extension = gl;
14962 
14963  } else {
14964 
14965  extension = extensions.get( 'ANGLE_instanced_arrays' );
14966 
14967  if ( extension === null ) {
14968 
14969  console.error( 'THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
14970  return;
14971 
14972  }
14973 
14974  }
14975 
14976  extension[ capabilities.isWebGL2 ? 'drawArraysInstanced' : 'drawArraysInstancedANGLE' ]( mode, start, count, geometry.maxInstancedCount );
14977 
14978  info.update( count, mode, geometry.maxInstancedCount );
14979 
14980  }
14981 
14982  //
14983 
14984  this.setMode = setMode;
14985  this.render = render;
14986  this.renderInstances = renderInstances;
14987 
14988  }
14989 
14994  function WebGLCapabilities( gl, extensions, parameters ) {
14995 
14996  var maxAnisotropy;
14997 
14998  function getMaxAnisotropy() {
14999 
15000  if ( maxAnisotropy !== undefined ) return maxAnisotropy;
15001 
15002  var extension = extensions.get( 'EXT_texture_filter_anisotropic' );
15003 
15004  if ( extension !== null ) {
15005 
15006  maxAnisotropy = gl.getParameter( extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT );
15007 
15008  } else {
15009 
15010  maxAnisotropy = 0;
15011 
15012  }
15013 
15014  return maxAnisotropy;
15015 
15016  }
15017 
15018  function getMaxPrecision( precision ) {
15019 
15020  if ( precision === 'highp' ) {
15021 
15022  if ( gl.getShaderPrecisionFormat( 35633, 36338 ).precision > 0 &&
15023  gl.getShaderPrecisionFormat( 35632, 36338 ).precision > 0 ) {
15024 
15025  return 'highp';
15026 
15027  }
15028 
15029  precision = 'mediump';
15030 
15031  }
15032 
15033  if ( precision === 'mediump' ) {
15034 
15035  if ( gl.getShaderPrecisionFormat( 35633, 36337 ).precision > 0 &&
15036  gl.getShaderPrecisionFormat( 35632, 36337 ).precision > 0 ) {
15037 
15038  return 'mediump';
15039 
15040  }
15041 
15042  }
15043 
15044  return 'lowp';
15045 
15046  }
15047 
15048  var isWebGL2 = typeof WebGL2RenderingContext !== 'undefined' && gl instanceof WebGL2RenderingContext;
15049 
15050  var precision = parameters.precision !== undefined ? parameters.precision : 'highp';
15051  var maxPrecision = getMaxPrecision( precision );
15052 
15053  if ( maxPrecision !== precision ) {
15054 
15055  console.warn( 'THREE.WebGLRenderer:', precision, 'not supported, using', maxPrecision, 'instead.' );
15056  precision = maxPrecision;
15057 
15058  }
15059 
15060  var logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true;
15061 
15062  var maxTextures = gl.getParameter( 34930 );
15063  var maxVertexTextures = gl.getParameter( 35660 );
15064  var maxTextureSize = gl.getParameter( 3379 );
15065  var maxCubemapSize = gl.getParameter( 34076 );
15066 
15067  var maxAttributes = gl.getParameter( 34921 );
15068  var maxVertexUniforms = gl.getParameter( 36347 );
15069  var maxVaryings = gl.getParameter( 36348 );
15070  var maxFragmentUniforms = gl.getParameter( 36349 );
15071 
15072  var vertexTextures = maxVertexTextures > 0;
15073  var floatFragmentTextures = isWebGL2 || !! extensions.get( 'OES_texture_float' );
15074  var floatVertexTextures = vertexTextures && floatFragmentTextures;
15075 
15076  var maxSamples = isWebGL2 ? gl.getParameter( 36183 ) : 0;
15077 
15078  return {
15079 
15080  isWebGL2: isWebGL2,
15081 
15082  getMaxAnisotropy: getMaxAnisotropy,
15083  getMaxPrecision: getMaxPrecision,
15084 
15085  precision: precision,
15086  logarithmicDepthBuffer: logarithmicDepthBuffer,
15087 
15088  maxTextures: maxTextures,
15089  maxVertexTextures: maxVertexTextures,
15090  maxTextureSize: maxTextureSize,
15091  maxCubemapSize: maxCubemapSize,
15092 
15093  maxAttributes: maxAttributes,
15094  maxVertexUniforms: maxVertexUniforms,
15095  maxVaryings: maxVaryings,
15096  maxFragmentUniforms: maxFragmentUniforms,
15097 
15098  vertexTextures: vertexTextures,
15099  floatFragmentTextures: floatFragmentTextures,
15100  floatVertexTextures: floatVertexTextures,
15101 
15102  maxSamples: maxSamples
15103 
15104  };
15105 
15106  }
15107 
15112  function WebGLClipping() {
15113 
15114  var scope = this,
15115 
15116  globalState = null,
15117  numGlobalPlanes = 0,
15118  localClippingEnabled = false,
15119  renderingShadows = false,
15120 
15121  plane = new Plane(),
15122  viewNormalMatrix = new Matrix3(),
15123 
15124  uniform = { value: null, needsUpdate: false };
15125 
15126  this.uniform = uniform;
15127  this.numPlanes = 0;
15128  this.numIntersection = 0;
15129 
15130  this.init = function ( planes, enableLocalClipping, camera ) {
15131 
15132  var enabled =
15133  planes.length !== 0 ||
15134  enableLocalClipping ||
15135  // enable state of previous frame - the clipping code has to
15136  // run another frame in order to reset the state:
15137  numGlobalPlanes !== 0 ||
15138  localClippingEnabled;
15139 
15140  localClippingEnabled = enableLocalClipping;
15141 
15142  globalState = projectPlanes( planes, camera, 0 );
15143  numGlobalPlanes = planes.length;
15144 
15145  return enabled;
15146 
15147  };
15148 
15149  this.beginShadows = function () {
15150 
15151  renderingShadows = true;
15152  projectPlanes( null );
15153 
15154  };
15155 
15156  this.endShadows = function () {
15157 
15158  renderingShadows = false;
15159  resetGlobalState();
15160 
15161  };
15162 
15163  this.setState = function ( planes, clipIntersection, clipShadows, camera, cache, fromCache ) {
15164 
15165  if ( ! localClippingEnabled || planes === null || planes.length === 0 || renderingShadows && ! clipShadows ) {
15166 
15167  // there's no local clipping
15168 
15169  if ( renderingShadows ) {
15170 
15171  // there's no global clipping
15172 
15173  projectPlanes( null );
15174 
15175  } else {
15176 
15177  resetGlobalState();
15178 
15179  }
15180 
15181  } else {
15182 
15183  var nGlobal = renderingShadows ? 0 : numGlobalPlanes,
15184  lGlobal = nGlobal * 4,
15185 
15186  dstArray = cache.clippingState || null;
15187 
15188  uniform.value = dstArray; // ensure unique state
15189 
15190  dstArray = projectPlanes( planes, camera, lGlobal, fromCache );
15191 
15192  for ( var i = 0; i !== lGlobal; ++ i ) {
15193 
15194  dstArray[ i ] = globalState[ i ];
15195 
15196  }
15197 
15198  cache.clippingState = dstArray;
15199  this.numIntersection = clipIntersection ? this.numPlanes : 0;
15200  this.numPlanes += nGlobal;
15201 
15202  }
15203 
15204 
15205  };
15206 
15207  function resetGlobalState() {
15208 
15209  if ( uniform.value !== globalState ) {
15210 
15211  uniform.value = globalState;
15212  uniform.needsUpdate = numGlobalPlanes > 0;
15213 
15214  }
15215 
15216  scope.numPlanes = numGlobalPlanes;
15217  scope.numIntersection = 0;
15218 
15219  }
15220 
15221  function projectPlanes( planes, camera, dstOffset, skipTransform ) {
15222 
15223  var nPlanes = planes !== null ? planes.length : 0,
15224  dstArray = null;
15225 
15226  if ( nPlanes !== 0 ) {
15227 
15228  dstArray = uniform.value;
15229 
15230  if ( skipTransform !== true || dstArray === null ) {
15231 
15232  var flatSize = dstOffset + nPlanes * 4,
15233  viewMatrix = camera.matrixWorldInverse;
15234 
15235  viewNormalMatrix.getNormalMatrix( viewMatrix );
15236 
15237  if ( dstArray === null || dstArray.length < flatSize ) {
15238 
15239  dstArray = new Float32Array( flatSize );
15240 
15241  }
15242 
15243  for ( var i = 0, i4 = dstOffset; i !== nPlanes; ++ i, i4 += 4 ) {
15244 
15245  plane.copy( planes[ i ] ).applyMatrix4( viewMatrix, viewNormalMatrix );
15246 
15247  plane.normal.toArray( dstArray, i4 );
15248  dstArray[ i4 + 3 ] = plane.constant;
15249 
15250  }
15251 
15252  }
15253 
15254  uniform.value = dstArray;
15255  uniform.needsUpdate = true;
15256 
15257  }
15258 
15259  scope.numPlanes = nPlanes;
15260 
15261  return dstArray;
15262 
15263  }
15264 
15265  }
15266 
15271  function WebGLExtensions( gl ) {
15272 
15273  var extensions = {};
15274 
15275  return {
15276 
15277  get: function ( name ) {
15278 
15279  if ( extensions[ name ] !== undefined ) {
15280 
15281  return extensions[ name ];
15282 
15283  }
15284 
15285  var extension;
15286 
15287  switch ( name ) {
15288 
15289  case 'WEBGL_depth_texture':
15290  extension = gl.getExtension( 'WEBGL_depth_texture' ) || gl.getExtension( 'MOZ_WEBGL_depth_texture' ) || gl.getExtension( 'WEBKIT_WEBGL_depth_texture' );
15291  break;
15292 
15293  case 'EXT_texture_filter_anisotropic':
15294  extension = gl.getExtension( 'EXT_texture_filter_anisotropic' ) || gl.getExtension( 'MOZ_EXT_texture_filter_anisotropic' ) || gl.getExtension( 'WEBKIT_EXT_texture_filter_anisotropic' );
15295  break;
15296 
15297  case 'WEBGL_compressed_texture_s3tc':
15298  extension = gl.getExtension( 'WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'MOZ_WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_s3tc' );
15299  break;
15300 
15301  case 'WEBGL_compressed_texture_pvrtc':
15302  extension = gl.getExtension( 'WEBGL_compressed_texture_pvrtc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_pvrtc' );
15303  break;
15304 
15305  default:
15306  extension = gl.getExtension( name );
15307 
15308  }
15309 
15310  if ( extension === null ) {
15311 
15312  console.warn( 'THREE.WebGLRenderer: ' + name + ' extension not supported.' );
15313 
15314  }
15315 
15316  extensions[ name ] = extension;
15317 
15318  return extension;
15319 
15320  }
15321 
15322  };
15323 
15324  }
15325 
15330  function WebGLGeometries( gl, attributes, info ) {
15331 
15332  var geometries = {};
15333  var wireframeAttributes = {};
15334 
15335  function onGeometryDispose( event ) {
15336 
15337  var geometry = event.target;
15338  var buffergeometry = geometries[ geometry.id ];
15339 
15340  if ( buffergeometry.index !== null ) {
15341 
15342  attributes.remove( buffergeometry.index );
15343 
15344  }
15345 
15346  for ( var name in buffergeometry.attributes ) {
15347 
15348  attributes.remove( buffergeometry.attributes[ name ] );
15349 
15350  }
15351 
15352  geometry.removeEventListener( 'dispose', onGeometryDispose );
15353 
15354  delete geometries[ geometry.id ];
15355 
15356  var attribute = wireframeAttributes[ buffergeometry.id ];
15357 
15358  if ( attribute ) {
15359 
15360  attributes.remove( attribute );
15361  delete wireframeAttributes[ buffergeometry.id ];
15362 
15363  }
15364 
15365  //
15366 
15367  info.memory.geometries --;
15368 
15369  }
15370 
15371  function get( object, geometry ) {
15372 
15373  var buffergeometry = geometries[ geometry.id ];
15374 
15375  if ( buffergeometry ) return buffergeometry;
15376 
15377  geometry.addEventListener( 'dispose', onGeometryDispose );
15378 
15379  if ( geometry.isBufferGeometry ) {
15380 
15381  buffergeometry = geometry;
15382 
15383  } else if ( geometry.isGeometry ) {
15384 
15385  if ( geometry._bufferGeometry === undefined ) {
15386 
15387  geometry._bufferGeometry = new BufferGeometry().setFromObject( object );
15388 
15389  }
15390 
15391  buffergeometry = geometry._bufferGeometry;
15392 
15393  }
15394 
15395  geometries[ geometry.id ] = buffergeometry;
15396 
15397  info.memory.geometries ++;
15398 
15399  return buffergeometry;
15400 
15401  }
15402 
15403  function update( geometry ) {
15404 
15405  var index = geometry.index;
15406  var geometryAttributes = geometry.attributes;
15407 
15408  if ( index !== null ) {
15409 
15410  attributes.update( index, 34963 );
15411 
15412  }
15413 
15414  for ( var name in geometryAttributes ) {
15415 
15416  attributes.update( geometryAttributes[ name ], 34962 );
15417 
15418  }
15419 
15420  // morph targets
15421 
15422  var morphAttributes = geometry.morphAttributes;
15423 
15424  for ( var name in morphAttributes ) {
15425 
15426  var array = morphAttributes[ name ];
15427 
15428  for ( var i = 0, l = array.length; i < l; i ++ ) {
15429 
15430  attributes.update( array[ i ], 34962 );
15431 
15432  }
15433 
15434  }
15435 
15436  }
15437 
15438  function getWireframeAttribute( geometry ) {
15439 
15440  var attribute = wireframeAttributes[ geometry.id ];
15441 
15442  if ( attribute ) return attribute;
15443 
15444  var indices = [];
15445 
15446  var geometryIndex = geometry.index;
15447  var geometryAttributes = geometry.attributes;
15448 
15449  // console.time( 'wireframe' );
15450 
15451  if ( geometryIndex !== null ) {
15452 
15453  var array = geometryIndex.array;
15454 
15455  for ( var i = 0, l = array.length; i < l; i += 3 ) {
15456 
15457  var a = array[ i + 0 ];
15458  var b = array[ i + 1 ];
15459  var c = array[ i + 2 ];
15460 
15461  indices.push( a, b, b, c, c, a );
15462 
15463  }
15464 
15465  } else {
15466 
15467  var array = geometryAttributes.position.array;
15468 
15469  for ( var i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) {
15470 
15471  var a = i + 0;
15472  var b = i + 1;
15473  var c = i + 2;
15474 
15475  indices.push( a, b, b, c, c, a );
15476 
15477  }
15478 
15479  }
15480 
15481  // console.timeEnd( 'wireframe' );
15482 
15483  attribute = new ( arrayMax( indices ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 );
15484 
15485  attributes.update( attribute, 34963 );
15486 
15487  wireframeAttributes[ geometry.id ] = attribute;
15488 
15489  return attribute;
15490 
15491  }
15492 
15493  return {
15494 
15495  get: get,
15496  update: update,
15497 
15498  getWireframeAttribute: getWireframeAttribute
15499 
15500  };
15501 
15502  }
15503 
15508  function WebGLIndexedBufferRenderer( gl, extensions, info, capabilities ) {
15509 
15510  var mode;
15511 
15512  function setMode( value ) {
15513 
15514  mode = value;
15515 
15516  }
15517 
15518  var type, bytesPerElement;
15519 
15520  function setIndex( value ) {
15521 
15522  type = value.type;
15523  bytesPerElement = value.bytesPerElement;
15524 
15525  }
15526 
15527  function render( start, count ) {
15528 
15529  gl.drawElements( mode, count, type, start * bytesPerElement );
15530 
15531  info.update( count, mode );
15532 
15533  }
15534 
15535  function renderInstances( geometry, start, count ) {
15536 
15537  var extension;
15538 
15539  if ( capabilities.isWebGL2 ) {
15540 
15541  extension = gl;
15542 
15543  } else {
15544 
15545  var extension = extensions.get( 'ANGLE_instanced_arrays' );
15546 
15547  if ( extension === null ) {
15548 
15549  console.error( 'THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
15550  return;
15551 
15552  }
15553 
15554  }
15555 
15556  extension[ capabilities.isWebGL2 ? 'drawElementsInstanced' : 'drawElementsInstancedANGLE' ]( mode, count, type, start * bytesPerElement, geometry.maxInstancedCount );
15557 
15558  info.update( count, mode, geometry.maxInstancedCount );
15559 
15560  }
15561 
15562  //
15563 
15564  this.setMode = setMode;
15565  this.setIndex = setIndex;
15566  this.render = render;
15567  this.renderInstances = renderInstances;
15568 
15569  }
15570 
15575  function WebGLInfo( gl ) {
15576 
15577  var memory = {
15578  geometries: 0,
15579  textures: 0
15580  };
15581 
15582  var render = {
15583  frame: 0,
15584  calls: 0,
15585  triangles: 0,
15586  points: 0,
15587  lines: 0
15588  };
15589 
15590  function update( count, mode, instanceCount ) {
15591 
15592  instanceCount = instanceCount || 1;
15593 
15594  render.calls ++;
15595 
15596  switch ( mode ) {
15597 
15598  case 4:
15599  render.triangles += instanceCount * ( count / 3 );
15600  break;
15601 
15602  case 5:
15603  case 6:
15604  render.triangles += instanceCount * ( count - 2 );
15605  break;
15606 
15607  case 1:
15608  render.lines += instanceCount * ( count / 2 );
15609  break;
15610 
15611  case 3:
15612  render.lines += instanceCount * ( count - 1 );
15613  break;
15614 
15615  case 2:
15616  render.lines += instanceCount * count;
15617  break;
15618 
15619  case 0:
15620  render.points += instanceCount * count;
15621  break;
15622 
15623  default:
15624  console.error( 'THREE.WebGLInfo: Unknown draw mode:', mode );
15625  break;
15626 
15627  }
15628 
15629  }
15630 
15631  function reset() {
15632 
15633  render.frame ++;
15634  render.calls = 0;
15635  render.triangles = 0;
15636  render.points = 0;
15637  render.lines = 0;
15638 
15639  }
15640 
15641  return {
15642  memory: memory,
15643  render: render,
15644  programs: null,
15645  autoReset: true,
15646  reset: reset,
15647  update: update
15648  };
15649 
15650  }
15651 
15656  function absNumericalSort( a, b ) {
15657 
15658  return Math.abs( b[ 1 ] ) - Math.abs( a[ 1 ] );
15659 
15660  }
15661 
15662  function WebGLMorphtargets( gl ) {
15663 
15664  var influencesList = {};
15665  var morphInfluences = new Float32Array( 8 );
15666 
15667  function update( object, geometry, material, program ) {
15668 
15669  var objectInfluences = object.morphTargetInfluences;
15670 
15671  var length = objectInfluences.length;
15672 
15673  var influences = influencesList[ geometry.id ];
15674 
15675  if ( influences === undefined ) {
15676 
15677  // initialise list
15678 
15679  influences = [];
15680 
15681  for ( var i = 0; i < length; i ++ ) {
15682 
15683  influences[ i ] = [ i, 0 ];
15684 
15685  }
15686 
15687  influencesList[ geometry.id ] = influences;
15688 
15689  }
15690 
15691  var morphTargets = material.morphTargets && geometry.morphAttributes.position;
15692  var morphNormals = material.morphNormals && geometry.morphAttributes.normal;
15693 
15694  // Remove current morphAttributes
15695 
15696  for ( var i = 0; i < length; i ++ ) {
15697 
15698  var influence = influences[ i ];
15699 
15700  if ( influence[ 1 ] !== 0 ) {
15701 
15702  if ( morphTargets ) geometry.removeAttribute( 'morphTarget' + i );
15703  if ( morphNormals ) geometry.removeAttribute( 'morphNormal' + i );
15704 
15705  }
15706 
15707  }
15708 
15709  // Collect influences
15710 
15711  for ( var i = 0; i < length; i ++ ) {
15712 
15713  var influence = influences[ i ];
15714 
15715  influence[ 0 ] = i;
15716  influence[ 1 ] = objectInfluences[ i ];
15717 
15718  }
15719 
15720  influences.sort( absNumericalSort );
15721 
15722  // Add morphAttributes
15723 
15724  for ( var i = 0; i < 8; i ++ ) {
15725 
15726  var influence = influences[ i ];
15727 
15728  if ( influence ) {
15729 
15730  var index = influence[ 0 ];
15731  var value = influence[ 1 ];
15732 
15733  if ( value ) {
15734 
15735  if ( morphTargets ) geometry.addAttribute( 'morphTarget' + i, morphTargets[ index ] );
15736  if ( morphNormals ) geometry.addAttribute( 'morphNormal' + i, morphNormals[ index ] );
15737 
15738  morphInfluences[ i ] = value;
15739  continue;
15740 
15741  }
15742 
15743  }
15744 
15745  morphInfluences[ i ] = 0;
15746 
15747  }
15748 
15749  program.getUniforms().setValue( gl, 'morphTargetInfluences', morphInfluences );
15750 
15751  }
15752 
15753  return {
15754 
15755  update: update
15756 
15757  };
15758 
15759  }
15760 
15765  function WebGLObjects( geometries, info ) {
15766 
15767  var updateList = {};
15768 
15769  function update( object ) {
15770 
15771  var frame = info.render.frame;
15772 
15773  var geometry = object.geometry;
15774  var buffergeometry = geometries.get( object, geometry );
15775 
15776  // Update once per frame
15777 
15778  if ( updateList[ buffergeometry.id ] !== frame ) {
15779 
15780  if ( geometry.isGeometry ) {
15781 
15782  buffergeometry.updateFromObject( object );
15783 
15784  }
15785 
15786  geometries.update( buffergeometry );
15787 
15788  updateList[ buffergeometry.id ] = frame;
15789 
15790  }
15791 
15792  return buffergeometry;
15793 
15794  }
15795 
15796  function dispose() {
15797 
15798  updateList = {};
15799 
15800  }
15801 
15802  return {
15803 
15804  update: update,
15805  dispose: dispose
15806 
15807  };
15808 
15809  }
15810 
15815  function CubeTexture( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) {
15816 
15817  images = images !== undefined ? images : [];
15818  mapping = mapping !== undefined ? mapping : CubeReflectionMapping;
15819  format = format !== undefined ? format : RGBFormat;
15820 
15821  Texture.call( this, images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
15822 
15823  this.flipY = false;
15824 
15825  }
15826 
15827  CubeTexture.prototype = Object.create( Texture.prototype );
15828  CubeTexture.prototype.constructor = CubeTexture;
15829 
15830  CubeTexture.prototype.isCubeTexture = true;
15831 
15832  Object.defineProperty( CubeTexture.prototype, 'images', {
15833 
15834  get: function () {
15835 
15836  return this.image;
15837 
15838  },
15839 
15840  set: function ( value ) {
15841 
15842  this.image = value;
15843 
15844  }
15845 
15846  } );
15847 
15852  function DataTexture3D( data, width, height, depth ) {
15853 
15854  // We're going to add .setXXX() methods for setting properties later.
15855  // Users can still set in DataTexture3D directly.
15856  //
15857  // var texture = new THREE.DataTexture3D( data, width, height, depth );
15858  // texture.anisotropy = 16;
15859  //
15860  // See #14839
15861 
15862  Texture.call( this, null );
15863 
15864  this.image = { data: data, width: width, height: height, depth: depth };
15865 
15866  this.magFilter = NearestFilter;
15867  this.minFilter = NearestFilter;
15868 
15869  this.wrapR = ClampToEdgeWrapping;
15870 
15871  this.generateMipmaps = false;
15872  this.flipY = false;
15873 
15874  }
15875 
15876  DataTexture3D.prototype = Object.create( Texture.prototype );
15877  DataTexture3D.prototype.constructor = DataTexture3D;
15878  DataTexture3D.prototype.isDataTexture3D = true;
15879 
15931  var emptyTexture = new Texture();
15932  var emptyTexture3d = new DataTexture3D();
15933  var emptyCubeTexture = new CubeTexture();
15934 
15935  // --- Base for inner nodes (including the root) ---
15936 
15937  function UniformContainer() {
15938 
15939  this.seq = [];
15940  this.map = {};
15941 
15942  }
15943 
15944  // --- Utilities ---
15945 
15946  // Array Caches (provide typed arrays for temporary by size)
15947 
15948  var arrayCacheF32 = [];
15949  var arrayCacheI32 = [];
15950 
15951  // Float32Array caches used for uploading Matrix uniforms
15952 
15953  var mat4array = new Float32Array( 16 );
15954  var mat3array = new Float32Array( 9 );
15955  var mat2array = new Float32Array( 4 );
15956 
15957  // Flattening for arrays of vectors and matrices
15958 
15959  function flatten( array, nBlocks, blockSize ) {
15960 
15961  var firstElem = array[ 0 ];
15962 
15963  if ( firstElem <= 0 || firstElem > 0 ) return array;
15964  // unoptimized: ! isNaN( firstElem )
15965  // see http://jacksondunstan.com/articles/983
15966 
15967  var n = nBlocks * blockSize,
15968  r = arrayCacheF32[ n ];
15969 
15970  if ( r === undefined ) {
15971 
15972  r = new Float32Array( n );
15973  arrayCacheF32[ n ] = r;
15974 
15975  }
15976 
15977  if ( nBlocks !== 0 ) {
15978 
15979  firstElem.toArray( r, 0 );
15980 
15981  for ( var i = 1, offset = 0; i !== nBlocks; ++ i ) {
15982 
15983  offset += blockSize;
15984  array[ i ].toArray( r, offset );
15985 
15986  }
15987 
15988  }
15989 
15990  return r;
15991 
15992  }
15993 
15994  function arraysEqual( a, b ) {
15995 
15996  if ( a.length !== b.length ) return false;
15997 
15998  for ( var i = 0, l = a.length; i < l; i ++ ) {
15999 
16000  if ( a[ i ] !== b[ i ] ) return false;
16001 
16002  }
16003 
16004  return true;
16005 
16006  }
16007 
16008  function copyArray( a, b ) {
16009 
16010  for ( var i = 0, l = b.length; i < l; i ++ ) {
16011 
16012  a[ i ] = b[ i ];
16013 
16014  }
16015 
16016  }
16017 
16018  // Texture unit allocation
16019 
16020  function allocTexUnits( renderer, n ) {
16021 
16022  var r = arrayCacheI32[ n ];
16023 
16024  if ( r === undefined ) {
16025 
16026  r = new Int32Array( n );
16027  arrayCacheI32[ n ] = r;
16028 
16029  }
16030 
16031  for ( var i = 0; i !== n; ++ i )
16032  r[ i ] = renderer.allocTextureUnit();
16033 
16034  return r;
16035 
16036  }
16037 
16038  // --- Setters ---
16039 
16040  // Note: Defining these methods externally, because they come in a bunch
16041  // and this way their names minify.
16042 
16043  // Single scalar
16044 
16045  function setValue1f( gl, v ) {
16046 
16047  var cache = this.cache;
16048 
16049  if ( cache[ 0 ] === v ) return;
16050 
16051  gl.uniform1f( this.addr, v );
16052 
16053  cache[ 0 ] = v;
16054 
16055  }
16056 
16057  function setValue1i( gl, v ) {
16058 
16059  var cache = this.cache;
16060 
16061  if ( cache[ 0 ] === v ) return;
16062 
16063  gl.uniform1i( this.addr, v );
16064 
16065  cache[ 0 ] = v;
16066 
16067  }
16068 
16069  // Single float vector (from flat array or THREE.VectorN)
16070 
16071  function setValue2fv( gl, v ) {
16072 
16073  var cache = this.cache;
16074 
16075  if ( v.x !== undefined ) {
16076 
16077  if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) {
16078 
16079  gl.uniform2f( this.addr, v.x, v.y );
16080 
16081  cache[ 0 ] = v.x;
16082  cache[ 1 ] = v.y;
16083 
16084  }
16085 
16086  } else {
16087 
16088  if ( arraysEqual( cache, v ) ) return;
16089 
16090  gl.uniform2fv( this.addr, v );
16091 
16092  copyArray( cache, v );
16093 
16094  }
16095 
16096  }
16097 
16098  function setValue3fv( gl, v ) {
16099 
16100  var cache = this.cache;
16101 
16102  if ( v.x !== undefined ) {
16103 
16104  if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) {
16105 
16106  gl.uniform3f( this.addr, v.x, v.y, v.z );
16107 
16108  cache[ 0 ] = v.x;
16109  cache[ 1 ] = v.y;
16110  cache[ 2 ] = v.z;
16111 
16112  }
16113 
16114  } else if ( v.r !== undefined ) {
16115 
16116  if ( cache[ 0 ] !== v.r || cache[ 1 ] !== v.g || cache[ 2 ] !== v.b ) {
16117 
16118  gl.uniform3f( this.addr, v.r, v.g, v.b );
16119 
16120  cache[ 0 ] = v.r;
16121  cache[ 1 ] = v.g;
16122  cache[ 2 ] = v.b;
16123 
16124  }
16125 
16126  } else {
16127 
16128  if ( arraysEqual( cache, v ) ) return;
16129 
16130  gl.uniform3fv( this.addr, v );
16131 
16132  copyArray( cache, v );
16133 
16134  }
16135 
16136  }
16137 
16138  function setValue4fv( gl, v ) {
16139 
16140  var cache = this.cache;
16141 
16142  if ( v.x !== undefined ) {
16143 
16144  if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) {
16145 
16146  gl.uniform4f( this.addr, v.x, v.y, v.z, v.w );
16147 
16148  cache[ 0 ] = v.x;
16149  cache[ 1 ] = v.y;
16150  cache[ 2 ] = v.z;
16151  cache[ 3 ] = v.w;
16152 
16153  }
16154 
16155  } else {
16156 
16157  if ( arraysEqual( cache, v ) ) return;
16158 
16159  gl.uniform4fv( this.addr, v );
16160 
16161  copyArray( cache, v );
16162 
16163  }
16164 
16165  }
16166 
16167  // Single matrix (from flat array or MatrixN)
16168 
16169  function setValue2fm( gl, v ) {
16170 
16171  var cache = this.cache;
16172  var elements = v.elements;
16173 
16174  if ( elements === undefined ) {
16175 
16176  if ( arraysEqual( cache, v ) ) return;
16177 
16178  gl.uniformMatrix2fv( this.addr, false, v );
16179 
16180  copyArray( cache, v );
16181 
16182  } else {
16183 
16184  if ( arraysEqual( cache, elements ) ) return;
16185 
16186  mat2array.set( elements );
16187 
16188  gl.uniformMatrix2fv( this.addr, false, mat2array );
16189 
16190  copyArray( cache, elements );
16191 
16192  }
16193 
16194  }
16195 
16196  function setValue3fm( gl, v ) {
16197 
16198  var cache = this.cache;
16199  var elements = v.elements;
16200 
16201  if ( elements === undefined ) {
16202 
16203  if ( arraysEqual( cache, v ) ) return;
16204 
16205  gl.uniformMatrix3fv( this.addr, false, v );
16206 
16207  copyArray( cache, v );
16208 
16209  } else {
16210 
16211  if ( arraysEqual( cache, elements ) ) return;
16212 
16213  mat3array.set( elements );
16214 
16215  gl.uniformMatrix3fv( this.addr, false, mat3array );
16216 
16217  copyArray( cache, elements );
16218 
16219  }
16220 
16221  }
16222 
16223  function setValue4fm( gl, v ) {
16224 
16225  var cache = this.cache;
16226  var elements = v.elements;
16227 
16228  if ( elements === undefined ) {
16229 
16230  if ( arraysEqual( cache, v ) ) return;
16231 
16232  gl.uniformMatrix4fv( this.addr, false, v );
16233 
16234  copyArray( cache, v );
16235 
16236  } else {
16237 
16238  if ( arraysEqual( cache, elements ) ) return;
16239 
16240  mat4array.set( elements );
16241 
16242  gl.uniformMatrix4fv( this.addr, false, mat4array );
16243 
16244  copyArray( cache, elements );
16245 
16246  }
16247 
16248  }
16249 
16250  // Single texture (2D / Cube)
16251 
16252  function setValueT1( gl, v, renderer ) {
16253 
16254  var cache = this.cache;
16255  var unit = renderer.allocTextureUnit();
16256 
16257  if ( cache[ 0 ] !== unit ) {
16258 
16259  gl.uniform1i( this.addr, unit );
16260  cache[ 0 ] = unit;
16261 
16262  }
16263 
16264  renderer.setTexture2D( v || emptyTexture, unit );
16265 
16266  }
16267 
16268  function setValueT3D1( gl, v, renderer ) {
16269 
16270  var cache = this.cache;
16271  var unit = renderer.allocTextureUnit();
16272 
16273  if ( cache[ 0 ] !== unit ) {
16274 
16275  gl.uniform1i( this.addr, unit );
16276  cache[ 0 ] = unit;
16277 
16278  }
16279 
16280  renderer.setTexture3D( v || emptyTexture3d, unit );
16281 
16282  }
16283 
16284  function setValueT6( gl, v, renderer ) {
16285 
16286  var cache = this.cache;
16287  var unit = renderer.allocTextureUnit();
16288 
16289  if ( cache[ 0 ] !== unit ) {
16290 
16291  gl.uniform1i( this.addr, unit );
16292  cache[ 0 ] = unit;
16293 
16294  }
16295 
16296  renderer.setTextureCube( v || emptyCubeTexture, unit );
16297 
16298  }
16299 
16300  // Integer / Boolean vectors or arrays thereof (always flat arrays)
16301 
16302  function setValue2iv( gl, v ) {
16303 
16304  var cache = this.cache;
16305 
16306  if ( arraysEqual( cache, v ) ) return;
16307 
16308  gl.uniform2iv( this.addr, v );
16309 
16310  copyArray( cache, v );
16311 
16312  }
16313 
16314  function setValue3iv( gl, v ) {
16315 
16316  var cache = this.cache;
16317 
16318  if ( arraysEqual( cache, v ) ) return;
16319 
16320  gl.uniform3iv( this.addr, v );
16321 
16322  copyArray( cache, v );
16323 
16324  }
16325 
16326  function setValue4iv( gl, v ) {
16327 
16328  var cache = this.cache;
16329 
16330  if ( arraysEqual( cache, v ) ) return;
16331 
16332  gl.uniform4iv( this.addr, v );
16333 
16334  copyArray( cache, v );
16335 
16336  }
16337 
16338  // Helper to pick the right setter for the singular case
16339 
16340  function getSingularSetter( type ) {
16341 
16342  switch ( type ) {
16343 
16344  case 0x1406: return setValue1f; // FLOAT
16345  case 0x8b50: return setValue2fv; // _VEC2
16346  case 0x8b51: return setValue3fv; // _VEC3
16347  case 0x8b52: return setValue4fv; // _VEC4
16348 
16349  case 0x8b5a: return setValue2fm; // _MAT2
16350  case 0x8b5b: return setValue3fm; // _MAT3
16351  case 0x8b5c: return setValue4fm; // _MAT4
16352 
16353  case 0x8b5e: case 0x8d66: return setValueT1; // SAMPLER_2D, SAMPLER_EXTERNAL_OES
16354  case 0x8B5F: return setValueT3D1; // SAMPLER_3D
16355  case 0x8b60: return setValueT6; // SAMPLER_CUBE
16356 
16357  case 0x1404: case 0x8b56: return setValue1i; // INT, BOOL
16358  case 0x8b53: case 0x8b57: return setValue2iv; // _VEC2
16359  case 0x8b54: case 0x8b58: return setValue3iv; // _VEC3
16360  case 0x8b55: case 0x8b59: return setValue4iv; // _VEC4
16361 
16362  }
16363 
16364  }
16365 
16366  // Array of scalars
16367 
16368  function setValue1fv( gl, v ) {
16369 
16370  var cache = this.cache;
16371 
16372  if ( arraysEqual( cache, v ) ) return;
16373 
16374  gl.uniform1fv( this.addr, v );
16375 
16376  copyArray( cache, v );
16377 
16378  }
16379  function setValue1iv( gl, v ) {
16380 
16381  var cache = this.cache;
16382 
16383  if ( arraysEqual( cache, v ) ) return;
16384 
16385  gl.uniform1iv( this.addr, v );
16386 
16387  copyArray( cache, v );
16388 
16389  }
16390 
16391  // Array of vectors (flat or from THREE classes)
16392 
16393  function setValueV2a( gl, v ) {
16394 
16395  var cache = this.cache;
16396  var data = flatten( v, this.size, 2 );
16397 
16398  if ( arraysEqual( cache, data ) ) return;
16399 
16400  gl.uniform2fv( this.addr, data );
16401 
16402  this.updateCache( data );
16403 
16404  }
16405 
16406  function setValueV3a( gl, v ) {
16407 
16408  var cache = this.cache;
16409  var data = flatten( v, this.size, 3 );
16410 
16411  if ( arraysEqual( cache, data ) ) return;
16412 
16413  gl.uniform3fv( this.addr, data );
16414 
16415  this.updateCache( data );
16416 
16417  }
16418 
16419  function setValueV4a( gl, v ) {
16420 
16421  var cache = this.cache;
16422  var data = flatten( v, this.size, 4 );
16423 
16424  if ( arraysEqual( cache, data ) ) return;
16425 
16426  gl.uniform4fv( this.addr, data );
16427 
16428  this.updateCache( data );
16429 
16430  }
16431 
16432  // Array of matrices (flat or from THREE clases)
16433 
16434  function setValueM2a( gl, v ) {
16435 
16436  var cache = this.cache;
16437  var data = flatten( v, this.size, 4 );
16438 
16439  if ( arraysEqual( cache, data ) ) return;
16440 
16441  gl.uniformMatrix2fv( this.addr, false, data );
16442 
16443  this.updateCache( data );
16444 
16445  }
16446 
16447  function setValueM3a( gl, v ) {
16448 
16449  var cache = this.cache;
16450  var data = flatten( v, this.size, 9 );
16451 
16452  if ( arraysEqual( cache, data ) ) return;
16453 
16454  gl.uniformMatrix3fv( this.addr, false, data );
16455 
16456  this.updateCache( data );
16457 
16458  }
16459 
16460  function setValueM4a( gl, v ) {
16461 
16462  var cache = this.cache;
16463  var data = flatten( v, this.size, 16 );
16464 
16465  if ( arraysEqual( cache, data ) ) return;
16466 
16467  gl.uniformMatrix4fv( this.addr, false, data );
16468 
16469  this.updateCache( data );
16470 
16471  }
16472 
16473  // Array of textures (2D / Cube)
16474 
16475  function setValueT1a( gl, v, renderer ) {
16476 
16477  var cache = this.cache;
16478  var n = v.length;
16479 
16480  var units = allocTexUnits( renderer, n );
16481 
16482  if ( arraysEqual( cache, units ) === false ) {
16483 
16484  gl.uniform1iv( this.addr, units );
16485  copyArray( cache, units );
16486 
16487  }
16488 
16489  for ( var i = 0; i !== n; ++ i ) {
16490 
16491  renderer.setTexture2D( v[ i ] || emptyTexture, units[ i ] );
16492 
16493  }
16494 
16495  }
16496 
16497  function setValueT6a( gl, v, renderer ) {
16498 
16499  var cache = this.cache;
16500  var n = v.length;
16501 
16502  var units = allocTexUnits( renderer, n );
16503 
16504  if ( arraysEqual( cache, units ) === false ) {
16505 
16506  gl.uniform1iv( this.addr, units );
16507  copyArray( cache, units );
16508 
16509  }
16510 
16511  for ( var i = 0; i !== n; ++ i ) {
16512 
16513  renderer.setTextureCube( v[ i ] || emptyCubeTexture, units[ i ] );
16514 
16515  }
16516 
16517  }
16518 
16519  // Helper to pick the right setter for a pure (bottom-level) array
16520 
16521  function getPureArraySetter( type ) {
16522 
16523  switch ( type ) {
16524 
16525  case 0x1406: return setValue1fv; // FLOAT
16526  case 0x8b50: return setValueV2a; // _VEC2
16527  case 0x8b51: return setValueV3a; // _VEC3
16528  case 0x8b52: return setValueV4a; // _VEC4
16529 
16530  case 0x8b5a: return setValueM2a; // _MAT2
16531  case 0x8b5b: return setValueM3a; // _MAT3
16532  case 0x8b5c: return setValueM4a; // _MAT4
16533 
16534  case 0x8b5e: return setValueT1a; // SAMPLER_2D
16535  case 0x8b60: return setValueT6a; // SAMPLER_CUBE
16536 
16537  case 0x1404: case 0x8b56: return setValue1iv; // INT, BOOL
16538  case 0x8b53: case 0x8b57: return setValue2iv; // _VEC2
16539  case 0x8b54: case 0x8b58: return setValue3iv; // _VEC3
16540  case 0x8b55: case 0x8b59: return setValue4iv; // _VEC4
16541 
16542  }
16543 
16544  }
16545 
16546  // --- Uniform Classes ---
16547 
16548  function SingleUniform( id, activeInfo, addr ) {
16549 
16550  this.id = id;
16551  this.addr = addr;
16552  this.cache = [];
16553  this.setValue = getSingularSetter( activeInfo.type );
16554 
16555  // this.path = activeInfo.name; // DEBUG
16556 
16557  }
16558 
16559  function PureArrayUniform( id, activeInfo, addr ) {
16560 
16561  this.id = id;
16562  this.addr = addr;
16563  this.cache = [];
16564  this.size = activeInfo.size;
16565  this.setValue = getPureArraySetter( activeInfo.type );
16566 
16567  // this.path = activeInfo.name; // DEBUG
16568 
16569  }
16570 
16571  PureArrayUniform.prototype.updateCache = function ( data ) {
16572 
16573  var cache = this.cache;
16574 
16575  if ( data instanceof Float32Array && cache.length !== data.length ) {
16576 
16577  this.cache = new Float32Array( data.length );
16578 
16579  }
16580 
16581  copyArray( cache, data );
16582 
16583  };
16584 
16585  function StructuredUniform( id ) {
16586 
16587  this.id = id;
16588 
16589  UniformContainer.call( this ); // mix-in
16590 
16591  }
16592 
16593  StructuredUniform.prototype.setValue = function ( gl, value, renderer ) {
16594 
16595  var seq = this.seq;
16596 
16597  for ( var i = 0, n = seq.length; i !== n; ++ i ) {
16598 
16599  var u = seq[ i ];
16600  u.setValue( gl, value[ u.id ], renderer );
16601 
16602  }
16603 
16604  };
16605 
16606  // --- Top-level ---
16607 
16608  // Parser - builds up the property tree from the path strings
16609 
16610  var RePathPart = /([\w\d_]+)(\])?(\[|\.)?/g;
16611 
16612  // extracts
16613  // - the identifier (member name or array index)
16614  // - followed by an optional right bracket (found when array index)
16615  // - followed by an optional left bracket or dot (type of subscript)
16616  //
16617  // Note: These portions can be read in a non-overlapping fashion and
16618  // allow straightforward parsing of the hierarchy that WebGL encodes
16619  // in the uniform names.
16620 
16621  function addUniform( container, uniformObject ) {
16622 
16623  container.seq.push( uniformObject );
16624  container.map[ uniformObject.id ] = uniformObject;
16625 
16626  }
16627 
16628  function parseUniform( activeInfo, addr, container ) {
16629 
16630  var path = activeInfo.name,
16631  pathLength = path.length;
16632 
16633  // reset RegExp object, because of the early exit of a previous run
16634  RePathPart.lastIndex = 0;
16635 
16636  while ( true ) {
16637 
16638  var match = RePathPart.exec( path ),
16639  matchEnd = RePathPart.lastIndex,
16640 
16641  id = match[ 1 ],
16642  idIsIndex = match[ 2 ] === ']',
16643  subscript = match[ 3 ];
16644 
16645  if ( idIsIndex ) id = id | 0; // convert to integer
16646 
16647  if ( subscript === undefined || subscript === '[' && matchEnd + 2 === pathLength ) {
16648 
16649  // bare name or "pure" bottom-level array "[0]" suffix
16650 
16651  addUniform( container, subscript === undefined ?
16652  new SingleUniform( id, activeInfo, addr ) :
16653  new PureArrayUniform( id, activeInfo, addr ) );
16654 
16655  break;
16656 
16657  } else {
16658 
16659  // step into inner node / create it in case it doesn't exist
16660 
16661  var map = container.map, next = map[ id ];
16662 
16663  if ( next === undefined ) {
16664 
16665  next = new StructuredUniform( id );
16666  addUniform( container, next );
16667 
16668  }
16669 
16670  container = next;
16671 
16672  }
16673 
16674  }
16675 
16676  }
16677 
16678  // Root Container
16679 
16680  function WebGLUniforms( gl, program, renderer ) {
16681 
16682  UniformContainer.call( this );
16683 
16684  this.renderer = renderer;
16685 
16686  var n = gl.getProgramParameter( program, 35718 );
16687 
16688  for ( var i = 0; i < n; ++ i ) {
16689 
16690  var info = gl.getActiveUniform( program, i ),
16691  addr = gl.getUniformLocation( program, info.name );
16692 
16693  parseUniform( info, addr, this );
16694 
16695  }
16696 
16697  }
16698 
16699  WebGLUniforms.prototype.setValue = function ( gl, name, value ) {
16700 
16701  var u = this.map[ name ];
16702 
16703  if ( u !== undefined ) u.setValue( gl, value, this.renderer );
16704 
16705  };
16706 
16707  WebGLUniforms.prototype.setOptional = function ( gl, object, name ) {
16708 
16709  var v = object[ name ];
16710 
16711  if ( v !== undefined ) this.setValue( gl, name, v );
16712 
16713  };
16714 
16715 
16716  // Static interface
16717 
16718  WebGLUniforms.upload = function ( gl, seq, values, renderer ) {
16719 
16720  for ( var i = 0, n = seq.length; i !== n; ++ i ) {
16721 
16722  var u = seq[ i ],
16723  v = values[ u.id ];
16724 
16725  if ( v.needsUpdate !== false ) {
16726 
16727  // note: always updating when .needsUpdate is undefined
16728  u.setValue( gl, v.value, renderer );
16729 
16730  }
16731 
16732  }
16733 
16734  };
16735 
16736  WebGLUniforms.seqWithValue = function ( seq, values ) {
16737 
16738  var r = [];
16739 
16740  for ( var i = 0, n = seq.length; i !== n; ++ i ) {
16741 
16742  var u = seq[ i ];
16743  if ( u.id in values ) r.push( u );
16744 
16745  }
16746 
16747  return r;
16748 
16749  };
16750 
16755  function addLineNumbers( string ) {
16756 
16757  var lines = string.split( '\n' );
16758 
16759  for ( var i = 0; i < lines.length; i ++ ) {
16760 
16761  lines[ i ] = ( i + 1 ) + ': ' + lines[ i ];
16762 
16763  }
16764 
16765  return lines.join( '\n' );
16766 
16767  }
16768 
16769  function WebGLShader( gl, type, string ) {
16770 
16771  var shader = gl.createShader( type );
16772 
16773  gl.shaderSource( shader, string );
16774  gl.compileShader( shader );
16775 
16776  if ( gl.getShaderParameter( shader, 35713 ) === false ) {
16777 
16778  console.error( 'THREE.WebGLShader: Shader couldn\'t compile.' );
16779 
16780  }
16781 
16782  if ( gl.getShaderInfoLog( shader ) !== '' ) {
16783 
16784  console.warn( 'THREE.WebGLShader: gl.getShaderInfoLog()', type === 35633 ? 'vertex' : 'fragment', gl.getShaderInfoLog( shader ), addLineNumbers( string ) );
16785 
16786  }
16787 
16788  // --enable-privileged-webgl-extension
16789  // console.log( type, gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) );
16790 
16791  return shader;
16792 
16793  }
16794 
16799  var programIdCount = 0;
16800 
16801  function getEncodingComponents( encoding ) {
16802 
16803  switch ( encoding ) {
16804 
16805  case LinearEncoding:
16806  return [ 'Linear', '( value )' ];
16807  case sRGBEncoding:
16808  return [ 'sRGB', '( value )' ];
16809  case RGBEEncoding:
16810  return [ 'RGBE', '( value )' ];
16811  case RGBM7Encoding:
16812  return [ 'RGBM', '( value, 7.0 )' ];
16813  case RGBM16Encoding:
16814  return [ 'RGBM', '( value, 16.0 )' ];
16815  case RGBDEncoding:
16816  return [ 'RGBD', '( value, 256.0 )' ];
16817  case GammaEncoding:
16818  return [ 'Gamma', '( value, float( GAMMA_FACTOR ) )' ];
16819  default:
16820  throw new Error( 'unsupported encoding: ' + encoding );
16821 
16822  }
16823 
16824  }
16825 
16826  function getTexelDecodingFunction( functionName, encoding ) {
16827 
16828  var components = getEncodingComponents( encoding );
16829  return 'vec4 ' + functionName + '( vec4 value ) { return ' + components[ 0 ] + 'ToLinear' + components[ 1 ] + '; }';
16830 
16831  }
16832 
16833  function getTexelEncodingFunction( functionName, encoding ) {
16834 
16835  var components = getEncodingComponents( encoding );
16836  return 'vec4 ' + functionName + '( vec4 value ) { return LinearTo' + components[ 0 ] + components[ 1 ] + '; }';
16837 
16838  }
16839 
16840  function getToneMappingFunction( functionName, toneMapping ) {
16841 
16842  var toneMappingName;
16843 
16844  switch ( toneMapping ) {
16845 
16846  case LinearToneMapping:
16847  toneMappingName = 'Linear';
16848  break;
16849 
16850  case ReinhardToneMapping:
16851  toneMappingName = 'Reinhard';
16852  break;
16853 
16854  case Uncharted2ToneMapping:
16855  toneMappingName = 'Uncharted2';
16856  break;
16857 
16858  case CineonToneMapping:
16859  toneMappingName = 'OptimizedCineon';
16860  break;
16861 
16862  case ACESFilmicToneMapping:
16863  toneMappingName = 'ACESFilmic';
16864  break;
16865 
16866  default:
16867  throw new Error( 'unsupported toneMapping: ' + toneMapping );
16868 
16869  }
16870 
16871  return 'vec3 ' + functionName + '( vec3 color ) { return ' + toneMappingName + 'ToneMapping( color ); }';
16872 
16873  }
16874 
16875  function generateExtensions( extensions, parameters, rendererExtensions ) {
16876 
16877  extensions = extensions || {};
16878 
16879  var chunks = [
16880  ( extensions.derivatives || parameters.envMapCubeUV || parameters.bumpMap || ( parameters.normalMap && ! parameters.objectSpaceNormalMap ) || parameters.flatShading ) ? '#extension GL_OES_standard_derivatives : enable' : '',
16881  ( extensions.fragDepth || parameters.logarithmicDepthBuffer ) && rendererExtensions.get( 'EXT_frag_depth' ) ? '#extension GL_EXT_frag_depth : enable' : '',
16882  ( extensions.drawBuffers ) && rendererExtensions.get( 'WEBGL_draw_buffers' ) ? '#extension GL_EXT_draw_buffers : require' : '',
16883  ( extensions.shaderTextureLOD || parameters.envMap ) && rendererExtensions.get( 'EXT_shader_texture_lod' ) ? '#extension GL_EXT_shader_texture_lod : enable' : ''
16884  ];
16885 
16886  return chunks.filter( filterEmptyLine ).join( '\n' );
16887 
16888  }
16889 
16890  function generateDefines( defines ) {
16891 
16892  var chunks = [];
16893 
16894  for ( var name in defines ) {
16895 
16896  var value = defines[ name ];
16897 
16898  if ( value === false ) continue;
16899 
16900  chunks.push( '#define ' + name + ' ' + value );
16901 
16902  }
16903 
16904  return chunks.join( '\n' );
16905 
16906  }
16907 
16908  function fetchAttributeLocations( gl, program ) {
16909 
16910  var attributes = {};
16911 
16912  var n = gl.getProgramParameter( program, 35721 );
16913 
16914  for ( var i = 0; i < n; i ++ ) {
16915 
16916  var info = gl.getActiveAttrib( program, i );
16917  var name = info.name;
16918 
16919  // console.log( 'THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:', name, i );
16920 
16921  attributes[ name ] = gl.getAttribLocation( program, name );
16922 
16923  }
16924 
16925  return attributes;
16926 
16927  }
16928 
16929  function filterEmptyLine( string ) {
16930 
16931  return string !== '';
16932 
16933  }
16934 
16935  function replaceLightNums( string, parameters ) {
16936 
16937  return string
16938  .replace( /NUM_DIR_LIGHTS/g, parameters.numDirLights )
16939  .replace( /NUM_SPOT_LIGHTS/g, parameters.numSpotLights )
16940  .replace( /NUM_RECT_AREA_LIGHTS/g, parameters.numRectAreaLights )
16941  .replace( /NUM_POINT_LIGHTS/g, parameters.numPointLights )
16942  .replace( /NUM_HEMI_LIGHTS/g, parameters.numHemiLights );
16943 
16944  }
16945 
16946  function replaceClippingPlaneNums( string, parameters ) {
16947 
16948  return string
16949  .replace( /NUM_CLIPPING_PLANES/g, parameters.numClippingPlanes )
16950  .replace( /UNION_CLIPPING_PLANES/g, ( parameters.numClippingPlanes - parameters.numClipIntersection ) );
16951 
16952  }
16953 
16954  function parseIncludes( string ) {
16955 
16956  var pattern = /^[ \t]*#include +<([\w\d./]+)>/gm;
16957 
16958  function replace( match, include ) {
16959 
16960  var replace = ShaderChunk[ include ];
16961 
16962  if ( replace === undefined ) {
16963 
16964  throw new Error( 'Can not resolve #include <' + include + '>' );
16965 
16966  }
16967 
16968  return parseIncludes( replace );
16969 
16970  }
16971 
16972  return string.replace( pattern, replace );
16973 
16974  }
16975 
16976  function unrollLoops( string ) {
16977 
16978  var pattern = /#pragma unroll_loop[\s]+?for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g;
16979 
16980  function replace( match, start, end, snippet ) {
16981 
16982  var unroll = '';
16983 
16984  for ( var i = parseInt( start ); i < parseInt( end ); i ++ ) {
16985 
16986  unroll += snippet.replace( /\[ i \]/g, '[ ' + i + ' ]' );
16987 
16988  }
16989 
16990  return unroll;
16991 
16992  }
16993 
16994  return string.replace( pattern, replace );
16995 
16996  }
16997 
16998  function WebGLProgram( renderer, extensions, code, material, shader, parameters, capabilities ) {
16999 
17000  var gl = renderer.context;
17001 
17002  var defines = material.defines;
17003 
17004  var vertexShader = shader.vertexShader;
17005  var fragmentShader = shader.fragmentShader;
17006 
17007  var shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC';
17008 
17009  if ( parameters.shadowMapType === PCFShadowMap ) {
17010 
17011  shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF';
17012 
17013  } else if ( parameters.shadowMapType === PCFSoftShadowMap ) {
17014 
17015  shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT';
17016 
17017  }
17018 
17019  var envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
17020  var envMapModeDefine = 'ENVMAP_MODE_REFLECTION';
17021  var envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
17022 
17023  if ( parameters.envMap ) {
17024 
17025  switch ( material.envMap.mapping ) {
17026 
17027  case CubeReflectionMapping:
17028  case CubeRefractionMapping:
17029  envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
17030  break;
17031 
17032  case CubeUVReflectionMapping:
17033  case CubeUVRefractionMapping:
17034  envMapTypeDefine = 'ENVMAP_TYPE_CUBE_UV';
17035  break;
17036 
17037  case EquirectangularReflectionMapping:
17038  case EquirectangularRefractionMapping:
17039  envMapTypeDefine = 'ENVMAP_TYPE_EQUIREC';
17040  break;
17041 
17042  case SphericalReflectionMapping:
17043  envMapTypeDefine = 'ENVMAP_TYPE_SPHERE';
17044  break;
17045 
17046  }
17047 
17048  switch ( material.envMap.mapping ) {
17049 
17050  case CubeRefractionMapping:
17051  case EquirectangularRefractionMapping:
17052  envMapModeDefine = 'ENVMAP_MODE_REFRACTION';
17053  break;
17054 
17055  }
17056 
17057  switch ( material.combine ) {
17058 
17059  case MultiplyOperation:
17060  envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
17061  break;
17062 
17063  case MixOperation:
17064  envMapBlendingDefine = 'ENVMAP_BLENDING_MIX';
17065  break;
17066 
17067  case AddOperation:
17068  envMapBlendingDefine = 'ENVMAP_BLENDING_ADD';
17069  break;
17070 
17071  }
17072 
17073  }
17074 
17075  var gammaFactorDefine = ( renderer.gammaFactor > 0 ) ? renderer.gammaFactor : 1.0;
17076 
17077  // console.log( 'building new program ' );
17078 
17079  //
17080 
17081  var customExtensions = capabilities.isWebGL2 ? '' : generateExtensions( material.extensions, parameters, extensions );
17082 
17083  var customDefines = generateDefines( defines );
17084 
17085  //
17086 
17087  var program = gl.createProgram();
17088 
17089  var prefixVertex, prefixFragment;
17090 
17091  if ( material.isRawShaderMaterial ) {
17092 
17093  prefixVertex = [
17094 
17095  customDefines
17096 
17097  ].filter( filterEmptyLine ).join( '\n' );
17098 
17099  if ( prefixVertex.length > 0 ) {
17100 
17101  prefixVertex += '\n';
17102 
17103  }
17104 
17105  prefixFragment = [
17106 
17107  customExtensions,
17108  customDefines
17109 
17110  ].filter( filterEmptyLine ).join( '\n' );
17111 
17112  if ( prefixFragment.length > 0 ) {
17113 
17114  prefixFragment += '\n';
17115 
17116  }
17117 
17118  } else {
17119 
17120  prefixVertex = [
17121 
17122  'precision ' + parameters.precision + ' float;',
17123  'precision ' + parameters.precision + ' int;',
17124 
17125  '#define SHADER_NAME ' + shader.name,
17126 
17127  customDefines,
17128 
17129  parameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '',
17130 
17131  '#define GAMMA_FACTOR ' + gammaFactorDefine,
17132 
17133  '#define MAX_BONES ' + parameters.maxBones,
17134  ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',
17135  ( parameters.useFog && parameters.fogExp ) ? '#define FOG_EXP2' : '',
17136 
17137  parameters.map ? '#define USE_MAP' : '',
17138  parameters.envMap ? '#define USE_ENVMAP' : '',
17139  parameters.envMap ? '#define ' + envMapModeDefine : '',
17140  parameters.lightMap ? '#define USE_LIGHTMAP' : '',
17141  parameters.aoMap ? '#define USE_AOMAP' : '',
17142  parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
17143  parameters.bumpMap ? '#define USE_BUMPMAP' : '',
17144  parameters.normalMap ? '#define USE_NORMALMAP' : '',
17145  ( parameters.normalMap && parameters.objectSpaceNormalMap ) ? '#define OBJECTSPACE_NORMALMAP' : '',
17146  parameters.displacementMap && parameters.supportsVertexTextures ? '#define USE_DISPLACEMENTMAP' : '',
17147  parameters.specularMap ? '#define USE_SPECULARMAP' : '',
17148  parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
17149  parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
17150  parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
17151 
17152  parameters.vertexTangents ? '#define USE_TANGENT' : '',
17153  parameters.vertexColors ? '#define USE_COLOR' : '',
17154 
17155  parameters.flatShading ? '#define FLAT_SHADED' : '',
17156 
17157  parameters.skinning ? '#define USE_SKINNING' : '',
17158  parameters.useVertexTexture ? '#define BONE_TEXTURE' : '',
17159 
17160  parameters.morphTargets ? '#define USE_MORPHTARGETS' : '',
17161  parameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '',
17162  parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
17163  parameters.flipSided ? '#define FLIP_SIDED' : '',
17164 
17165  parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
17166  parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
17167 
17168  parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '',
17169 
17170  parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
17171  parameters.logarithmicDepthBuffer && ( capabilities.isWebGL2 || extensions.get( 'EXT_frag_depth' ) ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
17172 
17173  'uniform mat4 modelMatrix;',
17174  'uniform mat4 modelViewMatrix;',
17175  'uniform mat4 projectionMatrix;',
17176  'uniform mat4 viewMatrix;',
17177  'uniform mat3 normalMatrix;',
17178  'uniform vec3 cameraPosition;',
17179 
17180  'attribute vec3 position;',
17181  'attribute vec3 normal;',
17182  'attribute vec2 uv;',
17183 
17184  '#ifdef USE_TANGENT',
17185 
17186  ' attribute vec4 tangent;',
17187 
17188  '#endif',
17189 
17190  '#ifdef USE_COLOR',
17191 
17192  ' attribute vec3 color;',
17193 
17194  '#endif',
17195 
17196  '#ifdef USE_MORPHTARGETS',
17197 
17198  ' attribute vec3 morphTarget0;',
17199  ' attribute vec3 morphTarget1;',
17200  ' attribute vec3 morphTarget2;',
17201  ' attribute vec3 morphTarget3;',
17202 
17203  ' #ifdef USE_MORPHNORMALS',
17204 
17205  ' attribute vec3 morphNormal0;',
17206  ' attribute vec3 morphNormal1;',
17207  ' attribute vec3 morphNormal2;',
17208  ' attribute vec3 morphNormal3;',
17209 
17210  ' #else',
17211 
17212  ' attribute vec3 morphTarget4;',
17213  ' attribute vec3 morphTarget5;',
17214  ' attribute vec3 morphTarget6;',
17215  ' attribute vec3 morphTarget7;',
17216 
17217  ' #endif',
17218 
17219  '#endif',
17220 
17221  '#ifdef USE_SKINNING',
17222 
17223  ' attribute vec4 skinIndex;',
17224  ' attribute vec4 skinWeight;',
17225 
17226  '#endif',
17227 
17228  '\n'
17229 
17230  ].filter( filterEmptyLine ).join( '\n' );
17231 
17232  prefixFragment = [
17233 
17234  customExtensions,
17235 
17236  'precision ' + parameters.precision + ' float;',
17237  'precision ' + parameters.precision + ' int;',
17238 
17239  '#define SHADER_NAME ' + shader.name,
17240 
17241  customDefines,
17242 
17243  parameters.alphaTest ? '#define ALPHATEST ' + parameters.alphaTest + ( parameters.alphaTest % 1 ? '' : '.0' ) : '', // add '.0' if integer
17244 
17245  '#define GAMMA_FACTOR ' + gammaFactorDefine,
17246 
17247  ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',
17248  ( parameters.useFog && parameters.fogExp ) ? '#define FOG_EXP2' : '',
17249 
17250  parameters.map ? '#define USE_MAP' : '',
17251  parameters.matcap ? '#define USE_MATCAP' : '',
17252  parameters.envMap ? '#define USE_ENVMAP' : '',
17253  parameters.envMap ? '#define ' + envMapTypeDefine : '',
17254  parameters.envMap ? '#define ' + envMapModeDefine : '',
17255  parameters.envMap ? '#define ' + envMapBlendingDefine : '',
17256  parameters.lightMap ? '#define USE_LIGHTMAP' : '',
17257  parameters.aoMap ? '#define USE_AOMAP' : '',
17258  parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
17259  parameters.bumpMap ? '#define USE_BUMPMAP' : '',
17260  parameters.normalMap ? '#define USE_NORMALMAP' : '',
17261  ( parameters.normalMap && parameters.objectSpaceNormalMap ) ? '#define OBJECTSPACE_NORMALMAP' : '',
17262  parameters.specularMap ? '#define USE_SPECULARMAP' : '',
17263  parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
17264  parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
17265  parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
17266 
17267  parameters.vertexTangents ? '#define USE_TANGENT' : '',
17268  parameters.vertexColors ? '#define USE_COLOR' : '',
17269 
17270  parameters.gradientMap ? '#define USE_GRADIENTMAP' : '',
17271 
17272  parameters.flatShading ? '#define FLAT_SHADED' : '',
17273 
17274  parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
17275  parameters.flipSided ? '#define FLIP_SIDED' : '',
17276 
17277  parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
17278  parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
17279 
17280  parameters.premultipliedAlpha ? '#define PREMULTIPLIED_ALPHA' : '',
17281 
17282  parameters.physicallyCorrectLights ? '#define PHYSICALLY_CORRECT_LIGHTS' : '',
17283 
17284  parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
17285  parameters.logarithmicDepthBuffer && ( capabilities.isWebGL2 || extensions.get( 'EXT_frag_depth' ) ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
17286 
17287  parameters.envMap && ( capabilities.isWebGL2 || extensions.get( 'EXT_shader_texture_lod' ) ) ? '#define TEXTURE_LOD_EXT' : '',
17288 
17289  'uniform mat4 viewMatrix;',
17290  'uniform vec3 cameraPosition;',
17291 
17292  ( parameters.toneMapping !== NoToneMapping ) ? '#define TONE_MAPPING' : '',
17293  ( parameters.toneMapping !== NoToneMapping ) ? ShaderChunk[ 'tonemapping_pars_fragment' ] : '', // this code is required here because it is used by the toneMapping() function defined below
17294  ( parameters.toneMapping !== NoToneMapping ) ? getToneMappingFunction( 'toneMapping', parameters.toneMapping ) : '',
17295 
17296  parameters.dithering ? '#define DITHERING' : '',
17297 
17298  ( parameters.outputEncoding || parameters.mapEncoding || parameters.matcapEncoding || parameters.envMapEncoding || parameters.emissiveMapEncoding ) ?
17299  ShaderChunk[ 'encodings_pars_fragment' ] : '', // this code is required here because it is used by the various encoding/decoding function defined below
17300  parameters.mapEncoding ? getTexelDecodingFunction( 'mapTexelToLinear', parameters.mapEncoding ) : '',
17301  parameters.matcapEncoding ? getTexelDecodingFunction( 'matcapTexelToLinear', parameters.matcapEncoding ) : '',
17302  parameters.envMapEncoding ? getTexelDecodingFunction( 'envMapTexelToLinear', parameters.envMapEncoding ) : '',
17303  parameters.emissiveMapEncoding ? getTexelDecodingFunction( 'emissiveMapTexelToLinear', parameters.emissiveMapEncoding ) : '',
17304  parameters.outputEncoding ? getTexelEncodingFunction( 'linearToOutputTexel', parameters.outputEncoding ) : '',
17305 
17306  parameters.depthPacking ? '#define DEPTH_PACKING ' + material.depthPacking : '',
17307 
17308  '\n'
17309 
17310  ].filter( filterEmptyLine ).join( '\n' );
17311 
17312  }
17313 
17314  vertexShader = parseIncludes( vertexShader );
17315  vertexShader = replaceLightNums( vertexShader, parameters );
17316  vertexShader = replaceClippingPlaneNums( vertexShader, parameters );
17317 
17318  fragmentShader = parseIncludes( fragmentShader );
17319  fragmentShader = replaceLightNums( fragmentShader, parameters );
17320  fragmentShader = replaceClippingPlaneNums( fragmentShader, parameters );
17321 
17322  vertexShader = unrollLoops( vertexShader );
17323  fragmentShader = unrollLoops( fragmentShader );
17324 
17325  if ( capabilities.isWebGL2 && ! material.isRawShaderMaterial ) {
17326 
17327  var isGLSL3ShaderMaterial = false;
17328 
17329  var versionRegex = /^\s*#version\s+300\s+es\s*\n/;
17330 
17331  if ( material.isShaderMaterial &&
17332  vertexShader.match( versionRegex ) !== null &&
17333  fragmentShader.match( versionRegex ) !== null ) {
17334 
17335  isGLSL3ShaderMaterial = true;
17336 
17337  vertexShader = vertexShader.replace( versionRegex, '' );
17338  fragmentShader = fragmentShader.replace( versionRegex, '' );
17339 
17340  }
17341 
17342  // GLSL 3.0 conversion
17343  prefixVertex = [
17344  '#version 300 es\n',
17345  '#define attribute in',
17346  '#define varying out',
17347  '#define texture2D texture'
17348  ].join( '\n' ) + '\n' + prefixVertex;
17349 
17350  prefixFragment = [
17351  '#version 300 es\n',
17352  '#define varying in',
17353  isGLSL3ShaderMaterial ? '' : 'out highp vec4 pc_fragColor;',
17354  isGLSL3ShaderMaterial ? '' : '#define gl_FragColor pc_fragColor',
17355  '#define gl_FragDepthEXT gl_FragDepth',
17356  '#define texture2D texture',
17357  '#define textureCube texture',
17358  '#define texture2DProj textureProj',
17359  '#define texture2DLodEXT textureLod',
17360  '#define texture2DProjLodEXT textureProjLod',
17361  '#define textureCubeLodEXT textureLod',
17362  '#define texture2DGradEXT textureGrad',
17363  '#define texture2DProjGradEXT textureProjGrad',
17364  '#define textureCubeGradEXT textureGrad'
17365  ].join( '\n' ) + '\n' + prefixFragment;
17366 
17367  }
17368 
17369  var vertexGlsl = prefixVertex + vertexShader;
17370  var fragmentGlsl = prefixFragment + fragmentShader;
17371 
17372  // console.log( '*VERTEX*', vertexGlsl );
17373  // console.log( '*FRAGMENT*', fragmentGlsl );
17374 
17375  var glVertexShader = WebGLShader( gl, 35633, vertexGlsl );
17376  var glFragmentShader = WebGLShader( gl, 35632, fragmentGlsl );
17377 
17378  gl.attachShader( program, glVertexShader );
17379  gl.attachShader( program, glFragmentShader );
17380 
17381  // Force a particular attribute to index 0.
17382 
17383  if ( material.index0AttributeName !== undefined ) {
17384 
17385  gl.bindAttribLocation( program, 0, material.index0AttributeName );
17386 
17387  } else if ( parameters.morphTargets === true ) {
17388 
17389  // programs with morphTargets displace position out of attribute 0
17390  gl.bindAttribLocation( program, 0, 'position' );
17391 
17392  }
17393 
17394  gl.linkProgram( program );
17395 
17396  var programLog = gl.getProgramInfoLog( program ).trim();
17397  var vertexLog = gl.getShaderInfoLog( glVertexShader ).trim();
17398  var fragmentLog = gl.getShaderInfoLog( glFragmentShader ).trim();
17399 
17400  var runnable = true;
17401  var haveDiagnostics = true;
17402 
17403  // console.log( '**VERTEX**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( glVertexShader ) );
17404  // console.log( '**FRAGMENT**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( glFragmentShader ) );
17405 
17406  if ( gl.getProgramParameter( program, 35714 ) === false ) {
17407 
17408  runnable = false;
17409 
17410  console.error( 'THREE.WebGLProgram: shader error: ', gl.getError(), '35715', gl.getProgramParameter( program, 35715 ), 'gl.getProgramInfoLog', programLog, vertexLog, fragmentLog );
17411 
17412  } else if ( programLog !== '' ) {
17413 
17414  console.warn( 'THREE.WebGLProgram: gl.getProgramInfoLog()', programLog );
17415 
17416  } else if ( vertexLog === '' || fragmentLog === '' ) {
17417 
17418  haveDiagnostics = false;
17419 
17420  }
17421 
17422  if ( haveDiagnostics ) {
17423 
17424  this.diagnostics = {
17425 
17426  runnable: runnable,
17427  material: material,
17428 
17429  programLog: programLog,
17430 
17431  vertexShader: {
17432 
17433  log: vertexLog,
17434  prefix: prefixVertex
17435 
17436  },
17437 
17438  fragmentShader: {
17439 
17440  log: fragmentLog,
17441  prefix: prefixFragment
17442 
17443  }
17444 
17445  };
17446 
17447  }
17448 
17449  // clean up
17450 
17451  gl.deleteShader( glVertexShader );
17452  gl.deleteShader( glFragmentShader );
17453 
17454  // set up caching for uniform locations
17455 
17456  var cachedUniforms;
17457 
17458  this.getUniforms = function () {
17459 
17460  if ( cachedUniforms === undefined ) {
17461 
17462  cachedUniforms = new WebGLUniforms( gl, program, renderer );
17463 
17464  }
17465 
17466  return cachedUniforms;
17467 
17468  };
17469 
17470  // set up caching for attribute locations
17471 
17472  var cachedAttributes;
17473 
17474  this.getAttributes = function () {
17475 
17476  if ( cachedAttributes === undefined ) {
17477 
17478  cachedAttributes = fetchAttributeLocations( gl, program );
17479 
17480  }
17481 
17482  return cachedAttributes;
17483 
17484  };
17485 
17486  // free resource
17487 
17488  this.destroy = function () {
17489 
17490  gl.deleteProgram( program );
17491  this.program = undefined;
17492 
17493  };
17494 
17495  // DEPRECATED
17496 
17497  Object.defineProperties( this, {
17498 
17499  uniforms: {
17500  get: function () {
17501 
17502  console.warn( 'THREE.WebGLProgram: .uniforms is now .getUniforms().' );
17503  return this.getUniforms();
17504 
17505  }
17506  },
17507 
17508  attributes: {
17509  get: function () {
17510 
17511  console.warn( 'THREE.WebGLProgram: .attributes is now .getAttributes().' );
17512  return this.getAttributes();
17513 
17514  }
17515  }
17516 
17517  } );
17518 
17519 
17520  //
17521 
17522  this.name = shader.name;
17523  this.id = programIdCount ++;
17524  this.code = code;
17525  this.usedTimes = 1;
17526  this.program = program;
17527  this.vertexShader = glVertexShader;
17528  this.fragmentShader = glFragmentShader;
17529 
17530  return this;
17531 
17532  }
17533 
17538  function WebGLPrograms( renderer, extensions, capabilities ) {
17539 
17540  var programs = [];
17541 
17542  var shaderIDs = {
17543  MeshDepthMaterial: 'depth',
17544  MeshDistanceMaterial: 'distanceRGBA',
17545  MeshNormalMaterial: 'normal',
17546  MeshBasicMaterial: 'basic',
17547  MeshLambertMaterial: 'lambert',
17548  MeshPhongMaterial: 'phong',
17549  MeshToonMaterial: 'phong',
17550  MeshStandardMaterial: 'physical',
17551  MeshPhysicalMaterial: 'physical',
17552  MeshMatcapMaterial: 'matcap',
17553  LineBasicMaterial: 'basic',
17554  LineDashedMaterial: 'dashed',
17555  PointsMaterial: 'points',
17556  ShadowMaterial: 'shadow',
17557  SpriteMaterial: 'sprite'
17558  };
17559 
17560  var parameterNames = [
17561  "precision", "supportsVertexTextures", "map", "mapEncoding", "matcap", "matcapEncoding", "envMap", "envMapMode", "envMapEncoding",
17562  "lightMap", "aoMap", "emissiveMap", "emissiveMapEncoding", "bumpMap", "normalMap", "objectSpaceNormalMap", "displacementMap", "specularMap",
17563  "roughnessMap", "metalnessMap", "gradientMap",
17564  "alphaMap", "combine", "vertexColors", "vertexTangents", "fog", "useFog", "fogExp",
17565  "flatShading", "sizeAttenuation", "logarithmicDepthBuffer", "skinning",
17566  "maxBones", "useVertexTexture", "morphTargets", "morphNormals",
17567  "maxMorphTargets", "maxMorphNormals", "premultipliedAlpha",
17568  "numDirLights", "numPointLights", "numSpotLights", "numHemiLights", "numRectAreaLights",
17569  "shadowMapEnabled", "shadowMapType", "toneMapping", 'physicallyCorrectLights',
17570  "alphaTest", "doubleSided", "flipSided", "numClippingPlanes", "numClipIntersection", "depthPacking", "dithering"
17571  ];
17572 
17573 
17574  function allocateBones( object ) {
17575 
17576  var skeleton = object.skeleton;
17577  var bones = skeleton.bones;
17578 
17579  if ( capabilities.floatVertexTextures ) {
17580 
17581  return 1024;
17582 
17583  } else {
17584 
17585  // default for when object is not specified
17586  // ( for example when prebuilding shader to be used with multiple objects )
17587  //
17588  // - leave some extra space for other uniforms
17589  // - limit here is ANGLE's 254 max uniform vectors
17590  // (up to 54 should be safe)
17591 
17592  var nVertexUniforms = capabilities.maxVertexUniforms;
17593  var nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 );
17594 
17595  var maxBones = Math.min( nVertexMatrices, bones.length );
17596 
17597  if ( maxBones < bones.length ) {
17598 
17599  console.warn( 'THREE.WebGLRenderer: Skeleton has ' + bones.length + ' bones. This GPU supports ' + maxBones + '.' );
17600  return 0;
17601 
17602  }
17603 
17604  return maxBones;
17605 
17606  }
17607 
17608  }
17609 
17610  function getTextureEncodingFromMap( map, gammaOverrideLinear ) {
17611 
17612  var encoding;
17613 
17614  if ( ! map ) {
17615 
17616  encoding = LinearEncoding;
17617 
17618  } else if ( map.isTexture ) {
17619 
17620  encoding = map.encoding;
17621 
17622  } else if ( map.isWebGLRenderTarget ) {
17623 
17624  console.warn( "THREE.WebGLPrograms.getTextureEncodingFromMap: don't use render targets as textures. Use their .texture property instead." );
17625  encoding = map.texture.encoding;
17626 
17627  }
17628 
17629  // add backwards compatibility for WebGLRenderer.gammaInput/gammaOutput parameter, should probably be removed at some point.
17630  if ( encoding === LinearEncoding && gammaOverrideLinear ) {
17631 
17632  encoding = GammaEncoding;
17633 
17634  }
17635 
17636  return encoding;
17637 
17638  }
17639 
17640  this.getParameters = function ( material, lights, shadows, fog, nClipPlanes, nClipIntersection, object ) {
17641 
17642  var shaderID = shaderIDs[ material.type ];
17643 
17644  // heuristics to create shader parameters according to lights in the scene
17645  // (not to blow over maxLights budget)
17646 
17647  var maxBones = object.isSkinnedMesh ? allocateBones( object ) : 0;
17648  var precision = capabilities.precision;
17649 
17650  if ( material.precision !== null ) {
17651 
17652  precision = capabilities.getMaxPrecision( material.precision );
17653 
17654  if ( precision !== material.precision ) {
17655 
17656  console.warn( 'THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.' );
17657 
17658  }
17659 
17660  }
17661 
17662  var currentRenderTarget = renderer.getRenderTarget();
17663 
17664  var parameters = {
17665 
17666  shaderID: shaderID,
17667 
17668  precision: precision,
17669  supportsVertexTextures: capabilities.vertexTextures,
17670  outputEncoding: getTextureEncodingFromMap( ( ! currentRenderTarget ) ? null : currentRenderTarget.texture, renderer.gammaOutput ),
17671  map: !! material.map,
17672  mapEncoding: getTextureEncodingFromMap( material.map, renderer.gammaInput ),
17673  matcap: !! material.matcap,
17674  matcapEncoding: getTextureEncodingFromMap( material.matcap, renderer.gammaInput ),
17675  envMap: !! material.envMap,
17676  envMapMode: material.envMap && material.envMap.mapping,
17677  envMapEncoding: getTextureEncodingFromMap( material.envMap, renderer.gammaInput ),
17678  envMapCubeUV: ( !! material.envMap ) && ( ( material.envMap.mapping === CubeUVReflectionMapping ) || ( material.envMap.mapping === CubeUVRefractionMapping ) ),
17679  lightMap: !! material.lightMap,
17680  aoMap: !! material.aoMap,
17681  emissiveMap: !! material.emissiveMap,
17682  emissiveMapEncoding: getTextureEncodingFromMap( material.emissiveMap, renderer.gammaInput ),
17683  bumpMap: !! material.bumpMap,
17684  normalMap: !! material.normalMap,
17685  objectSpaceNormalMap: material.normalMapType === ObjectSpaceNormalMap,
17686  displacementMap: !! material.displacementMap,
17687  roughnessMap: !! material.roughnessMap,
17688  metalnessMap: !! material.metalnessMap,
17689  specularMap: !! material.specularMap,
17690  alphaMap: !! material.alphaMap,
17691 
17692  gradientMap: !! material.gradientMap,
17693 
17694  combine: material.combine,
17695 
17696  vertexTangents: ( material.normalMap && material.vertexTangents ),
17697  vertexColors: material.vertexColors,
17698 
17699  fog: !! fog,
17700  useFog: material.fog,
17701  fogExp: ( fog && fog.isFogExp2 ),
17702 
17703  flatShading: material.flatShading,
17704 
17705  sizeAttenuation: material.sizeAttenuation,
17706  logarithmicDepthBuffer: capabilities.logarithmicDepthBuffer,
17707 
17708  skinning: material.skinning && maxBones > 0,
17709  maxBones: maxBones,
17710  useVertexTexture: capabilities.floatVertexTextures,
17711 
17712  morphTargets: material.morphTargets,
17713  morphNormals: material.morphNormals,
17714  maxMorphTargets: renderer.maxMorphTargets,
17715  maxMorphNormals: renderer.maxMorphNormals,
17716 
17717  numDirLights: lights.directional.length,
17718  numPointLights: lights.point.length,
17719  numSpotLights: lights.spot.length,
17720  numRectAreaLights: lights.rectArea.length,
17721  numHemiLights: lights.hemi.length,
17722 
17723  numClippingPlanes: nClipPlanes,
17724  numClipIntersection: nClipIntersection,
17725 
17726  dithering: material.dithering,
17727 
17728  shadowMapEnabled: renderer.shadowMap.enabled && object.receiveShadow && shadows.length > 0,
17729  shadowMapType: renderer.shadowMap.type,
17730 
17731  toneMapping: renderer.toneMapping,
17732  physicallyCorrectLights: renderer.physicallyCorrectLights,
17733 
17734  premultipliedAlpha: material.premultipliedAlpha,
17735 
17736  alphaTest: material.alphaTest,
17737  doubleSided: material.side === DoubleSide,
17738  flipSided: material.side === BackSide,
17739 
17740  depthPacking: ( material.depthPacking !== undefined ) ? material.depthPacking : false
17741 
17742  };
17743 
17744  return parameters;
17745 
17746  };
17747 
17748  this.getProgramCode = function ( material, parameters ) {
17749 
17750  var array = [];
17751 
17752  if ( parameters.shaderID ) {
17753 
17754  array.push( parameters.shaderID );
17755 
17756  } else {
17757 
17758  array.push( material.fragmentShader );
17759  array.push( material.vertexShader );
17760 
17761  }
17762 
17763  if ( material.defines !== undefined ) {
17764 
17765  for ( var name in material.defines ) {
17766 
17767  array.push( name );
17768  array.push( material.defines[ name ] );
17769 
17770  }
17771 
17772  }
17773 
17774  for ( var i = 0; i < parameterNames.length; i ++ ) {
17775 
17776  array.push( parameters[ parameterNames[ i ] ] );
17777 
17778  }
17779 
17780  array.push( material.onBeforeCompile.toString() );
17781 
17782  array.push( renderer.gammaOutput );
17783 
17784  array.push( renderer.gammaFactor );
17785 
17786  return array.join();
17787 
17788  };
17789 
17790  this.acquireProgram = function ( material, shader, parameters, code ) {
17791 
17792  var program;
17793 
17794  // Check if code has been already compiled
17795  for ( var p = 0, pl = programs.length; p < pl; p ++ ) {
17796 
17797  var programInfo = programs[ p ];
17798 
17799  if ( programInfo.code === code ) {
17800 
17801  program = programInfo;
17802  ++ program.usedTimes;
17803 
17804  break;
17805 
17806  }
17807 
17808  }
17809 
17810  if ( program === undefined ) {
17811 
17812  program = new WebGLProgram( renderer, extensions, code, material, shader, parameters, capabilities );
17813  programs.push( program );
17814 
17815  }
17816 
17817  return program;
17818 
17819  };
17820 
17821  this.releaseProgram = function ( program ) {
17822 
17823  if ( -- program.usedTimes === 0 ) {
17824 
17825  // Remove from unordered set
17826  var i = programs.indexOf( program );
17827  programs[ i ] = programs[ programs.length - 1 ];
17828  programs.pop();
17829 
17830  // Free WebGL resources
17831  program.destroy();
17832 
17833  }
17834 
17835  };
17836 
17837  // Exposed for resource monitoring & error feedback via renderer.info:
17838  this.programs = programs;
17839 
17840  }
17841 
17846  function WebGLProperties() {
17847 
17848  var properties = new WeakMap();
17849 
17850  function get( object ) {
17851 
17852  var map = properties.get( object );
17853 
17854  if ( map === undefined ) {
17855 
17856  map = {};
17857  properties.set( object, map );
17858 
17859  }
17860 
17861  return map;
17862 
17863  }
17864 
17865  function remove( object ) {
17866 
17867  properties.delete( object );
17868 
17869  }
17870 
17871  function update( object, key, value ) {
17872 
17873  properties.get( object )[ key ] = value;
17874 
17875  }
17876 
17877  function dispose() {
17878 
17879  properties = new WeakMap();
17880 
17881  }
17882 
17883  return {
17884  get: get,
17885  remove: remove,
17886  update: update,
17887  dispose: dispose
17888  };
17889 
17890  }
17891 
17896  function painterSortStable( a, b ) {
17897 
17898  if ( a.groupOrder !== b.groupOrder ) {
17899 
17900  return a.groupOrder - b.groupOrder;
17901 
17902  } else if ( a.renderOrder !== b.renderOrder ) {
17903 
17904  return a.renderOrder - b.renderOrder;
17905 
17906  } else if ( a.program && b.program && a.program !== b.program ) {
17907 
17908  return a.program.id - b.program.id;
17909 
17910  } else if ( a.material.id !== b.material.id ) {
17911 
17912  return a.material.id - b.material.id;
17913 
17914  } else if ( a.z !== b.z ) {
17915 
17916  return a.z - b.z;
17917 
17918  } else {
17919 
17920  return a.id - b.id;
17921 
17922  }
17923 
17924  }
17925 
17926  function reversePainterSortStable( a, b ) {
17927 
17928  if ( a.groupOrder !== b.groupOrder ) {
17929 
17930  return a.groupOrder - b.groupOrder;
17931 
17932  } else if ( a.renderOrder !== b.renderOrder ) {
17933 
17934  return a.renderOrder - b.renderOrder;
17935 
17936  } else if ( a.z !== b.z ) {
17937 
17938  return b.z - a.z;
17939 
17940  } else {
17941 
17942  return a.id - b.id;
17943 
17944  }
17945 
17946  }
17947 
17948 
17949  function WebGLRenderList() {
17950 
17951  var renderItems = [];
17952  var renderItemsIndex = 0;
17953 
17954  var opaque = [];
17955  var transparent = [];
17956 
17957  function init() {
17958 
17959  renderItemsIndex = 0;
17960 
17961  opaque.length = 0;
17962  transparent.length = 0;
17963 
17964  }
17965 
17966  function getNextRenderItem( object, geometry, material, groupOrder, z, group ) {
17967 
17968  var renderItem = renderItems[ renderItemsIndex ];
17969 
17970  if ( renderItem === undefined ) {
17971 
17972  renderItem = {
17973  id: object.id,
17974  object: object,
17975  geometry: geometry,
17976  material: material,
17977  program: material.program,
17978  groupOrder: groupOrder,
17979  renderOrder: object.renderOrder,
17980  z: z,
17981  group: group
17982  };
17983 
17984  renderItems[ renderItemsIndex ] = renderItem;
17985 
17986  } else {
17987 
17988  renderItem.id = object.id;
17989  renderItem.object = object;
17990  renderItem.geometry = geometry;
17991  renderItem.material = material;
17992  renderItem.program = material.program;
17993  renderItem.groupOrder = groupOrder;
17994  renderItem.renderOrder = object.renderOrder;
17995  renderItem.z = z;
17996  renderItem.group = group;
17997 
17998  }
17999 
18000  renderItemsIndex ++;
18001 
18002  return renderItem;
18003 
18004  }
18005 
18006  function push( object, geometry, material, groupOrder, z, group ) {
18007 
18008  var renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group );
18009 
18010  ( material.transparent === true ? transparent : opaque ).push( renderItem );
18011 
18012  }
18013 
18014  function unshift( object, geometry, material, groupOrder, z, group ) {
18015 
18016  var renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group );
18017 
18018  ( material.transparent === true ? transparent : opaque ).unshift( renderItem );
18019 
18020  }
18021 
18022  function sort() {
18023 
18024  if ( opaque.length > 1 ) opaque.sort( painterSortStable );
18025  if ( transparent.length > 1 ) transparent.sort( reversePainterSortStable );
18026 
18027  }
18028 
18029  return {
18030  opaque: opaque,
18031  transparent: transparent,
18032 
18033  init: init,
18034  push: push,
18035  unshift: unshift,
18036 
18037  sort: sort
18038  };
18039 
18040  }
18041 
18042  function WebGLRenderLists() {
18043 
18044  var lists = {};
18045 
18046  function onSceneDispose( event ) {
18047 
18048  var scene = event.target;
18049 
18050  scene.removeEventListener( 'dispose', onSceneDispose );
18051 
18052  delete lists[ scene.id ];
18053 
18054  }
18055 
18056  function get( scene, camera ) {
18057 
18058  var cameras = lists[ scene.id ];
18059  var list;
18060  if ( cameras === undefined ) {
18061 
18062  list = new WebGLRenderList();
18063  lists[ scene.id ] = {};
18064  lists[ scene.id ][ camera.id ] = list;
18065 
18066  scene.addEventListener( 'dispose', onSceneDispose );
18067 
18068  } else {
18069 
18070  list = cameras[ camera.id ];
18071  if ( list === undefined ) {
18072 
18073  list = new WebGLRenderList();
18074  cameras[ camera.id ] = list;
18075 
18076  }
18077 
18078  }
18079 
18080  return list;
18081 
18082  }
18083 
18084  function dispose() {
18085 
18086  lists = {};
18087 
18088  }
18089 
18090  return {
18091  get: get,
18092  dispose: dispose
18093  };
18094 
18095  }
18096 
18101  function UniformsCache() {
18102 
18103  var lights = {};
18104 
18105  return {
18106 
18107  get: function ( light ) {
18108 
18109  if ( lights[ light.id ] !== undefined ) {
18110 
18111  return lights[ light.id ];
18112 
18113  }
18114 
18115  var uniforms;
18116 
18117  switch ( light.type ) {
18118 
18119  case 'DirectionalLight':
18120  uniforms = {
18121  direction: new Vector3(),
18122  color: new Color(),
18123 
18124  shadow: false,
18125  shadowBias: 0,
18126  shadowRadius: 1,
18127  shadowMapSize: new Vector2()
18128  };
18129  break;
18130 
18131  case 'SpotLight':
18132  uniforms = {
18133  position: new Vector3(),
18134  direction: new Vector3(),
18135  color: new Color(),
18136  distance: 0,
18137  coneCos: 0,
18138  penumbraCos: 0,
18139  decay: 0,
18140 
18141  shadow: false,
18142  shadowBias: 0,
18143  shadowRadius: 1,
18144  shadowMapSize: new Vector2()
18145  };
18146  break;
18147 
18148  case 'PointLight':
18149  uniforms = {
18150  position: new Vector3(),
18151  color: new Color(),
18152  distance: 0,
18153  decay: 0,
18154 
18155  shadow: false,
18156  shadowBias: 0,
18157  shadowRadius: 1,
18158  shadowMapSize: new Vector2(),
18159  shadowCameraNear: 1,
18160  shadowCameraFar: 1000
18161  };
18162  break;
18163 
18164  case 'HemisphereLight':
18165  uniforms = {
18166  direction: new Vector3(),
18167  skyColor: new Color(),
18168  groundColor: new Color()
18169  };
18170  break;
18171 
18172  case 'RectAreaLight':
18173  uniforms = {
18174  color: new Color(),
18175  position: new Vector3(),
18176  halfWidth: new Vector3(),
18177  halfHeight: new Vector3()
18178  // TODO (abelnation): set RectAreaLight shadow uniforms
18179  };
18180  break;
18181 
18182  }
18183 
18184  lights[ light.id ] = uniforms;
18185 
18186  return uniforms;
18187 
18188  }
18189 
18190  };
18191 
18192  }
18193 
18194  var count = 0;
18195 
18196  function WebGLLights() {
18197 
18198  var cache = new UniformsCache();
18199 
18200  var state = {
18201 
18202  id: count ++,
18203 
18204  hash: {
18205  stateID: - 1,
18206  directionalLength: - 1,
18207  pointLength: - 1,
18208  spotLength: - 1,
18209  rectAreaLength: - 1,
18210  hemiLength: - 1,
18211  shadowsLength: - 1
18212  },
18213 
18214  ambient: [ 0, 0, 0 ],
18215  directional: [],
18216  directionalShadowMap: [],
18217  directionalShadowMatrix: [],
18218  spot: [],
18219  spotShadowMap: [],
18220  spotShadowMatrix: [],
18221  rectArea: [],
18222  point: [],
18223  pointShadowMap: [],
18224  pointShadowMatrix: [],
18225  hemi: []
18226 
18227  };
18228 
18229  var vector3 = new Vector3();
18230  var matrix4 = new Matrix4();
18231  var matrix42 = new Matrix4();
18232 
18233  function setup( lights, shadows, camera ) {
18234 
18235  var r = 0, g = 0, b = 0;
18236 
18237  var directionalLength = 0;
18238  var pointLength = 0;
18239  var spotLength = 0;
18240  var rectAreaLength = 0;
18241  var hemiLength = 0;
18242 
18243  var viewMatrix = camera.matrixWorldInverse;
18244 
18245  for ( var i = 0, l = lights.length; i < l; i ++ ) {
18246 
18247  var light = lights[ i ];
18248 
18249  var color = light.color;
18250  var intensity = light.intensity;
18251  var distance = light.distance;
18252 
18253  var shadowMap = ( light.shadow && light.shadow.map ) ? light.shadow.map.texture : null;
18254 
18255  if ( light.isAmbientLight ) {
18256 
18257  r += color.r * intensity;
18258  g += color.g * intensity;
18259  b += color.b * intensity;
18260 
18261  } else if ( light.isDirectionalLight ) {
18262 
18263  var uniforms = cache.get( light );
18264 
18265  uniforms.color.copy( light.color ).multiplyScalar( light.intensity );
18266  uniforms.direction.setFromMatrixPosition( light.matrixWorld );
18267  vector3.setFromMatrixPosition( light.target.matrixWorld );
18268  uniforms.direction.sub( vector3 );
18269  uniforms.direction.transformDirection( viewMatrix );
18270 
18271  uniforms.shadow = light.castShadow;
18272 
18273  if ( light.castShadow ) {
18274 
18275  var shadow = light.shadow;
18276 
18277  uniforms.shadowBias = shadow.bias;
18278  uniforms.shadowRadius = shadow.radius;
18279  uniforms.shadowMapSize = shadow.mapSize;
18280 
18281  }
18282 
18283  state.directionalShadowMap[ directionalLength ] = shadowMap;
18284  state.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix;
18285  state.directional[ directionalLength ] = uniforms;
18286 
18287  directionalLength ++;
18288 
18289  } else if ( light.isSpotLight ) {
18290 
18291  var uniforms = cache.get( light );
18292 
18293  uniforms.position.setFromMatrixPosition( light.matrixWorld );
18294  uniforms.position.applyMatrix4( viewMatrix );
18295 
18296  uniforms.color.copy( color ).multiplyScalar( intensity );
18297  uniforms.distance = distance;
18298 
18299  uniforms.direction.setFromMatrixPosition( light.matrixWorld );
18300  vector3.setFromMatrixPosition( light.target.matrixWorld );
18301  uniforms.direction.sub( vector3 );
18302  uniforms.direction.transformDirection( viewMatrix );
18303 
18304  uniforms.coneCos = Math.cos( light.angle );
18305  uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) );
18306  uniforms.decay = light.decay;
18307 
18308  uniforms.shadow = light.castShadow;
18309 
18310  if ( light.castShadow ) {
18311 
18312  var shadow = light.shadow;
18313 
18314  uniforms.shadowBias = shadow.bias;
18315  uniforms.shadowRadius = shadow.radius;
18316  uniforms.shadowMapSize = shadow.mapSize;
18317 
18318  }
18319 
18320  state.spotShadowMap[ spotLength ] = shadowMap;
18321  state.spotShadowMatrix[ spotLength ] = light.shadow.matrix;
18322  state.spot[ spotLength ] = uniforms;
18323 
18324  spotLength ++;
18325 
18326  } else if ( light.isRectAreaLight ) {
18327 
18328  var uniforms = cache.get( light );
18329 
18330  // (a) intensity is the total visible light emitted
18331  //uniforms.color.copy( color ).multiplyScalar( intensity / ( light.width * light.height * Math.PI ) );
18332 
18333  // (b) intensity is the brightness of the light
18334  uniforms.color.copy( color ).multiplyScalar( intensity );
18335 
18336  uniforms.position.setFromMatrixPosition( light.matrixWorld );
18337  uniforms.position.applyMatrix4( viewMatrix );
18338 
18339  // extract local rotation of light to derive width/height half vectors
18340  matrix42.identity();
18341  matrix4.copy( light.matrixWorld );
18342  matrix4.premultiply( viewMatrix );
18343  matrix42.extractRotation( matrix4 );
18344 
18345  uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 );
18346  uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 );
18347 
18348  uniforms.halfWidth.applyMatrix4( matrix42 );
18349  uniforms.halfHeight.applyMatrix4( matrix42 );
18350 
18351  // TODO (abelnation): RectAreaLight distance?
18352  // uniforms.distance = distance;
18353 
18354  state.rectArea[ rectAreaLength ] = uniforms;
18355 
18356  rectAreaLength ++;
18357 
18358  } else if ( light.isPointLight ) {
18359 
18360  var uniforms = cache.get( light );
18361 
18362  uniforms.position.setFromMatrixPosition( light.matrixWorld );
18363  uniforms.position.applyMatrix4( viewMatrix );
18364 
18365  uniforms.color.copy( light.color ).multiplyScalar( light.intensity );
18366  uniforms.distance = light.distance;
18367  uniforms.decay = light.decay;
18368 
18369  uniforms.shadow = light.castShadow;
18370 
18371  if ( light.castShadow ) {
18372 
18373  var shadow = light.shadow;
18374 
18375  uniforms.shadowBias = shadow.bias;
18376  uniforms.shadowRadius = shadow.radius;
18377  uniforms.shadowMapSize = shadow.mapSize;
18378  uniforms.shadowCameraNear = shadow.camera.near;
18379  uniforms.shadowCameraFar = shadow.camera.far;
18380 
18381  }
18382 
18383  state.pointShadowMap[ pointLength ] = shadowMap;
18384  state.pointShadowMatrix[ pointLength ] = light.shadow.matrix;
18385  state.point[ pointLength ] = uniforms;
18386 
18387  pointLength ++;
18388 
18389  } else if ( light.isHemisphereLight ) {
18390 
18391  var uniforms = cache.get( light );
18392 
18393  uniforms.direction.setFromMatrixPosition( light.matrixWorld );
18394  uniforms.direction.transformDirection( viewMatrix );
18395  uniforms.direction.normalize();
18396 
18397  uniforms.skyColor.copy( light.color ).multiplyScalar( intensity );
18398  uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity );
18399 
18400  state.hemi[ hemiLength ] = uniforms;
18401 
18402  hemiLength ++;
18403 
18404  }
18405 
18406  }
18407 
18408  state.ambient[ 0 ] = r;
18409  state.ambient[ 1 ] = g;
18410  state.ambient[ 2 ] = b;
18411 
18412  state.directional.length = directionalLength;
18413  state.spot.length = spotLength;
18414  state.rectArea.length = rectAreaLength;
18415  state.point.length = pointLength;
18416  state.hemi.length = hemiLength;
18417 
18418  state.hash.stateID = state.id;
18419  state.hash.directionalLength = directionalLength;
18420  state.hash.pointLength = pointLength;
18421  state.hash.spotLength = spotLength;
18422  state.hash.rectAreaLength = rectAreaLength;
18423  state.hash.hemiLength = hemiLength;
18424  state.hash.shadowsLength = shadows.length;
18425 
18426  }
18427 
18428  return {
18429  setup: setup,
18430  state: state
18431  };
18432 
18433  }
18434 
18439  function WebGLRenderState() {
18440 
18441  var lights = new WebGLLights();
18442 
18443  var lightsArray = [];
18444  var shadowsArray = [];
18445 
18446  function init() {
18447 
18448  lightsArray.length = 0;
18449  shadowsArray.length = 0;
18450 
18451  }
18452 
18453  function pushLight( light ) {
18454 
18455  lightsArray.push( light );
18456 
18457  }
18458 
18459  function pushShadow( shadowLight ) {
18460 
18461  shadowsArray.push( shadowLight );
18462 
18463  }
18464 
18465  function setupLights( camera ) {
18466 
18467  lights.setup( lightsArray, shadowsArray, camera );
18468 
18469  }
18470 
18471  var state = {
18472  lightsArray: lightsArray,
18473  shadowsArray: shadowsArray,
18474 
18475  lights: lights
18476  };
18477 
18478  return {
18479  init: init,
18480  state: state,
18481  setupLights: setupLights,
18482 
18483  pushLight: pushLight,
18484  pushShadow: pushShadow
18485  };
18486 
18487  }
18488 
18489  function WebGLRenderStates() {
18490 
18491  var renderStates = {};
18492 
18493  function onSceneDispose( event ) {
18494 
18495  var scene = event.target;
18496 
18497  scene.removeEventListener( 'dispose', onSceneDispose );
18498 
18499  delete renderStates[ scene.id ];
18500 
18501  }
18502 
18503  function get( scene, camera ) {
18504 
18505  var renderState;
18506 
18507  if ( renderStates[ scene.id ] === undefined ) {
18508 
18509  renderState = new WebGLRenderState();
18510  renderStates[ scene.id ] = {};
18511  renderStates[ scene.id ][ camera.id ] = renderState;
18512 
18513  scene.addEventListener( 'dispose', onSceneDispose );
18514 
18515  } else {
18516 
18517  if ( renderStates[ scene.id ][ camera.id ] === undefined ) {
18518 
18519  renderState = new WebGLRenderState();
18520  renderStates[ scene.id ][ camera.id ] = renderState;
18521 
18522  } else {
18523 
18524  renderState = renderStates[ scene.id ][ camera.id ];
18525 
18526  }
18527 
18528  }
18529 
18530  return renderState;
18531 
18532  }
18533 
18534  function dispose() {
18535 
18536  renderStates = {};
18537 
18538  }
18539 
18540  return {
18541  get: get,
18542  dispose: dispose
18543  };
18544 
18545  }
18546 
18570  function MeshDepthMaterial( parameters ) {
18571 
18572  Material.call( this );
18573 
18574  this.type = 'MeshDepthMaterial';
18575 
18576  this.depthPacking = BasicDepthPacking;
18577 
18578  this.skinning = false;
18579  this.morphTargets = false;
18580 
18581  this.map = null;
18582 
18583  this.alphaMap = null;
18584 
18585  this.displacementMap = null;
18586  this.displacementScale = 1;
18587  this.displacementBias = 0;
18588 
18589  this.wireframe = false;
18590  this.wireframeLinewidth = 1;
18591 
18592  this.fog = false;
18593  this.lights = false;
18594 
18595  this.setValues( parameters );
18596 
18597  }
18598 
18599  MeshDepthMaterial.prototype = Object.create( Material.prototype );
18600  MeshDepthMaterial.prototype.constructor = MeshDepthMaterial;
18601 
18602  MeshDepthMaterial.prototype.isMeshDepthMaterial = true;
18603 
18604  MeshDepthMaterial.prototype.copy = function ( source ) {
18605 
18606  Material.prototype.copy.call( this, source );
18607 
18608  this.depthPacking = source.depthPacking;
18609 
18610  this.skinning = source.skinning;
18611  this.morphTargets = source.morphTargets;
18612 
18613  this.map = source.map;
18614 
18615  this.alphaMap = source.alphaMap;
18616 
18617  this.displacementMap = source.displacementMap;
18618  this.displacementScale = source.displacementScale;
18619  this.displacementBias = source.displacementBias;
18620 
18621  this.wireframe = source.wireframe;
18622  this.wireframeLinewidth = source.wireframeLinewidth;
18623 
18624  return this;
18625 
18626  };
18627 
18651  function MeshDistanceMaterial( parameters ) {
18652 
18653  Material.call( this );
18654 
18655  this.type = 'MeshDistanceMaterial';
18656 
18657  this.referencePosition = new Vector3();
18658  this.nearDistance = 1;
18659  this.farDistance = 1000;
18660 
18661  this.skinning = false;
18662  this.morphTargets = false;
18663 
18664  this.map = null;
18665 
18666  this.alphaMap = null;
18667 
18668  this.displacementMap = null;
18669  this.displacementScale = 1;
18670  this.displacementBias = 0;
18671 
18672  this.fog = false;
18673  this.lights = false;
18674 
18675  this.setValues( parameters );
18676 
18677  }
18678 
18679  MeshDistanceMaterial.prototype = Object.create( Material.prototype );
18680  MeshDistanceMaterial.prototype.constructor = MeshDistanceMaterial;
18681 
18682  MeshDistanceMaterial.prototype.isMeshDistanceMaterial = true;
18683 
18684  MeshDistanceMaterial.prototype.copy = function ( source ) {
18685 
18686  Material.prototype.copy.call( this, source );
18687 
18688  this.referencePosition.copy( source.referencePosition );
18689  this.nearDistance = source.nearDistance;
18690  this.farDistance = source.farDistance;
18691 
18692  this.skinning = source.skinning;
18693  this.morphTargets = source.morphTargets;
18694 
18695  this.map = source.map;
18696 
18697  this.alphaMap = source.alphaMap;
18698 
18699  this.displacementMap = source.displacementMap;
18700  this.displacementScale = source.displacementScale;
18701  this.displacementBias = source.displacementBias;
18702 
18703  return this;
18704 
18705  };
18706 
18712  function WebGLShadowMap( _renderer, _objects, maxTextureSize ) {
18713 
18714  var _frustum = new Frustum(),
18715  _projScreenMatrix = new Matrix4(),
18716 
18717  _shadowMapSize = new Vector2(),
18718  _maxShadowMapSize = new Vector2( maxTextureSize, maxTextureSize ),
18719 
18720  _lookTarget = new Vector3(),
18721  _lightPositionWorld = new Vector3(),
18722 
18723  _MorphingFlag = 1,
18724  _SkinningFlag = 2,
18725 
18726  _NumberOfMaterialVariants = ( _MorphingFlag | _SkinningFlag ) + 1,
18727 
18728  _depthMaterials = new Array( _NumberOfMaterialVariants ),
18729  _distanceMaterials = new Array( _NumberOfMaterialVariants ),
18730 
18731  _materialCache = {};
18732 
18733  var shadowSide = { 0: BackSide, 1: FrontSide, 2: DoubleSide };
18734 
18735  var cubeDirections = [
18736  new Vector3( 1, 0, 0 ), new Vector3( - 1, 0, 0 ), new Vector3( 0, 0, 1 ),
18737  new Vector3( 0, 0, - 1 ), new Vector3( 0, 1, 0 ), new Vector3( 0, - 1, 0 )
18738  ];
18739 
18740  var cubeUps = [
18741  new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ),
18742  new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ), new Vector3( 0, 0, - 1 )
18743  ];
18744 
18745  var cube2DViewPorts = [
18746  new Vector4(), new Vector4(), new Vector4(),
18747  new Vector4(), new Vector4(), new Vector4()
18748  ];
18749 
18750  // init
18751 
18752  for ( var i = 0; i !== _NumberOfMaterialVariants; ++ i ) {
18753 
18754  var useMorphing = ( i & _MorphingFlag ) !== 0;
18755  var useSkinning = ( i & _SkinningFlag ) !== 0;
18756 
18757  var depthMaterial = new MeshDepthMaterial( {
18758 
18759  depthPacking: RGBADepthPacking,
18760 
18761  morphTargets: useMorphing,
18762  skinning: useSkinning
18763 
18764  } );
18765 
18766  _depthMaterials[ i ] = depthMaterial;
18767 
18768  //
18769 
18770  var distanceMaterial = new MeshDistanceMaterial( {
18771 
18772  morphTargets: useMorphing,
18773  skinning: useSkinning
18774 
18775  } );
18776 
18777  _distanceMaterials[ i ] = distanceMaterial;
18778 
18779  }
18780 
18781  //
18782 
18783  var scope = this;
18784 
18785  this.enabled = false;
18786 
18787  this.autoUpdate = true;
18788  this.needsUpdate = false;
18789 
18790  this.type = PCFShadowMap;
18791 
18792  this.render = function ( lights, scene, camera ) {
18793 
18794  if ( scope.enabled === false ) return;
18795  if ( scope.autoUpdate === false && scope.needsUpdate === false ) return;
18796 
18797  if ( lights.length === 0 ) return;
18798 
18799  var currentRenderTarget = _renderer.getRenderTarget();
18800 
18801  var _state = _renderer.state;
18802 
18803  // Set GL state for depth map.
18804  _state.setBlending( NoBlending );
18805  _state.buffers.color.setClear( 1, 1, 1, 1 );
18806  _state.buffers.depth.setTest( true );
18807  _state.setScissorTest( false );
18808 
18809  // render depth map
18810 
18811  var faceCount;
18812 
18813  for ( var i = 0, il = lights.length; i < il; i ++ ) {
18814 
18815  var light = lights[ i ];
18816  var shadow = light.shadow;
18817  var isPointLight = light && light.isPointLight;
18818 
18819  if ( shadow === undefined ) {
18820 
18821  console.warn( 'THREE.WebGLShadowMap:', light, 'has no shadow.' );
18822  continue;
18823 
18824  }
18825 
18826  var shadowCamera = shadow.camera;
18827 
18828  _shadowMapSize.copy( shadow.mapSize );
18829  _shadowMapSize.min( _maxShadowMapSize );
18830 
18831  if ( isPointLight ) {
18832 
18833  var vpWidth = _shadowMapSize.x;
18834  var vpHeight = _shadowMapSize.y;
18835 
18836  // These viewports map a cube-map onto a 2D texture with the
18837  // following orientation:
18838  //
18839  // xzXZ
18840  // y Y
18841  //
18842  // X - Positive x direction
18843  // x - Negative x direction
18844  // Y - Positive y direction
18845  // y - Negative y direction
18846  // Z - Positive z direction
18847  // z - Negative z direction
18848 
18849  // positive X
18850  cube2DViewPorts[ 0 ].set( vpWidth * 2, vpHeight, vpWidth, vpHeight );
18851  // negative X
18852  cube2DViewPorts[ 1 ].set( 0, vpHeight, vpWidth, vpHeight );
18853  // positive Z
18854  cube2DViewPorts[ 2 ].set( vpWidth * 3, vpHeight, vpWidth, vpHeight );
18855  // negative Z
18856  cube2DViewPorts[ 3 ].set( vpWidth, vpHeight, vpWidth, vpHeight );
18857  // positive Y
18858  cube2DViewPorts[ 4 ].set( vpWidth * 3, 0, vpWidth, vpHeight );
18859  // negative Y
18860  cube2DViewPorts[ 5 ].set( vpWidth, 0, vpWidth, vpHeight );
18861 
18862  _shadowMapSize.x *= 4.0;
18863  _shadowMapSize.y *= 2.0;
18864 
18865  }
18866 
18867  if ( shadow.map === null ) {
18868 
18869  var pars = { minFilter: NearestFilter, magFilter: NearestFilter, format: RGBAFormat };
18870 
18871  shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );
18872  shadow.map.texture.name = light.name + ".shadowMap";
18873 
18874  shadowCamera.updateProjectionMatrix();
18875 
18876  }
18877 
18878  if ( shadow.isSpotLightShadow ) {
18879 
18880  shadow.update( light );
18881 
18882  }
18883 
18884  var shadowMap = shadow.map;
18885  var shadowMatrix = shadow.matrix;
18886 
18887  _lightPositionWorld.setFromMatrixPosition( light.matrixWorld );
18888  shadowCamera.position.copy( _lightPositionWorld );
18889 
18890  if ( isPointLight ) {
18891 
18892  faceCount = 6;
18893 
18894  // for point lights we set the shadow matrix to be a translation-only matrix
18895  // equal to inverse of the light's position
18896 
18897  shadowMatrix.makeTranslation( - _lightPositionWorld.x, - _lightPositionWorld.y, - _lightPositionWorld.z );
18898 
18899  } else {
18900 
18901  faceCount = 1;
18902 
18903  _lookTarget.setFromMatrixPosition( light.target.matrixWorld );
18904  shadowCamera.lookAt( _lookTarget );
18905  shadowCamera.updateMatrixWorld();
18906 
18907  // compute shadow matrix
18908 
18909  shadowMatrix.set(
18910  0.5, 0.0, 0.0, 0.5,
18911  0.0, 0.5, 0.0, 0.5,
18912  0.0, 0.0, 0.5, 0.5,
18913  0.0, 0.0, 0.0, 1.0
18914  );
18915 
18916  shadowMatrix.multiply( shadowCamera.projectionMatrix );
18917  shadowMatrix.multiply( shadowCamera.matrixWorldInverse );
18918 
18919  }
18920 
18921  _renderer.setRenderTarget( shadowMap );
18922  _renderer.clear();
18923 
18924  // render shadow map for each cube face (if omni-directional) or
18925  // run a single pass if not
18926 
18927  for ( var face = 0; face < faceCount; face ++ ) {
18928 
18929  if ( isPointLight ) {
18930 
18931  _lookTarget.copy( shadowCamera.position );
18932  _lookTarget.add( cubeDirections[ face ] );
18933  shadowCamera.up.copy( cubeUps[ face ] );
18934  shadowCamera.lookAt( _lookTarget );
18935  shadowCamera.updateMatrixWorld();
18936 
18937  var vpDimensions = cube2DViewPorts[ face ];
18938  _state.viewport( vpDimensions );
18939 
18940  }
18941 
18942  // update camera matrices and frustum
18943 
18944  _projScreenMatrix.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse );
18945  _frustum.setFromMatrix( _projScreenMatrix );
18946 
18947  // set object matrices & frustum culling
18948 
18949  renderObject( scene, camera, shadowCamera, isPointLight );
18950 
18951  }
18952 
18953  }
18954 
18955  scope.needsUpdate = false;
18956 
18957  _renderer.setRenderTarget( currentRenderTarget );
18958 
18959  };
18960 
18961  function getDepthMaterial( object, material, isPointLight, lightPositionWorld, shadowCameraNear, shadowCameraFar ) {
18962 
18963  var geometry = object.geometry;
18964 
18965  var result = null;
18966 
18967  var materialVariants = _depthMaterials;
18968  var customMaterial = object.customDepthMaterial;
18969 
18970  if ( isPointLight ) {
18971 
18972  materialVariants = _distanceMaterials;
18973  customMaterial = object.customDistanceMaterial;
18974 
18975  }
18976 
18977  if ( ! customMaterial ) {
18978 
18979  var useMorphing = false;
18980 
18981  if ( material.morphTargets ) {
18982 
18983  if ( geometry && geometry.isBufferGeometry ) {
18984 
18985  useMorphing = geometry.morphAttributes && geometry.morphAttributes.position && geometry.morphAttributes.position.length > 0;
18986 
18987  } else if ( geometry && geometry.isGeometry ) {
18988 
18989  useMorphing = geometry.morphTargets && geometry.morphTargets.length > 0;
18990 
18991  }
18992 
18993  }
18994 
18995  if ( object.isSkinnedMesh && material.skinning === false ) {
18996 
18997  console.warn( 'THREE.WebGLShadowMap: THREE.SkinnedMesh with material.skinning set to false:', object );
18998 
18999  }
19000 
19001  var useSkinning = object.isSkinnedMesh && material.skinning;
19002 
19003  var variantIndex = 0;
19004 
19005  if ( useMorphing ) variantIndex |= _MorphingFlag;
19006  if ( useSkinning ) variantIndex |= _SkinningFlag;
19007 
19008  result = materialVariants[ variantIndex ];
19009 
19010  } else {
19011 
19012  result = customMaterial;
19013 
19014  }
19015 
19016  if ( _renderer.localClippingEnabled &&
19017  material.clipShadows === true &&
19018  material.clippingPlanes.length !== 0 ) {
19019 
19020  // in this case we need a unique material instance reflecting the
19021  // appropriate state
19022 
19023  var keyA = result.uuid, keyB = material.uuid;
19024 
19025  var materialsForVariant = _materialCache[ keyA ];
19026 
19027  if ( materialsForVariant === undefined ) {
19028 
19029  materialsForVariant = {};
19030  _materialCache[ keyA ] = materialsForVariant;
19031 
19032  }
19033 
19034  var cachedMaterial = materialsForVariant[ keyB ];
19035 
19036  if ( cachedMaterial === undefined ) {
19037 
19038  cachedMaterial = result.clone();
19039  materialsForVariant[ keyB ] = cachedMaterial;
19040 
19041  }
19042 
19043  result = cachedMaterial;
19044 
19045  }
19046 
19047  result.visible = material.visible;
19048  result.wireframe = material.wireframe;
19049 
19050  result.side = ( material.shadowSide != null ) ? material.shadowSide : shadowSide[ material.side ];
19051 
19052  result.clipShadows = material.clipShadows;
19053  result.clippingPlanes = material.clippingPlanes;
19054  result.clipIntersection = material.clipIntersection;
19055 
19056  result.wireframeLinewidth = material.wireframeLinewidth;
19057  result.linewidth = material.linewidth;
19058 
19059  if ( isPointLight && result.isMeshDistanceMaterial ) {
19060 
19061  result.referencePosition.copy( lightPositionWorld );
19062  result.nearDistance = shadowCameraNear;
19063  result.farDistance = shadowCameraFar;
19064 
19065  }
19066 
19067  return result;
19068 
19069  }
19070 
19071  function renderObject( object, camera, shadowCamera, isPointLight ) {
19072 
19073  if ( object.visible === false ) return;
19074 
19075  var visible = object.layers.test( camera.layers );
19076 
19077  if ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) {
19078 
19079  if ( object.castShadow && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) {
19080 
19081  object.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld );
19082 
19083  var geometry = _objects.update( object );
19084  var material = object.material;
19085 
19086  if ( Array.isArray( material ) ) {
19087 
19088  var groups = geometry.groups;
19089 
19090  for ( var k = 0, kl = groups.length; k < kl; k ++ ) {
19091 
19092  var group = groups[ k ];
19093  var groupMaterial = material[ group.materialIndex ];
19094 
19095  if ( groupMaterial && groupMaterial.visible ) {
19096 
19097  var depthMaterial = getDepthMaterial( object, groupMaterial, isPointLight, _lightPositionWorld, shadowCamera.near, shadowCamera.far );
19098  _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group );
19099 
19100  }
19101 
19102  }
19103 
19104  } else if ( material.visible ) {
19105 
19106  var depthMaterial = getDepthMaterial( object, material, isPointLight, _lightPositionWorld, shadowCamera.near, shadowCamera.far );
19107  _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null );
19108 
19109  }
19110 
19111  }
19112 
19113  }
19114 
19115  var children = object.children;
19116 
19117  for ( var i = 0, l = children.length; i < l; i ++ ) {
19118 
19119  renderObject( children[ i ], camera, shadowCamera, isPointLight );
19120 
19121  }
19122 
19123  }
19124 
19125  }
19126 
19131  function WebGLState( gl, extensions, utils, capabilities ) {
19132 
19133  function ColorBuffer() {
19134 
19135  var locked = false;
19136 
19137  var color = new Vector4();
19138  var currentColorMask = null;
19139  var currentColorClear = new Vector4( 0, 0, 0, 0 );
19140 
19141  return {
19142 
19143  setMask: function ( colorMask ) {
19144 
19145  if ( currentColorMask !== colorMask && ! locked ) {
19146 
19147  gl.colorMask( colorMask, colorMask, colorMask, colorMask );
19148  currentColorMask = colorMask;
19149 
19150  }
19151 
19152  },
19153 
19154  setLocked: function ( lock ) {
19155 
19156  locked = lock;
19157 
19158  },
19159 
19160  setClear: function ( r, g, b, a, premultipliedAlpha ) {
19161 
19162  if ( premultipliedAlpha === true ) {
19163 
19164  r *= a; g *= a; b *= a;
19165 
19166  }
19167 
19168  color.set( r, g, b, a );
19169 
19170  if ( currentColorClear.equals( color ) === false ) {
19171 
19172  gl.clearColor( r, g, b, a );
19173  currentColorClear.copy( color );
19174 
19175  }
19176 
19177  },
19178 
19179  reset: function () {
19180 
19181  locked = false;
19182 
19183  currentColorMask = null;
19184  currentColorClear.set( - 1, 0, 0, 0 ); // set to invalid state
19185 
19186  }
19187 
19188  };
19189 
19190  }
19191 
19192  function DepthBuffer() {
19193 
19194  var locked = false;
19195 
19196  var currentDepthMask = null;
19197  var currentDepthFunc = null;
19198  var currentDepthClear = null;
19199 
19200  return {
19201 
19202  setTest: function ( depthTest ) {
19203 
19204  if ( depthTest ) {
19205 
19206  enable( 2929 );
19207 
19208  } else {
19209 
19210  disable( 2929 );
19211 
19212  }
19213 
19214  },
19215 
19216  setMask: function ( depthMask ) {
19217 
19218  if ( currentDepthMask !== depthMask && ! locked ) {
19219 
19220  gl.depthMask( depthMask );
19221  currentDepthMask = depthMask;
19222 
19223  }
19224 
19225  },
19226 
19227  setFunc: function ( depthFunc ) {
19228 
19229  if ( currentDepthFunc !== depthFunc ) {
19230 
19231  if ( depthFunc ) {
19232 
19233  switch ( depthFunc ) {
19234 
19235  case NeverDepth:
19236 
19237  gl.depthFunc( 512 );
19238  break;
19239 
19240  case AlwaysDepth:
19241 
19242  gl.depthFunc( 519 );
19243  break;
19244 
19245  case LessDepth:
19246 
19247  gl.depthFunc( 513 );
19248  break;
19249 
19250  case LessEqualDepth:
19251 
19252  gl.depthFunc( 515 );
19253  break;
19254 
19255  case EqualDepth:
19256 
19257  gl.depthFunc( 514 );
19258  break;
19259 
19260  case GreaterEqualDepth:
19261 
19262  gl.depthFunc( 518 );
19263  break;
19264 
19265  case GreaterDepth:
19266 
19267  gl.depthFunc( 516 );
19268  break;
19269 
19270  case NotEqualDepth:
19271 
19272  gl.depthFunc( 517 );
19273  break;
19274 
19275  default:
19276 
19277  gl.depthFunc( 515 );
19278 
19279  }
19280 
19281  } else {
19282 
19283  gl.depthFunc( 515 );
19284 
19285  }
19286 
19287  currentDepthFunc = depthFunc;
19288 
19289  }
19290 
19291  },
19292 
19293  setLocked: function ( lock ) {
19294 
19295  locked = lock;
19296 
19297  },
19298 
19299  setClear: function ( depth ) {
19300 
19301  if ( currentDepthClear !== depth ) {
19302 
19303  gl.clearDepth( depth );
19304  currentDepthClear = depth;
19305 
19306  }
19307 
19308  },
19309 
19310  reset: function () {
19311 
19312  locked = false;
19313 
19314  currentDepthMask = null;
19315  currentDepthFunc = null;
19316  currentDepthClear = null;
19317 
19318  }
19319 
19320  };
19321 
19322  }
19323 
19324  function StencilBuffer() {
19325 
19326  var locked = false;
19327 
19328  var currentStencilMask = null;
19329  var currentStencilFunc = null;
19330  var currentStencilRef = null;
19331  var currentStencilFuncMask = null;
19332  var currentStencilFail = null;
19333  var currentStencilZFail = null;
19334  var currentStencilZPass = null;
19335  var currentStencilClear = null;
19336 
19337  return {
19338 
19339  setTest: function ( stencilTest ) {
19340 
19341  if ( stencilTest ) {
19342 
19343  enable( 2960 );
19344 
19345  } else {
19346 
19347  disable( 2960 );
19348 
19349  }
19350 
19351  },
19352 
19353  setMask: function ( stencilMask ) {
19354 
19355  if ( currentStencilMask !== stencilMask && ! locked ) {
19356 
19357  gl.stencilMask( stencilMask );
19358  currentStencilMask = stencilMask;
19359 
19360  }
19361 
19362  },
19363 
19364  setFunc: function ( stencilFunc, stencilRef, stencilMask ) {
19365 
19366  if ( currentStencilFunc !== stencilFunc ||
19367  currentStencilRef !== stencilRef ||
19368  currentStencilFuncMask !== stencilMask ) {
19369 
19370  gl.stencilFunc( stencilFunc, stencilRef, stencilMask );
19371 
19372  currentStencilFunc = stencilFunc;
19373  currentStencilRef = stencilRef;
19374  currentStencilFuncMask = stencilMask;
19375 
19376  }
19377 
19378  },
19379 
19380  setOp: function ( stencilFail, stencilZFail, stencilZPass ) {
19381 
19382  if ( currentStencilFail !== stencilFail ||
19383  currentStencilZFail !== stencilZFail ||
19384  currentStencilZPass !== stencilZPass ) {
19385 
19386  gl.stencilOp( stencilFail, stencilZFail, stencilZPass );
19387 
19388  currentStencilFail = stencilFail;
19389  currentStencilZFail = stencilZFail;
19390  currentStencilZPass = stencilZPass;
19391 
19392  }
19393 
19394  },
19395 
19396  setLocked: function ( lock ) {
19397 
19398  locked = lock;
19399 
19400  },
19401 
19402  setClear: function ( stencil ) {
19403 
19404  if ( currentStencilClear !== stencil ) {
19405 
19406  gl.clearStencil( stencil );
19407  currentStencilClear = stencil;
19408 
19409  }
19410 
19411  },
19412 
19413  reset: function () {
19414 
19415  locked = false;
19416 
19417  currentStencilMask = null;
19418  currentStencilFunc = null;
19419  currentStencilRef = null;
19420  currentStencilFuncMask = null;
19421  currentStencilFail = null;
19422  currentStencilZFail = null;
19423  currentStencilZPass = null;
19424  currentStencilClear = null;
19425 
19426  }
19427 
19428  };
19429 
19430  }
19431 
19432  //
19433 
19434  var colorBuffer = new ColorBuffer();
19435  var depthBuffer = new DepthBuffer();
19436  var stencilBuffer = new StencilBuffer();
19437 
19438  var maxVertexAttributes = gl.getParameter( 34921 );
19439  var newAttributes = new Uint8Array( maxVertexAttributes );
19440  var enabledAttributes = new Uint8Array( maxVertexAttributes );
19441  var attributeDivisors = new Uint8Array( maxVertexAttributes );
19442 
19443  var enabledCapabilities = {};
19444 
19445  var compressedTextureFormats = null;
19446 
19447  var currentProgram = null;
19448 
19449  var currentBlendingEnabled = null;
19450  var currentBlending = null;
19451  var currentBlendEquation = null;
19452  var currentBlendSrc = null;
19453  var currentBlendDst = null;
19454  var currentBlendEquationAlpha = null;
19455  var currentBlendSrcAlpha = null;
19456  var currentBlendDstAlpha = null;
19457  var currentPremultipledAlpha = false;
19458 
19459  var currentFlipSided = null;
19460  var currentCullFace = null;
19461 
19462  var currentLineWidth = null;
19463 
19464  var currentPolygonOffsetFactor = null;
19465  var currentPolygonOffsetUnits = null;
19466 
19467  var maxTextures = gl.getParameter( 35661 );
19468 
19469  var lineWidthAvailable = false;
19470  var version = 0;
19471  var glVersion = gl.getParameter( 7938 );
19472 
19473  if ( glVersion.indexOf( 'WebGL' ) !== - 1 ) {
19474 
19475  version = parseFloat( /^WebGL\ ([0-9])/.exec( glVersion )[ 1 ] );
19476  lineWidthAvailable = ( version >= 1.0 );
19477 
19478  } else if ( glVersion.indexOf( 'OpenGL ES' ) !== - 1 ) {
19479 
19480  version = parseFloat( /^OpenGL\ ES\ ([0-9])/.exec( glVersion )[ 1 ] );
19481  lineWidthAvailable = ( version >= 2.0 );
19482 
19483  }
19484 
19485  var currentTextureSlot = null;
19486  var currentBoundTextures = {};
19487 
19488  var currentScissor = new Vector4();
19489  var currentViewport = new Vector4();
19490 
19491  function createTexture( type, target, count ) {
19492 
19493  var data = new Uint8Array( 4 ); // 4 is required to match default unpack alignment of 4.
19494  var texture = gl.createTexture();
19495 
19496  gl.bindTexture( type, texture );
19497  gl.texParameteri( type, 10241, 9728 );
19498  gl.texParameteri( type, 10240, 9728 );
19499 
19500  for ( var i = 0; i < count; i ++ ) {
19501 
19502  gl.texImage2D( target + i, 0, 6408, 1, 1, 0, 6408, 5121, data );
19503 
19504  }
19505 
19506  return texture;
19507 
19508  }
19509 
19510  var emptyTextures = {};
19511  emptyTextures[ 3553 ] = createTexture( 3553, 3553, 1 );
19512  emptyTextures[ 34067 ] = createTexture( 34067, 34069, 6 );
19513 
19514  // init
19515 
19516  colorBuffer.setClear( 0, 0, 0, 1 );
19517  depthBuffer.setClear( 1 );
19518  stencilBuffer.setClear( 0 );
19519 
19520  enable( 2929 );
19521  depthBuffer.setFunc( LessEqualDepth );
19522 
19523  setFlipSided( false );
19524  setCullFace( CullFaceBack );
19525  enable( 2884 );
19526 
19527  setBlending( NoBlending );
19528 
19529  //
19530 
19531  function initAttributes() {
19532 
19533  for ( var i = 0, l = newAttributes.length; i < l; i ++ ) {
19534 
19535  newAttributes[ i ] = 0;
19536 
19537  }
19538 
19539  }
19540 
19541  function enableAttribute( attribute ) {
19542 
19543  enableAttributeAndDivisor( attribute, 0 );
19544 
19545  }
19546 
19547  function enableAttributeAndDivisor( attribute, meshPerAttribute ) {
19548 
19549  newAttributes[ attribute ] = 1;
19550 
19551  if ( enabledAttributes[ attribute ] === 0 ) {
19552 
19553  gl.enableVertexAttribArray( attribute );
19554  enabledAttributes[ attribute ] = 1;
19555 
19556  }
19557 
19558  if ( attributeDivisors[ attribute ] !== meshPerAttribute ) {
19559 
19560  var extension = capabilities.isWebGL2 ? gl : extensions.get( 'ANGLE_instanced_arrays' );
19561 
19562  extension[ capabilities.isWebGL2 ? 'vertexAttribDivisor' : 'vertexAttribDivisorANGLE' ]( attribute, meshPerAttribute );
19563  attributeDivisors[ attribute ] = meshPerAttribute;
19564 
19565  }
19566 
19567  }
19568 
19569  function disableUnusedAttributes() {
19570 
19571  for ( var i = 0, l = enabledAttributes.length; i !== l; ++ i ) {
19572 
19573  if ( enabledAttributes[ i ] !== newAttributes[ i ] ) {
19574 
19575  gl.disableVertexAttribArray( i );
19576  enabledAttributes[ i ] = 0;
19577 
19578  }
19579 
19580  }
19581 
19582  }
19583 
19584  function enable( id ) {
19585 
19586  if ( enabledCapabilities[ id ] !== true ) {
19587 
19588  gl.enable( id );
19589  enabledCapabilities[ id ] = true;
19590 
19591  }
19592 
19593  }
19594 
19595  function disable( id ) {
19596 
19597  if ( enabledCapabilities[ id ] !== false ) {
19598 
19599  gl.disable( id );
19600  enabledCapabilities[ id ] = false;
19601 
19602  }
19603 
19604  }
19605 
19606  function getCompressedTextureFormats() {
19607 
19608  if ( compressedTextureFormats === null ) {
19609 
19610  compressedTextureFormats = [];
19611 
19612  if ( extensions.get( 'WEBGL_compressed_texture_pvrtc' ) ||
19613  extensions.get( 'WEBGL_compressed_texture_s3tc' ) ||
19614  extensions.get( 'WEBGL_compressed_texture_etc1' ) ||
19615  extensions.get( 'WEBGL_compressed_texture_astc' ) ) {
19616 
19617  var formats = gl.getParameter( 34467 );
19618 
19619  for ( var i = 0; i < formats.length; i ++ ) {
19620 
19621  compressedTextureFormats.push( formats[ i ] );
19622 
19623  }
19624 
19625  }
19626 
19627  }
19628 
19629  return compressedTextureFormats;
19630 
19631  }
19632 
19633  function useProgram( program ) {
19634 
19635  if ( currentProgram !== program ) {
19636 
19637  gl.useProgram( program );
19638 
19639  currentProgram = program;
19640 
19641  return true;
19642 
19643  }
19644 
19645  return false;
19646 
19647  }
19648 
19649  function setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, premultipliedAlpha ) {
19650 
19651  if ( blending === NoBlending ) {
19652 
19653  if ( currentBlendingEnabled ) {
19654 
19655  disable( 3042 );
19656  currentBlendingEnabled = false;
19657 
19658  }
19659 
19660  return;
19661 
19662  }
19663 
19664  if ( ! currentBlendingEnabled ) {
19665 
19666  enable( 3042 );
19667  currentBlendingEnabled = true;
19668 
19669  }
19670 
19671  if ( blending !== CustomBlending ) {
19672 
19673  if ( blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha ) {
19674 
19675  if ( currentBlendEquation !== AddEquation || currentBlendEquationAlpha !== AddEquation ) {
19676 
19677  gl.blendEquation( 32774 );
19678 
19679  currentBlendEquation = AddEquation;
19680  currentBlendEquationAlpha = AddEquation;
19681 
19682  }
19683 
19684  if ( premultipliedAlpha ) {
19685 
19686  switch ( blending ) {
19687 
19688  case NormalBlending:
19689  gl.blendFuncSeparate( 1, 771, 1, 771 );
19690  break;
19691 
19692  case AdditiveBlending:
19693  gl.blendFunc( 1, 1 );
19694  break;
19695 
19696  case SubtractiveBlending:
19697  gl.blendFuncSeparate( 0, 0, 769, 771 );
19698  break;
19699 
19700  case MultiplyBlending:
19701  gl.blendFuncSeparate( 0, 768, 0, 770 );
19702  break;
19703 
19704  default:
19705  console.error( 'THREE.WebGLState: Invalid blending: ', blending );
19706  break;
19707 
19708  }
19709 
19710  } else {
19711 
19712  switch ( blending ) {
19713 
19714  case NormalBlending:
19715  gl.blendFuncSeparate( 770, 771, 1, 771 );
19716  break;
19717 
19718  case AdditiveBlending:
19719  gl.blendFunc( 770, 1 );
19720  break;
19721 
19722  case SubtractiveBlending:
19723  gl.blendFunc( 0, 769 );
19724  break;
19725 
19726  case MultiplyBlending:
19727  gl.blendFunc( 0, 768 );
19728  break;
19729 
19730  default:
19731  console.error( 'THREE.WebGLState: Invalid blending: ', blending );
19732  break;
19733 
19734  }
19735 
19736  }
19737 
19738  currentBlendSrc = null;
19739  currentBlendDst = null;
19740  currentBlendSrcAlpha = null;
19741  currentBlendDstAlpha = null;
19742 
19743  currentBlending = blending;
19744  currentPremultipledAlpha = premultipliedAlpha;
19745 
19746  }
19747 
19748  return;
19749 
19750  }
19751 
19752  // custom blending
19753 
19754  blendEquationAlpha = blendEquationAlpha || blendEquation;
19755  blendSrcAlpha = blendSrcAlpha || blendSrc;
19756  blendDstAlpha = blendDstAlpha || blendDst;
19757 
19758  if ( blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha ) {
19759 
19760  gl.blendEquationSeparate( utils.convert( blendEquation ), utils.convert( blendEquationAlpha ) );
19761 
19762  currentBlendEquation = blendEquation;
19763  currentBlendEquationAlpha = blendEquationAlpha;
19764 
19765  }
19766 
19767  if ( blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha ) {
19768 
19769  gl.blendFuncSeparate( utils.convert( blendSrc ), utils.convert( blendDst ), utils.convert( blendSrcAlpha ), utils.convert( blendDstAlpha ) );
19770 
19771  currentBlendSrc = blendSrc;
19772  currentBlendDst = blendDst;
19773  currentBlendSrcAlpha = blendSrcAlpha;
19774  currentBlendDstAlpha = blendDstAlpha;
19775 
19776  }
19777 
19778  currentBlending = blending;
19779  currentPremultipledAlpha = null;
19780 
19781  }
19782 
19783  function setMaterial( material, frontFaceCW ) {
19784 
19785  material.side === DoubleSide
19786  ? disable( 2884 )
19787  : enable( 2884 );
19788 
19789  var flipSided = ( material.side === BackSide );
19790  if ( frontFaceCW ) flipSided = ! flipSided;
19791 
19792  setFlipSided( flipSided );
19793 
19794  ( material.blending === NormalBlending && material.transparent === false )
19795  ? setBlending( NoBlending )
19796  : setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha );
19797 
19798  depthBuffer.setFunc( material.depthFunc );
19799  depthBuffer.setTest( material.depthTest );
19800  depthBuffer.setMask( material.depthWrite );
19801  colorBuffer.setMask( material.colorWrite );
19802 
19803  setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
19804 
19805  }
19806 
19807  //
19808 
19809  function setFlipSided( flipSided ) {
19810 
19811  if ( currentFlipSided !== flipSided ) {
19812 
19813  if ( flipSided ) {
19814 
19815  gl.frontFace( 2304 );
19816 
19817  } else {
19818 
19819  gl.frontFace( 2305 );
19820 
19821  }
19822 
19823  currentFlipSided = flipSided;
19824 
19825  }
19826 
19827  }
19828 
19829  function setCullFace( cullFace ) {
19830 
19831  if ( cullFace !== CullFaceNone ) {
19832 
19833  enable( 2884 );
19834 
19835  if ( cullFace !== currentCullFace ) {
19836 
19837  if ( cullFace === CullFaceBack ) {
19838 
19839  gl.cullFace( 1029 );
19840 
19841  } else if ( cullFace === CullFaceFront ) {
19842 
19843  gl.cullFace( 1028 );
19844 
19845  } else {
19846 
19847  gl.cullFace( 1032 );
19848 
19849  }
19850 
19851  }
19852 
19853  } else {
19854 
19855  disable( 2884 );
19856 
19857  }
19858 
19859  currentCullFace = cullFace;
19860 
19861  }
19862 
19863  function setLineWidth( width ) {
19864 
19865  if ( width !== currentLineWidth ) {
19866 
19867  if ( lineWidthAvailable ) gl.lineWidth( width );
19868 
19869  currentLineWidth = width;
19870 
19871  }
19872 
19873  }
19874 
19875  function setPolygonOffset( polygonOffset, factor, units ) {
19876 
19877  if ( polygonOffset ) {
19878 
19879  enable( 32823 );
19880 
19881  if ( currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units ) {
19882 
19883  gl.polygonOffset( factor, units );
19884 
19885  currentPolygonOffsetFactor = factor;
19886  currentPolygonOffsetUnits = units;
19887 
19888  }
19889 
19890  } else {
19891 
19892  disable( 32823 );
19893 
19894  }
19895 
19896  }
19897 
19898  function setScissorTest( scissorTest ) {
19899 
19900  if ( scissorTest ) {
19901 
19902  enable( 3089 );
19903 
19904  } else {
19905 
19906  disable( 3089 );
19907 
19908  }
19909 
19910  }
19911 
19912  // texture
19913 
19914  function activeTexture( webglSlot ) {
19915 
19916  if ( webglSlot === undefined ) webglSlot = 33984 + maxTextures - 1;
19917 
19918  if ( currentTextureSlot !== webglSlot ) {
19919 
19920  gl.activeTexture( webglSlot );
19921  currentTextureSlot = webglSlot;
19922 
19923  }
19924 
19925  }
19926 
19927  function bindTexture( webglType, webglTexture ) {
19928 
19929  if ( currentTextureSlot === null ) {
19930 
19931  activeTexture();
19932 
19933  }
19934 
19935  var boundTexture = currentBoundTextures[ currentTextureSlot ];
19936 
19937  if ( boundTexture === undefined ) {
19938 
19939  boundTexture = { type: undefined, texture: undefined };
19940  currentBoundTextures[ currentTextureSlot ] = boundTexture;
19941 
19942  }
19943 
19944  if ( boundTexture.type !== webglType || boundTexture.texture !== webglTexture ) {
19945 
19946  gl.bindTexture( webglType, webglTexture || emptyTextures[ webglType ] );
19947 
19948  boundTexture.type = webglType;
19949  boundTexture.texture = webglTexture;
19950 
19951  }
19952 
19953  }
19954 
19955  function compressedTexImage2D() {
19956 
19957  try {
19958 
19959  gl.compressedTexImage2D.apply( gl, arguments );
19960 
19961  } catch ( error ) {
19962 
19963  console.error( 'THREE.WebGLState:', error );
19964 
19965  }
19966 
19967  }
19968 
19969  function texImage2D() {
19970 
19971  try {
19972 
19973  gl.texImage2D.apply( gl, arguments );
19974 
19975  } catch ( error ) {
19976 
19977  console.error( 'THREE.WebGLState:', error );
19978 
19979  }
19980 
19981  }
19982 
19983  function texImage3D() {
19984 
19985  try {
19986 
19987  gl.texImage3D.apply( gl, arguments );
19988 
19989  } catch ( error ) {
19990 
19991  console.error( 'THREE.WebGLState:', error );
19992 
19993  }
19994 
19995  }
19996 
19997  //
19998 
19999  function scissor( scissor ) {
20000 
20001  if ( currentScissor.equals( scissor ) === false ) {
20002 
20003  gl.scissor( scissor.x, scissor.y, scissor.z, scissor.w );
20004  currentScissor.copy( scissor );
20005 
20006  }
20007 
20008  }
20009 
20010  function viewport( viewport ) {
20011 
20012  if ( currentViewport.equals( viewport ) === false ) {
20013 
20014  gl.viewport( viewport.x, viewport.y, viewport.z, viewport.w );
20015  currentViewport.copy( viewport );
20016 
20017  }
20018 
20019  }
20020 
20021  //
20022 
20023  function reset() {
20024 
20025  for ( var i = 0; i < enabledAttributes.length; i ++ ) {
20026 
20027  if ( enabledAttributes[ i ] === 1 ) {
20028 
20029  gl.disableVertexAttribArray( i );
20030  enabledAttributes[ i ] = 0;
20031 
20032  }
20033 
20034  }
20035 
20036  enabledCapabilities = {};
20037 
20038  compressedTextureFormats = null;
20039 
20040  currentTextureSlot = null;
20041  currentBoundTextures = {};
20042 
20043  currentProgram = null;
20044 
20045  currentBlending = null;
20046 
20047  currentFlipSided = null;
20048  currentCullFace = null;
20049 
20050  colorBuffer.reset();
20051  depthBuffer.reset();
20052  stencilBuffer.reset();
20053 
20054  }
20055 
20056  return {
20057 
20058  buffers: {
20059  color: colorBuffer,
20060  depth: depthBuffer,
20061  stencil: stencilBuffer
20062  },
20063 
20064  initAttributes: initAttributes,
20065  enableAttribute: enableAttribute,
20066  enableAttributeAndDivisor: enableAttributeAndDivisor,
20067  disableUnusedAttributes: disableUnusedAttributes,
20068  enable: enable,
20069  disable: disable,
20070  getCompressedTextureFormats: getCompressedTextureFormats,
20071 
20072  useProgram: useProgram,
20073 
20074  setBlending: setBlending,
20075  setMaterial: setMaterial,
20076 
20077  setFlipSided: setFlipSided,
20078  setCullFace: setCullFace,
20079 
20080  setLineWidth: setLineWidth,
20081  setPolygonOffset: setPolygonOffset,
20082 
20083  setScissorTest: setScissorTest,
20084 
20085  activeTexture: activeTexture,
20086  bindTexture: bindTexture,
20087  compressedTexImage2D: compressedTexImage2D,
20088  texImage2D: texImage2D,
20089  texImage3D: texImage3D,
20090 
20091  scissor: scissor,
20092  viewport: viewport,
20093 
20094  reset: reset
20095 
20096  };
20097 
20098  }
20099 
20104  function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ) {
20105 
20106  var _videoTextures = {};
20107  var _canvas;
20108 
20109  //
20110 
20111  var useOffscreenCanvas = typeof OffscreenCanvas !== 'undefined';
20112 
20113  function createCanvas( width, height ) {
20114 
20115  // Use OffscreenCanvas when available. Specially needed in web workers
20116 
20117  return useOffscreenCanvas ?
20118  new OffscreenCanvas( width, height ) :
20119  document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
20120 
20121  }
20122 
20123  function resizeImage( image, needsPowerOfTwo, needsNewCanvas, maxSize ) {
20124 
20125  var scale = 1;
20126 
20127  // handle case if texture exceeds max size
20128 
20129  if ( image.width > maxSize || image.height > maxSize ) {
20130 
20131  scale = maxSize / Math.max( image.width, image.height );
20132 
20133  }
20134 
20135  // only perform resize if necessary
20136 
20137  if ( scale < 1 || needsPowerOfTwo === true ) {
20138 
20139  // only perform resize for certain image types
20140 
20141  if ( image instanceof ImageBitmap || image instanceof HTMLImageElement || image instanceof HTMLCanvasElement ) {
20142 
20143  var floor = needsPowerOfTwo ? _Math.floorPowerOfTwo : Math.floor;
20144 
20145  var width = floor( scale * image.width );
20146  var height = floor( scale * image.height );
20147 
20148  if ( _canvas === undefined ) _canvas = createCanvas( width, height );
20149 
20150  // cube textures can't reuse the same canvas
20151 
20152  var canvas = needsNewCanvas ? createCanvas( width, height ) : _canvas;
20153 
20154  canvas.width = width;
20155  canvas.height = height;
20156 
20157  var context = canvas.getContext( '2d' );
20158  context.drawImage( image, 0, 0, width, height );
20159 
20160  console.warn( 'THREE.WebGLRenderer: Texture has been resized from (' + image.width + 'x' + image.height + ') to (' + width + 'x' + height + ').' );
20161 
20162  return useOffscreenCanvas ? canvas.transferToImageBitmap() : canvas;
20163 
20164  } else {
20165 
20166  if ( 'data' in image ) {
20167 
20168  console.warn( 'THREE.WebGLRenderer: Image in DataTexture is too big (' + image.width + 'x' + image.height + ').' );
20169 
20170  }
20171 
20172  return image;
20173 
20174  }
20175 
20176  }
20177 
20178  return image;
20179 
20180  }
20181 
20182  function isPowerOfTwo( image ) {
20183 
20184  return _Math.isPowerOfTwo( image.width ) && _Math.isPowerOfTwo( image.height );
20185 
20186  }
20187 
20188  function textureNeedsPowerOfTwo( texture ) {
20189 
20190  if ( capabilities.isWebGL2 ) return false;
20191 
20192  return ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) ||
20193  ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter );
20194 
20195  }
20196 
20197  function textureNeedsGenerateMipmaps( texture, supportsMips ) {
20198 
20199  return texture.generateMipmaps && supportsMips &&
20200  texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter;
20201 
20202  }
20203 
20204  function generateMipmap( target, texture, width, height ) {
20205 
20206  _gl.generateMipmap( target );
20207 
20208  var textureProperties = properties.get( texture );
20209 
20210  // Note: Math.log( x ) * Math.LOG2E used instead of Math.log2( x ) which is not supported by IE11
20211  textureProperties.__maxMipLevel = Math.log( Math.max( width, height ) ) * Math.LOG2E;
20212 
20213  }
20214 
20215  function getInternalFormat( glFormat, glType ) {
20216 
20217  if ( ! capabilities.isWebGL2 ) return glFormat;
20218 
20219  var internalFormat = glFormat;
20220 
20221  if ( glFormat === 6403 ) {
20222 
20223  if ( glType === 5126 ) internalFormat = 33326;
20224  if ( glType === 5131 ) internalFormat = 33325;
20225  if ( glType === 5121 ) internalFormat = 33321;
20226 
20227  }
20228 
20229  if ( glFormat === 6407 ) {
20230 
20231  if ( glType === 5126 ) internalFormat = 34837;
20232  if ( glType === 5131 ) internalFormat = 34843;
20233  if ( glType === 5121 ) internalFormat = 32849;
20234 
20235  }
20236 
20237  if ( glFormat === 6408 ) {
20238 
20239  if ( glType === 5126 ) internalFormat = 34836;
20240  if ( glType === 5131 ) internalFormat = 34842;
20241  if ( glType === 5121 ) internalFormat = 32856;
20242 
20243  }
20244 
20245  if ( internalFormat === 33325 || internalFormat === 33326 ||
20246  internalFormat === 34842 || internalFormat === 34836 ) {
20247 
20248  extensions.get( 'EXT_color_buffer_float' );
20249 
20250  } else if ( internalFormat === 34843 || internalFormat === 34837 ) {
20251 
20252  console.warn( 'THREE.WebGLRenderer: Floating point textures with RGB format not supported. Please use RGBA instead.' );
20253 
20254  }
20255 
20256  return internalFormat;
20257 
20258  }
20259 
20260  // Fallback filters for non-power-of-2 textures
20261 
20262  function filterFallback( f ) {
20263 
20264  if ( f === NearestFilter || f === NearestMipMapNearestFilter || f === NearestMipMapLinearFilter ) {
20265 
20266  return 9728;
20267 
20268  }
20269 
20270  return 9729;
20271 
20272  }
20273 
20274  //
20275 
20276  function onTextureDispose( event ) {
20277 
20278  var texture = event.target;
20279 
20280  texture.removeEventListener( 'dispose', onTextureDispose );
20281 
20282  deallocateTexture( texture );
20283 
20284  if ( texture.isVideoTexture ) {
20285 
20286  delete _videoTextures[ texture.id ];
20287 
20288  }
20289 
20290  info.memory.textures --;
20291 
20292  }
20293 
20294  function onRenderTargetDispose( event ) {
20295 
20296  var renderTarget = event.target;
20297 
20298  renderTarget.removeEventListener( 'dispose', onRenderTargetDispose );
20299 
20300  deallocateRenderTarget( renderTarget );
20301 
20302  info.memory.textures --;
20303 
20304  }
20305 
20306  //
20307 
20308  function deallocateTexture( texture ) {
20309 
20310  var textureProperties = properties.get( texture );
20311 
20312  if ( textureProperties.__webglInit === undefined ) return;
20313 
20314  _gl.deleteTexture( textureProperties.__webglTexture );
20315 
20316  properties.remove( texture );
20317 
20318  }
20319 
20320  function deallocateRenderTarget( renderTarget ) {
20321 
20322  var renderTargetProperties = properties.get( renderTarget );
20323  var textureProperties = properties.get( renderTarget.texture );
20324 
20325  if ( ! renderTarget ) return;
20326 
20327  if ( textureProperties.__webglTexture !== undefined ) {
20328 
20329  _gl.deleteTexture( textureProperties.__webglTexture );
20330 
20331  }
20332 
20333  if ( renderTarget.depthTexture ) {
20334 
20335  renderTarget.depthTexture.dispose();
20336 
20337  }
20338 
20339  if ( renderTarget.isWebGLRenderTargetCube ) {
20340 
20341  for ( var i = 0; i < 6; i ++ ) {
20342 
20343  _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ] );
20344  if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer[ i ] );
20345 
20346  }
20347 
20348  } else {
20349 
20350  _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer );
20351  if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer );
20352 
20353  }
20354 
20355  properties.remove( renderTarget.texture );
20356  properties.remove( renderTarget );
20357 
20358  }
20359 
20360  //
20361 
20362 
20363 
20364  function setTexture2D( texture, slot ) {
20365 
20366  var textureProperties = properties.get( texture );
20367 
20368  if ( texture.isVideoTexture ) updateVideoTexture( texture );
20369 
20370  if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
20371 
20372  var image = texture.image;
20373 
20374  if ( image === undefined ) {
20375 
20376  console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is undefined' );
20377 
20378  } else if ( image.complete === false ) {
20379 
20380  console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is incomplete' );
20381 
20382  } else {
20383 
20384  uploadTexture( textureProperties, texture, slot );
20385  return;
20386 
20387  }
20388 
20389  }
20390 
20391  state.activeTexture( 33984 + slot );
20392  state.bindTexture( 3553, textureProperties.__webglTexture );
20393 
20394  }
20395 
20396  function setTexture3D( texture, slot ) {
20397 
20398  var textureProperties = properties.get( texture );
20399 
20400  if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
20401 
20402  uploadTexture( textureProperties, texture, slot );
20403  return;
20404 
20405  }
20406 
20407  state.activeTexture( 33984 + slot );
20408  state.bindTexture( 32879, textureProperties.__webglTexture );
20409 
20410  }
20411 
20412  function setTextureCube( texture, slot ) {
20413 
20414  var textureProperties = properties.get( texture );
20415 
20416  if ( texture.image.length === 6 ) {
20417 
20418  if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
20419 
20420  initTexture( textureProperties, texture );
20421 
20422  state.activeTexture( 33984 + slot );
20423  state.bindTexture( 34067, textureProperties.__webglTexture );
20424 
20425  _gl.pixelStorei( 37440, texture.flipY );
20426 
20427  var isCompressed = ( texture && texture.isCompressedTexture );
20428  var isDataTexture = ( texture.image[ 0 ] && texture.image[ 0 ].isDataTexture );
20429 
20430  var cubeImage = [];
20431 
20432  for ( var i = 0; i < 6; i ++ ) {
20433 
20434  if ( ! isCompressed && ! isDataTexture ) {
20435 
20436  cubeImage[ i ] = resizeImage( texture.image[ i ], false, true, capabilities.maxCubemapSize );
20437 
20438  } else {
20439 
20440  cubeImage[ i ] = isDataTexture ? texture.image[ i ].image : texture.image[ i ];
20441 
20442  }
20443 
20444  }
20445 
20446  var image = cubeImage[ 0 ],
20447  supportsMips = isPowerOfTwo( image ) || capabilities.isWebGL2,
20448  glFormat = utils.convert( texture.format ),
20449  glType = utils.convert( texture.type ),
20450  glInternalFormat = getInternalFormat( glFormat, glType );
20451 
20452  setTextureParameters( 34067, texture, supportsMips );
20453 
20454  for ( var i = 0; i < 6; i ++ ) {
20455 
20456  if ( ! isCompressed ) {
20457 
20458  if ( isDataTexture ) {
20459 
20460  state.texImage2D( 34069 + i, 0, glInternalFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data );
20461 
20462  } else {
20463 
20464  state.texImage2D( 34069 + i, 0, glInternalFormat, glFormat, glType, cubeImage[ i ] );
20465 
20466  }
20467 
20468  } else {
20469 
20470  var mipmap, mipmaps = cubeImage[ i ].mipmaps;
20471 
20472  for ( var j = 0, jl = mipmaps.length; j < jl; j ++ ) {
20473 
20474  mipmap = mipmaps[ j ];
20475 
20476  if ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) {
20477 
20478  if ( state.getCompressedTextureFormats().indexOf( glFormat ) > - 1 ) {
20479 
20480  state.compressedTexImage2D( 34069 + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );
20481 
20482  } else {
20483 
20484  console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()' );
20485 
20486  }
20487 
20488  } else {
20489 
20490  state.texImage2D( 34069 + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
20491 
20492  }
20493 
20494  }
20495 
20496  }
20497 
20498  }
20499 
20500  if ( ! isCompressed ) {
20501 
20502  textureProperties.__maxMipLevel = 0;
20503 
20504  } else {
20505 
20506  textureProperties.__maxMipLevel = mipmaps.length - 1;
20507 
20508  }
20509 
20510  if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {
20511 
20512  // We assume images for cube map have the same size.
20513  generateMipmap( 34067, texture, image.width, image.height );
20514 
20515  }
20516 
20517  textureProperties.__version = texture.version;
20518 
20519  if ( texture.onUpdate ) texture.onUpdate( texture );
20520 
20521  } else {
20522 
20523  state.activeTexture( 33984 + slot );
20524  state.bindTexture( 34067, textureProperties.__webglTexture );
20525 
20526  }
20527 
20528  }
20529 
20530  }
20531 
20532  function setTextureCubeDynamic( texture, slot ) {
20533 
20534  state.activeTexture( 33984 + slot );
20535  state.bindTexture( 34067, properties.get( texture ).__webglTexture );
20536 
20537  }
20538 
20539  function setTextureParameters( textureType, texture, supportsMips ) {
20540 
20541  var extension;
20542 
20543  if ( supportsMips ) {
20544 
20545  _gl.texParameteri( textureType, 10242, utils.convert( texture.wrapS ) );
20546  _gl.texParameteri( textureType, 10243, utils.convert( texture.wrapT ) );
20547 
20548  if ( textureType === 32879 ) {
20549 
20550  _gl.texParameteri( textureType, 32882, utils.convert( texture.wrapR ) );
20551 
20552  }
20553 
20554  _gl.texParameteri( textureType, 10240, utils.convert( texture.magFilter ) );
20555  _gl.texParameteri( textureType, 10241, utils.convert( texture.minFilter ) );
20556 
20557  } else {
20558 
20559  _gl.texParameteri( textureType, 10242, 33071 );
20560  _gl.texParameteri( textureType, 10243, 33071 );
20561 
20562  if ( textureType === 32879 ) {
20563 
20564  _gl.texParameteri( textureType, 32882, 33071 );
20565 
20566  }
20567 
20568  if ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) {
20569 
20570  console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping.' );
20571 
20572  }
20573 
20574  _gl.texParameteri( textureType, 10240, filterFallback( texture.magFilter ) );
20575  _gl.texParameteri( textureType, 10241, filterFallback( texture.minFilter ) );
20576 
20577  if ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ) {
20578 
20579  console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.' );
20580 
20581  }
20582 
20583  }
20584 
20585  extension = extensions.get( 'EXT_texture_filter_anisotropic' );
20586 
20587  if ( extension ) {
20588 
20589  if ( texture.type === FloatType && extensions.get( 'OES_texture_float_linear' ) === null ) return;
20590  if ( texture.type === HalfFloatType && ( capabilities.isWebGL2 || extensions.get( 'OES_texture_half_float_linear' ) ) === null ) return;
20591 
20592  if ( texture.anisotropy > 1 || properties.get( texture ).__currentAnisotropy ) {
20593 
20594  _gl.texParameterf( textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, capabilities.getMaxAnisotropy() ) );
20595  properties.get( texture ).__currentAnisotropy = texture.anisotropy;
20596 
20597  }
20598 
20599  }
20600 
20601  }
20602 
20603  function initTexture( textureProperties, texture ) {
20604 
20605  if ( textureProperties.__webglInit === undefined ) {
20606 
20607  textureProperties.__webglInit = true;
20608 
20609  texture.addEventListener( 'dispose', onTextureDispose );
20610 
20611  textureProperties.__webglTexture = _gl.createTexture();
20612 
20613  info.memory.textures ++;
20614 
20615  }
20616 
20617  }
20618 
20619  function uploadTexture( textureProperties, texture, slot ) {
20620 
20621  var textureType = ( texture.isDataTexture3D ) ? 32879 : 3553;
20622 
20623  initTexture( textureProperties, texture );
20624 
20625  state.activeTexture( 33984 + slot );
20626  state.bindTexture( textureType, textureProperties.__webglTexture );
20627 
20628  _gl.pixelStorei( 37440, texture.flipY );
20629  _gl.pixelStorei( 37441, texture.premultiplyAlpha );
20630  _gl.pixelStorei( 3317, texture.unpackAlignment );
20631 
20632  var needsPowerOfTwo = textureNeedsPowerOfTwo( texture ) && isPowerOfTwo( texture.image ) === false;
20633  var image = resizeImage( texture.image, needsPowerOfTwo, false, capabilities.maxTextureSize );
20634 
20635  var supportsMips = isPowerOfTwo( image ) || capabilities.isWebGL2,
20636  glFormat = utils.convert( texture.format ),
20637  glType = utils.convert( texture.type ),
20638  glInternalFormat = getInternalFormat( glFormat, glType );
20639 
20640  setTextureParameters( textureType, texture, supportsMips );
20641 
20642  var mipmap, mipmaps = texture.mipmaps;
20643 
20644  if ( texture.isDepthTexture ) {
20645 
20646  // populate depth texture with dummy data
20647 
20648  glInternalFormat = 6402;
20649 
20650  if ( texture.type === FloatType ) {
20651 
20652  if ( ! capabilities.isWebGL2 ) throw new Error( 'Float Depth Texture only supported in WebGL2.0' );
20653  glInternalFormat = 36012;
20654 
20655  } else if ( capabilities.isWebGL2 ) {
20656 
20657  // WebGL 2.0 requires signed internalformat for glTexImage2D
20658  glInternalFormat = 33189;
20659 
20660  }
20661 
20662  if ( texture.format === DepthFormat && glInternalFormat === 6402 ) {
20663 
20664  // The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
20665  // DEPTH_COMPONENT and type is not UNSIGNED_SHORT or UNSIGNED_INT
20666  // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
20667  if ( texture.type !== UnsignedShortType && texture.type !== UnsignedIntType ) {
20668 
20669  console.warn( 'THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture.' );
20670 
20671  texture.type = UnsignedShortType;
20672  glType = utils.convert( texture.type );
20673 
20674  }
20675 
20676  }
20677 
20678  // Depth stencil textures need the DEPTH_STENCIL internal format
20679  // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
20680  if ( texture.format === DepthStencilFormat ) {
20681 
20682  glInternalFormat = 34041;
20683 
20684  // The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
20685  // DEPTH_STENCIL and type is not UNSIGNED_INT_24_8_WEBGL.
20686  // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
20687  if ( texture.type !== UnsignedInt248Type ) {
20688 
20689  console.warn( 'THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture.' );
20690 
20691  texture.type = UnsignedInt248Type;
20692  glType = utils.convert( texture.type );
20693 
20694  }
20695 
20696  }
20697 
20698  state.texImage2D( 3553, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, null );
20699 
20700  } else if ( texture.isDataTexture ) {
20701 
20702  // use manually created mipmaps if available
20703  // if there are no manual mipmaps
20704  // set 0 level mipmap and then use GL to generate other mipmap levels
20705 
20706  if ( mipmaps.length > 0 && supportsMips ) {
20707 
20708  for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
20709 
20710  mipmap = mipmaps[ i ];
20711  state.texImage2D( 3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
20712 
20713  }
20714 
20715  texture.generateMipmaps = false;
20716  textureProperties.__maxMipLevel = mipmaps.length - 1;
20717 
20718  } else {
20719 
20720  state.texImage2D( 3553, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, image.data );
20721  textureProperties.__maxMipLevel = 0;
20722 
20723  }
20724 
20725  } else if ( texture.isCompressedTexture ) {
20726 
20727  for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
20728 
20729  mipmap = mipmaps[ i ];
20730 
20731  if ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) {
20732 
20733  if ( state.getCompressedTextureFormats().indexOf( glFormat ) > - 1 ) {
20734 
20735  state.compressedTexImage2D( 3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );
20736 
20737  } else {
20738 
20739  console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' );
20740 
20741  }
20742 
20743  } else {
20744 
20745  state.texImage2D( 3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
20746 
20747  }
20748 
20749  }
20750 
20751  textureProperties.__maxMipLevel = mipmaps.length - 1;
20752 
20753  } else if ( texture.isDataTexture3D ) {
20754 
20755  state.texImage3D( 32879, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data );
20756  textureProperties.__maxMipLevel = 0;
20757 
20758  } else {
20759 
20760  // regular Texture (image, video, canvas)
20761 
20762  // use manually created mipmaps if available
20763  // if there are no manual mipmaps
20764  // set 0 level mipmap and then use GL to generate other mipmap levels
20765 
20766  if ( mipmaps.length > 0 && supportsMips ) {
20767 
20768  for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
20769 
20770  mipmap = mipmaps[ i ];
20771  state.texImage2D( 3553, i, glInternalFormat, glFormat, glType, mipmap );
20772 
20773  }
20774 
20775  texture.generateMipmaps = false;
20776  textureProperties.__maxMipLevel = mipmaps.length - 1;
20777 
20778  } else {
20779 
20780  state.texImage2D( 3553, 0, glInternalFormat, glFormat, glType, image );
20781  textureProperties.__maxMipLevel = 0;
20782 
20783  }
20784 
20785  }
20786 
20787  if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {
20788 
20789  generateMipmap( 3553, texture, image.width, image.height );
20790 
20791  }
20792 
20793  textureProperties.__version = texture.version;
20794 
20795  if ( texture.onUpdate ) texture.onUpdate( texture );
20796 
20797  }
20798 
20799  // Render targets
20800 
20801  // Setup storage for target texture and bind it to correct framebuffer
20802  function setupFrameBufferTexture( framebuffer, renderTarget, attachment, textureTarget ) {
20803 
20804  var glFormat = utils.convert( renderTarget.texture.format );
20805  var glType = utils.convert( renderTarget.texture.type );
20806  var glInternalFormat = getInternalFormat( glFormat, glType );
20807  state.texImage2D( textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
20808  _gl.bindFramebuffer( 36160, framebuffer );
20809  _gl.framebufferTexture2D( 36160, attachment, textureTarget, properties.get( renderTarget.texture ).__webglTexture, 0 );
20810  _gl.bindFramebuffer( 36160, null );
20811 
20812  }
20813 
20814  // Setup storage for internal depth/stencil buffers and bind to correct framebuffer
20815  function setupRenderBufferStorage( renderbuffer, renderTarget, isMultisample ) {
20816 
20817  _gl.bindRenderbuffer( 36161, renderbuffer );
20818 
20819  if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) {
20820 
20821  if ( isMultisample ) {
20822 
20823  var samples = getRenderTargetSamples( renderTarget );
20824 
20825  _gl.renderbufferStorageMultisample( 36161, samples, 33189, renderTarget.width, renderTarget.height );
20826 
20827  } else {
20828 
20829  _gl.renderbufferStorage( 36161, 33189, renderTarget.width, renderTarget.height );
20830 
20831  }
20832 
20833  _gl.framebufferRenderbuffer( 36160, 36096, 36161, renderbuffer );
20834 
20835  } else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
20836 
20837  if ( isMultisample ) {
20838 
20839  var samples = getRenderTargetSamples( renderTarget );
20840 
20841  _gl.renderbufferStorageMultisample( 36161, samples, 34041, renderTarget.width, renderTarget.height );
20842 
20843  } else {
20844 
20845  _gl.renderbufferStorage( 36161, 34041, renderTarget.width, renderTarget.height );
20846 
20847  }
20848 
20849 
20850  _gl.framebufferRenderbuffer( 36160, 33306, 36161, renderbuffer );
20851 
20852  } else {
20853 
20854  var glFormat = utils.convert( renderTarget.texture.format );
20855  var glType = utils.convert( renderTarget.texture.type );
20856  var glInternalFormat = getInternalFormat( glFormat, glType );
20857 
20858  if ( isMultisample ) {
20859 
20860  var samples = getRenderTargetSamples( renderTarget );
20861 
20862  _gl.renderbufferStorageMultisample( 36161, samples, glInternalFormat, renderTarget.width, renderTarget.height );
20863 
20864  } else {
20865 
20866  _gl.renderbufferStorage( 36161, glInternalFormat, renderTarget.width, renderTarget.height );
20867 
20868  }
20869 
20870  }
20871 
20872  _gl.bindRenderbuffer( 36161, null );
20873 
20874  }
20875 
20876  // Setup resources for a Depth Texture for a FBO (needs an extension)
20877  function setupDepthTexture( framebuffer, renderTarget ) {
20878 
20879  var isCube = ( renderTarget && renderTarget.isWebGLRenderTargetCube );
20880  if ( isCube ) throw new Error( 'Depth Texture with cube render targets is not supported' );
20881 
20882  _gl.bindFramebuffer( 36160, framebuffer );
20883 
20884  if ( ! ( renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture ) ) {
20885 
20886  throw new Error( 'renderTarget.depthTexture must be an instance of THREE.DepthTexture' );
20887 
20888  }
20889 
20890  // upload an empty depth texture with framebuffer size
20891  if ( ! properties.get( renderTarget.depthTexture ).__webglTexture ||
20892  renderTarget.depthTexture.image.width !== renderTarget.width ||
20893  renderTarget.depthTexture.image.height !== renderTarget.height ) {
20894 
20895  renderTarget.depthTexture.image.width = renderTarget.width;
20896  renderTarget.depthTexture.image.height = renderTarget.height;
20897  renderTarget.depthTexture.needsUpdate = true;
20898 
20899  }
20900 
20901  setTexture2D( renderTarget.depthTexture, 0 );
20902 
20903  var webglDepthTexture = properties.get( renderTarget.depthTexture ).__webglTexture;
20904 
20905  if ( renderTarget.depthTexture.format === DepthFormat ) {
20906 
20907  _gl.framebufferTexture2D( 36160, 36096, 3553, webglDepthTexture, 0 );
20908 
20909  } else if ( renderTarget.depthTexture.format === DepthStencilFormat ) {
20910 
20911  _gl.framebufferTexture2D( 36160, 33306, 3553, webglDepthTexture, 0 );
20912 
20913  } else {
20914 
20915  throw new Error( 'Unknown depthTexture format' );
20916 
20917  }
20918 
20919  }
20920 
20921  // Setup GL resources for a non-texture depth buffer
20922  function setupDepthRenderbuffer( renderTarget ) {
20923 
20924  var renderTargetProperties = properties.get( renderTarget );
20925 
20926  var isCube = ( renderTarget.isWebGLRenderTargetCube === true );
20927 
20928  if ( renderTarget.depthTexture ) {
20929 
20930  if ( isCube ) throw new Error( 'target.depthTexture not supported in Cube render targets' );
20931 
20932  setupDepthTexture( renderTargetProperties.__webglFramebuffer, renderTarget );
20933 
20934  } else {
20935 
20936  if ( isCube ) {
20937 
20938  renderTargetProperties.__webglDepthbuffer = [];
20939 
20940  for ( var i = 0; i < 6; i ++ ) {
20941 
20942  _gl.bindFramebuffer( 36160, renderTargetProperties.__webglFramebuffer[ i ] );
20943  renderTargetProperties.__webglDepthbuffer[ i ] = _gl.createRenderbuffer();
20944  setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer[ i ], renderTarget );
20945 
20946  }
20947 
20948  } else {
20949 
20950  _gl.bindFramebuffer( 36160, renderTargetProperties.__webglFramebuffer );
20951  renderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer();
20952  setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer, renderTarget );
20953 
20954  }
20955 
20956  }
20957 
20958  _gl.bindFramebuffer( 36160, null );
20959 
20960  }
20961 
20962  // Set up GL resources for the render target
20963  function setupRenderTarget( renderTarget ) {
20964 
20965  var renderTargetProperties = properties.get( renderTarget );
20966  var textureProperties = properties.get( renderTarget.texture );
20967 
20968  renderTarget.addEventListener( 'dispose', onRenderTargetDispose );
20969 
20970  textureProperties.__webglTexture = _gl.createTexture();
20971 
20972  info.memory.textures ++;
20973 
20974  var isCube = ( renderTarget.isWebGLRenderTargetCube === true );
20975  var isMultisample = ( renderTarget.isWebGLMultisampleRenderTarget === true );
20976  var supportsMips = isPowerOfTwo( renderTarget ) || capabilities.isWebGL2;
20977 
20978  // Setup framebuffer
20979 
20980  if ( isCube ) {
20981 
20982  renderTargetProperties.__webglFramebuffer = [];
20983 
20984  for ( var i = 0; i < 6; i ++ ) {
20985 
20986  renderTargetProperties.__webglFramebuffer[ i ] = _gl.createFramebuffer();
20987 
20988  }
20989 
20990  } else {
20991 
20992  renderTargetProperties.__webglFramebuffer = _gl.createFramebuffer();
20993 
20994  if ( isMultisample ) {
20995 
20996  if ( capabilities.isWebGL2 ) {
20997 
20998  renderTargetProperties.__webglMultisampledFramebuffer = _gl.createFramebuffer();
20999  renderTargetProperties.__webglColorRenderbuffer = _gl.createRenderbuffer();
21000 
21001  _gl.bindRenderbuffer( 36161, renderTargetProperties.__webglColorRenderbuffer );
21002  var glFormat = utils.convert( renderTarget.texture.format );
21003  var glType = utils.convert( renderTarget.texture.type );
21004  var glInternalFormat = getInternalFormat( glFormat, glType );
21005  var samples = getRenderTargetSamples( renderTarget );
21006  _gl.renderbufferStorageMultisample( 36161, samples, glInternalFormat, renderTarget.width, renderTarget.height );
21007 
21008  _gl.bindFramebuffer( 36160, renderTargetProperties.__webglMultisampledFramebuffer );
21009  _gl.framebufferRenderbuffer( 36160, 36064, 36161, renderTargetProperties.__webglColorRenderbuffer );
21010  _gl.bindRenderbuffer( 36161, null );
21011 
21012  if ( renderTarget.depthBuffer ) {
21013 
21014  renderTargetProperties.__webglDepthRenderbuffer = _gl.createRenderbuffer();
21015  setupRenderBufferStorage( renderTargetProperties.__webglDepthRenderbuffer, renderTarget, true );
21016 
21017  }
21018 
21019  _gl.bindFramebuffer( 36160, null );
21020 
21021 
21022  } else {
21023 
21024  console.warn( 'THREE.WebGLRenderer: WebGLMultisampleRenderTarget can only be used with WebGL2.' );
21025 
21026  }
21027 
21028  }
21029 
21030  }
21031 
21032  // Setup color buffer
21033 
21034  if ( isCube ) {
21035 
21036  state.bindTexture( 34067, textureProperties.__webglTexture );
21037  setTextureParameters( 34067, renderTarget.texture, supportsMips );
21038 
21039  for ( var i = 0; i < 6; i ++ ) {
21040 
21041  setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ], renderTarget, 36064, 34069 + i );
21042 
21043  }
21044 
21045  if ( textureNeedsGenerateMipmaps( renderTarget.texture, supportsMips ) ) {
21046 
21047  generateMipmap( 34067, renderTarget.texture, renderTarget.width, renderTarget.height );
21048 
21049  }
21050 
21051  state.bindTexture( 34067, null );
21052 
21053  } else {
21054 
21055  state.bindTexture( 3553, textureProperties.__webglTexture );
21056  setTextureParameters( 3553, renderTarget.texture, supportsMips );
21057  setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, 36064, 3553 );
21058 
21059  if ( textureNeedsGenerateMipmaps( renderTarget.texture, supportsMips ) ) {
21060 
21061  generateMipmap( 3553, renderTarget.texture, renderTarget.width, renderTarget.height );
21062 
21063  }
21064 
21065  state.bindTexture( 3553, null );
21066 
21067  }
21068 
21069  // Setup depth and stencil buffers
21070 
21071  if ( renderTarget.depthBuffer ) {
21072 
21073  setupDepthRenderbuffer( renderTarget );
21074 
21075  }
21076 
21077  }
21078 
21079  function updateRenderTargetMipmap( renderTarget ) {
21080 
21081  var texture = renderTarget.texture;
21082  var supportsMips = isPowerOfTwo( renderTarget ) || capabilities.isWebGL2;
21083 
21084  if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {
21085 
21086  var target = renderTarget.isWebGLRenderTargetCube ? 34067 : 3553;
21087  var webglTexture = properties.get( texture ).__webglTexture;
21088 
21089  state.bindTexture( target, webglTexture );
21090  generateMipmap( target, texture, renderTarget.width, renderTarget.height );
21091  state.bindTexture( target, null );
21092 
21093  }
21094 
21095  }
21096 
21097  function updateMultisampleRenderTarget( renderTarget ) {
21098 
21099  if ( renderTarget.isWebGLMultisampleRenderTarget ) {
21100 
21101  if ( capabilities.isWebGL2 ) {
21102 
21103  var renderTargetProperties = properties.get( renderTarget );
21104 
21105  _gl.bindFramebuffer( 36008, renderTargetProperties.__webglMultisampledFramebuffer );
21106  _gl.bindFramebuffer( 36009, renderTargetProperties.__webglFramebuffer );
21107 
21108  var width = renderTarget.width;
21109  var height = renderTarget.height;
21110  var mask = 16384;
21111 
21112  if ( renderTarget.depthBuffer ) mask |= 256;
21113  if ( renderTarget.stencilBuffer ) mask |= 1024;
21114 
21115  _gl.blitFramebuffer( 0, 0, width, height, 0, 0, width, height, mask, 9728 );
21116 
21117  } else {
21118 
21119  console.warn( 'THREE.WebGLRenderer: WebGLMultisampleRenderTarget can only be used with WebGL2.' );
21120 
21121  }
21122 
21123  }
21124 
21125  }
21126 
21127  function getRenderTargetSamples( renderTarget ) {
21128 
21129  return ( capabilities.isWebGL2 && renderTarget.isWebGLMultisampleRenderTarget ) ?
21130  Math.min( capabilities.maxSamples, renderTarget.samples ) : 0;
21131 
21132  }
21133 
21134  function updateVideoTexture( texture ) {
21135 
21136  var id = texture.id;
21137  var frame = info.render.frame;
21138 
21139  // Check the last frame we updated the VideoTexture
21140 
21141  if ( _videoTextures[ id ] !== frame ) {
21142 
21143  _videoTextures[ id ] = frame;
21144  texture.update();
21145 
21146  }
21147 
21148  }
21149 
21150  this.setTexture2D = setTexture2D;
21151  this.setTexture3D = setTexture3D;
21152  this.setTextureCube = setTextureCube;
21153  this.setTextureCubeDynamic = setTextureCubeDynamic;
21154  this.setupRenderTarget = setupRenderTarget;
21155  this.updateRenderTargetMipmap = updateRenderTargetMipmap;
21156  this.updateMultisampleRenderTarget = updateMultisampleRenderTarget;
21157 
21158  }
21159 
21164  function WebGLUtils( gl, extensions, capabilities ) {
21165 
21166  function convert( p ) {
21167 
21168  var extension;
21169 
21170  if ( p === RepeatWrapping ) return 10497;
21171  if ( p === ClampToEdgeWrapping ) return 33071;
21172  if ( p === MirroredRepeatWrapping ) return 33648;
21173 
21174  if ( p === NearestFilter ) return 9728;
21175  if ( p === NearestMipMapNearestFilter ) return 9984;
21176  if ( p === NearestMipMapLinearFilter ) return 9986;
21177 
21178  if ( p === LinearFilter ) return 9729;
21179  if ( p === LinearMipMapNearestFilter ) return 9985;
21180  if ( p === LinearMipMapLinearFilter ) return 9987;
21181 
21182  if ( p === UnsignedByteType ) return 5121;
21183  if ( p === UnsignedShort4444Type ) return 32819;
21184  if ( p === UnsignedShort5551Type ) return 32820;
21185  if ( p === UnsignedShort565Type ) return 33635;
21186 
21187  if ( p === ByteType ) return 5120;
21188  if ( p === ShortType ) return 5122;
21189  if ( p === UnsignedShortType ) return 5123;
21190  if ( p === IntType ) return 5124;
21191  if ( p === UnsignedIntType ) return 5125;
21192  if ( p === FloatType ) return 5126;
21193 
21194  if ( p === HalfFloatType ) {
21195 
21196  if ( capabilities.isWebGL2 ) return 5131;
21197 
21198  extension = extensions.get( 'OES_texture_half_float' );
21199 
21200  if ( extension !== null ) return extension.HALF_FLOAT_OES;
21201 
21202  }
21203 
21204  if ( p === AlphaFormat ) return 6406;
21205  if ( p === RGBFormat ) return 6407;
21206  if ( p === RGBAFormat ) return 6408;
21207  if ( p === LuminanceFormat ) return 6409;
21208  if ( p === LuminanceAlphaFormat ) return 6410;
21209  if ( p === DepthFormat ) return 6402;
21210  if ( p === DepthStencilFormat ) return 34041;
21211  if ( p === RedFormat ) return 6403;
21212 
21213  if ( p === AddEquation ) return 32774;
21214  if ( p === SubtractEquation ) return 32778;
21215  if ( p === ReverseSubtractEquation ) return 32779;
21216 
21217  if ( p === ZeroFactor ) return 0;
21218  if ( p === OneFactor ) return 1;
21219  if ( p === SrcColorFactor ) return 768;
21220  if ( p === OneMinusSrcColorFactor ) return 769;
21221  if ( p === SrcAlphaFactor ) return 770;
21222  if ( p === OneMinusSrcAlphaFactor ) return 771;
21223  if ( p === DstAlphaFactor ) return 772;
21224  if ( p === OneMinusDstAlphaFactor ) return 773;
21225 
21226  if ( p === DstColorFactor ) return 774;
21227  if ( p === OneMinusDstColorFactor ) return 775;
21228  if ( p === SrcAlphaSaturateFactor ) return 776;
21229 
21230  if ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format ||
21231  p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) {
21232 
21233  extension = extensions.get( 'WEBGL_compressed_texture_s3tc' );
21234 
21235  if ( extension !== null ) {
21236 
21237  if ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT;
21238  if ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT;
21239  if ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT;
21240  if ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT;
21241 
21242  }
21243 
21244  }
21245 
21246  if ( p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format ||
21247  p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format ) {
21248 
21249  extension = extensions.get( 'WEBGL_compressed_texture_pvrtc' );
21250 
21251  if ( extension !== null ) {
21252 
21253  if ( p === RGB_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
21254  if ( p === RGB_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
21255  if ( p === RGBA_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
21256  if ( p === RGBA_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
21257 
21258  }
21259 
21260  }
21261 
21262  if ( p === RGB_ETC1_Format ) {
21263 
21264  extension = extensions.get( 'WEBGL_compressed_texture_etc1' );
21265 
21266  if ( extension !== null ) return extension.COMPRESSED_RGB_ETC1_WEBGL;
21267 
21268  }
21269 
21270  if ( p === RGBA_ASTC_4x4_Format || p === RGBA_ASTC_5x4_Format || p === RGBA_ASTC_5x5_Format ||
21271  p === RGBA_ASTC_6x5_Format || p === RGBA_ASTC_6x6_Format || p === RGBA_ASTC_8x5_Format ||
21272  p === RGBA_ASTC_8x6_Format || p === RGBA_ASTC_8x8_Format || p === RGBA_ASTC_10x5_Format ||
21273  p === RGBA_ASTC_10x6_Format || p === RGBA_ASTC_10x8_Format || p === RGBA_ASTC_10x10_Format ||
21274  p === RGBA_ASTC_12x10_Format || p === RGBA_ASTC_12x12_Format ) {
21275 
21276  extension = extensions.get( 'WEBGL_compressed_texture_astc' );
21277 
21278  if ( extension !== null ) {
21279 
21280  return p;
21281 
21282  }
21283 
21284  }
21285 
21286  if ( p === MinEquation || p === MaxEquation ) {
21287 
21288  if ( capabilities.isWebGL2 ) {
21289 
21290  if ( p === MinEquation ) return 32775;
21291  if ( p === MaxEquation ) return 32776;
21292 
21293  }
21294 
21295  extension = extensions.get( 'EXT_blend_minmax' );
21296 
21297  if ( extension !== null ) {
21298 
21299  if ( p === MinEquation ) return extension.MIN_EXT;
21300  if ( p === MaxEquation ) return extension.MAX_EXT;
21301 
21302  }
21303 
21304  }
21305 
21306  if ( p === UnsignedInt248Type ) {
21307 
21308  if ( capabilities.isWebGL2 ) return 34042;
21309 
21310  extension = extensions.get( 'WEBGL_depth_texture' );
21311 
21312  if ( extension !== null ) return extension.UNSIGNED_INT_24_8_WEBGL;
21313 
21314  }
21315 
21316  return 0;
21317 
21318  }
21319 
21320  return { convert: convert };
21321 
21322  }
21323 
21328  function Group() {
21329 
21330  Object3D.call( this );
21331 
21332  this.type = 'Group';
21333 
21334  }
21335 
21336  Group.prototype = Object.assign( Object.create( Object3D.prototype ), {
21337 
21338  constructor: Group,
21339 
21340  isGroup: true
21341 
21342  } );
21343 
21350  function Camera() {
21351 
21352  Object3D.call( this );
21353 
21354  this.type = 'Camera';
21355 
21356  this.matrixWorldInverse = new Matrix4();
21357 
21358  this.projectionMatrix = new Matrix4();
21359  this.projectionMatrixInverse = new Matrix4();
21360 
21361  }
21362 
21363  Camera.prototype = Object.assign( Object.create( Object3D.prototype ), {
21364 
21365  constructor: Camera,
21366 
21367  isCamera: true,
21368 
21369  copy: function ( source, recursive ) {
21370 
21371  Object3D.prototype.copy.call( this, source, recursive );
21372 
21373  this.matrixWorldInverse.copy( source.matrixWorldInverse );
21374 
21375  this.projectionMatrix.copy( source.projectionMatrix );
21376  this.projectionMatrixInverse.copy( source.projectionMatrixInverse );
21377 
21378  return this;
21379 
21380  },
21381 
21382  getWorldDirection: function ( target ) {
21383 
21384  if ( target === undefined ) {
21385 
21386  console.warn( 'THREE.Camera: .getWorldDirection() target is now required' );
21387  target = new Vector3();
21388 
21389  }
21390 
21391  this.updateMatrixWorld( true );
21392 
21393  var e = this.matrixWorld.elements;
21394 
21395  return target.set( - e[ 8 ], - e[ 9 ], - e[ 10 ] ).normalize();
21396 
21397  },
21398 
21399  updateMatrixWorld: function ( force ) {
21400 
21401  Object3D.prototype.updateMatrixWorld.call( this, force );
21402 
21403  this.matrixWorldInverse.getInverse( this.matrixWorld );
21404 
21405  },
21406 
21407  clone: function () {
21408 
21409  return new this.constructor().copy( this );
21410 
21411  }
21412 
21413  } );
21414 
21422  function PerspectiveCamera( fov, aspect, near, far ) {
21423 
21424  Camera.call( this );
21425 
21426  this.type = 'PerspectiveCamera';
21427 
21428  this.fov = fov !== undefined ? fov : 50;
21429  this.zoom = 1;
21430 
21431  this.near = near !== undefined ? near : 0.1;
21432  this.far = far !== undefined ? far : 2000;
21433  this.focus = 10;
21434 
21435  this.aspect = aspect !== undefined ? aspect : 1;
21436  this.view = null;
21437 
21438  this.filmGauge = 35; // width of the film (default in millimeters)
21439  this.filmOffset = 0; // horizontal film offset (same unit as gauge)
21440 
21441  this.updateProjectionMatrix();
21442 
21443  }
21444 
21445  PerspectiveCamera.prototype = Object.assign( Object.create( Camera.prototype ), {
21446 
21447  constructor: PerspectiveCamera,
21448 
21449  isPerspectiveCamera: true,
21450 
21451  copy: function ( source, recursive ) {
21452 
21453  Camera.prototype.copy.call( this, source, recursive );
21454 
21455  this.fov = source.fov;
21456  this.zoom = source.zoom;
21457 
21458  this.near = source.near;
21459  this.far = source.far;
21460  this.focus = source.focus;
21461 
21462  this.aspect = source.aspect;
21463  this.view = source.view === null ? null : Object.assign( {}, source.view );
21464 
21465  this.filmGauge = source.filmGauge;
21466  this.filmOffset = source.filmOffset;
21467 
21468  return this;
21469 
21470  },
21471 
21480  setFocalLength: function ( focalLength ) {
21481 
21482  // see http://www.bobatkins.com/photography/technical/field_of_view.html
21483  var vExtentSlope = 0.5 * this.getFilmHeight() / focalLength;
21484 
21485  this.fov = _Math.RAD2DEG * 2 * Math.atan( vExtentSlope );
21486  this.updateProjectionMatrix();
21487 
21488  },
21489 
21493  getFocalLength: function () {
21494 
21495  var vExtentSlope = Math.tan( _Math.DEG2RAD * 0.5 * this.fov );
21496 
21497  return 0.5 * this.getFilmHeight() / vExtentSlope;
21498 
21499  },
21500 
21501  getEffectiveFOV: function () {
21502 
21503  return _Math.RAD2DEG * 2 * Math.atan(
21504  Math.tan( _Math.DEG2RAD * 0.5 * this.fov ) / this.zoom );
21505 
21506  },
21507 
21508  getFilmWidth: function () {
21509 
21510  // film not completely covered in portrait format (aspect < 1)
21511  return this.filmGauge * Math.min( this.aspect, 1 );
21512 
21513  },
21514 
21515  getFilmHeight: function () {
21516 
21517  // film not completely covered in landscape format (aspect > 1)
21518  return this.filmGauge / Math.max( this.aspect, 1 );
21519 
21520  },
21521 
21557  setViewOffset: function ( fullWidth, fullHeight, x, y, width, height ) {
21558 
21559  this.aspect = fullWidth / fullHeight;
21560 
21561  if ( this.view === null ) {
21562 
21563  this.view = {
21564  enabled: true,
21565  fullWidth: 1,
21566  fullHeight: 1,
21567  offsetX: 0,
21568  offsetY: 0,
21569  width: 1,
21570  height: 1
21571  };
21572 
21573  }
21574 
21575  this.view.enabled = true;
21576  this.view.fullWidth = fullWidth;
21577  this.view.fullHeight = fullHeight;
21578  this.view.offsetX = x;
21579  this.view.offsetY = y;
21580  this.view.width = width;
21581  this.view.height = height;
21582 
21583  this.updateProjectionMatrix();
21584 
21585  },
21586 
21587  clearViewOffset: function () {
21588 
21589  if ( this.view !== null ) {
21590 
21591  this.view.enabled = false;
21592 
21593  }
21594 
21595  this.updateProjectionMatrix();
21596 
21597  },
21598 
21599  updateProjectionMatrix: function () {
21600 
21601  var near = this.near,
21602  top = near * Math.tan( _Math.DEG2RAD * 0.5 * this.fov ) / this.zoom,
21603  height = 2 * top,
21604  width = this.aspect * height,
21605  left = - 0.5 * width,
21606  view = this.view;
21607 
21608  if ( this.view !== null && this.view.enabled ) {
21609 
21610  var fullWidth = view.fullWidth,
21611  fullHeight = view.fullHeight;
21612 
21613  left += view.offsetX * width / fullWidth;
21614  top -= view.offsetY * height / fullHeight;
21615  width *= view.width / fullWidth;
21616  height *= view.height / fullHeight;
21617 
21618  }
21619 
21620  var skew = this.filmOffset;
21621  if ( skew !== 0 ) left += near * skew / this.getFilmWidth();
21622 
21623  this.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far );
21624 
21625  this.projectionMatrixInverse.getInverse( this.projectionMatrix );
21626 
21627  },
21628 
21629  toJSON: function ( meta ) {
21630 
21631  var data = Object3D.prototype.toJSON.call( this, meta );
21632 
21633  data.object.fov = this.fov;
21634  data.object.zoom = this.zoom;
21635 
21636  data.object.near = this.near;
21637  data.object.far = this.far;
21638  data.object.focus = this.focus;
21639 
21640  data.object.aspect = this.aspect;
21641 
21642  if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
21643 
21644  data.object.filmGauge = this.filmGauge;
21645  data.object.filmOffset = this.filmOffset;
21646 
21647  return data;
21648 
21649  }
21650 
21651  } );
21652 
21657  function ArrayCamera( array ) {
21658 
21659  PerspectiveCamera.call( this );
21660 
21661  this.cameras = array || [];
21662 
21663  }
21664 
21665  ArrayCamera.prototype = Object.assign( Object.create( PerspectiveCamera.prototype ), {
21666 
21667  constructor: ArrayCamera,
21668 
21669  isArrayCamera: true
21670 
21671  } );
21672 
21678  var cameraLPos = new Vector3();
21679  var cameraRPos = new Vector3();
21680 
21687  function setProjectionFromUnion( camera, cameraL, cameraR ) {
21688 
21689  cameraLPos.setFromMatrixPosition( cameraL.matrixWorld );
21690  cameraRPos.setFromMatrixPosition( cameraR.matrixWorld );
21691 
21692  var ipd = cameraLPos.distanceTo( cameraRPos );
21693 
21694  var projL = cameraL.projectionMatrix.elements;
21695  var projR = cameraR.projectionMatrix.elements;
21696 
21697  // VR systems will have identical far and near planes, and
21698  // most likely identical top and bottom frustum extents.
21699  // Use the left camera for these values.
21700  var near = projL[ 14 ] / ( projL[ 10 ] - 1 );
21701  var far = projL[ 14 ] / ( projL[ 10 ] + 1 );
21702  var topFov = ( projL[ 9 ] + 1 ) / projL[ 5 ];
21703  var bottomFov = ( projL[ 9 ] - 1 ) / projL[ 5 ];
21704 
21705  var leftFov = ( projL[ 8 ] - 1 ) / projL[ 0 ];
21706  var rightFov = ( projR[ 8 ] + 1 ) / projR[ 0 ];
21707  var left = near * leftFov;
21708  var right = near * rightFov;
21709 
21710  // Calculate the new camera's position offset from the
21711  // left camera. xOffset should be roughly half `ipd`.
21712  var zOffset = ipd / ( - leftFov + rightFov );
21713  var xOffset = zOffset * - leftFov;
21714 
21715  // TODO: Better way to apply this offset?
21716  cameraL.matrixWorld.decompose( camera.position, camera.quaternion, camera.scale );
21717  camera.translateX( xOffset );
21718  camera.translateZ( zOffset );
21719  camera.matrixWorld.compose( camera.position, camera.quaternion, camera.scale );
21720  camera.matrixWorldInverse.getInverse( camera.matrixWorld );
21721 
21722  // Find the union of the frustum values of the cameras and scale
21723  // the values so that the near plane's position does not change in world space,
21724  // although must now be relative to the new union camera.
21725  var near2 = near + zOffset;
21726  var far2 = far + zOffset;
21727  var left2 = left - xOffset;
21728  var right2 = right + ( ipd - xOffset );
21729  var top2 = topFov * far / far2 * near2;
21730  var bottom2 = bottomFov * far / far2 * near2;
21731 
21732  camera.projectionMatrix.makePerspective( left2, right2, top2, bottom2, near2, far2 );
21733 
21734  }
21735 
21740  function WebVRManager( renderer ) {
21741 
21742  var scope = this;
21743 
21744  var device = null;
21745  var frameData = null;
21746 
21747  var poseTarget = null;
21748 
21749  var controllers = [];
21750  var standingMatrix = new Matrix4();
21751  var standingMatrixInverse = new Matrix4();
21752 
21753  var framebufferScaleFactor = 1.0;
21754 
21755  var frameOfReferenceType = 'stage';
21756 
21757  if ( typeof window !== 'undefined' && 'VRFrameData' in window ) {
21758 
21759  frameData = new window.VRFrameData();
21760  window.addEventListener( 'vrdisplaypresentchange', onVRDisplayPresentChange, false );
21761 
21762  }
21763 
21764  var matrixWorldInverse = new Matrix4();
21765  var tempQuaternion = new Quaternion();
21766  var tempPosition = new Vector3();
21767 
21768  var cameraL = new PerspectiveCamera();
21769  cameraL.bounds = new Vector4( 0.0, 0.0, 0.5, 1.0 );
21770  cameraL.layers.enable( 1 );
21771 
21772  var cameraR = new PerspectiveCamera();
21773  cameraR.bounds = new Vector4( 0.5, 0.0, 0.5, 1.0 );
21774  cameraR.layers.enable( 2 );
21775 
21776  var cameraVR = new ArrayCamera( [ cameraL, cameraR ] );
21777  cameraVR.layers.enable( 1 );
21778  cameraVR.layers.enable( 2 );
21779 
21780  //
21781 
21782  function isPresenting() {
21783 
21784  return device !== null && device.isPresenting === true;
21785 
21786  }
21787 
21788  var currentSize = new Vector2(), currentPixelRatio;
21789 
21790  function onVRDisplayPresentChange() {
21791 
21792  if ( isPresenting() ) {
21793 
21794  var eyeParameters = device.getEyeParameters( 'left' );
21795  var renderWidth = eyeParameters.renderWidth * framebufferScaleFactor;
21796  var renderHeight = eyeParameters.renderHeight * framebufferScaleFactor;
21797 
21798  currentPixelRatio = renderer.getPixelRatio();
21799  renderer.getSize( currentSize );
21800 
21801  renderer.setDrawingBufferSize( renderWidth * 2, renderHeight, 1 );
21802 
21803  animation.start();
21804 
21805  } else {
21806 
21807  if ( scope.enabled ) {
21808 
21809  renderer.setDrawingBufferSize( currentSize.width, currentSize.height, currentPixelRatio );
21810 
21811  }
21812 
21813  animation.stop();
21814 
21815  }
21816 
21817  }
21818 
21819  //
21820 
21821  var triggers = [];
21822 
21823  function findGamepad( id ) {
21824 
21825  var gamepads = navigator.getGamepads && navigator.getGamepads();
21826 
21827  for ( var i = 0, j = 0, l = gamepads.length; i < l; i ++ ) {
21828 
21829  var gamepad = gamepads[ i ];
21830 
21831  if ( gamepad && ( gamepad.id === 'Daydream Controller' ||
21832  gamepad.id === 'Gear VR Controller' || gamepad.id === 'Oculus Go Controller' ||
21833  gamepad.id === 'OpenVR Gamepad' || gamepad.id.startsWith( 'Oculus Touch' ) ||
21834  gamepad.id.startsWith( 'Spatial Controller' ) ) ) {
21835 
21836  if ( j === id ) return gamepad;
21837 
21838  j ++;
21839 
21840  }
21841 
21842  }
21843 
21844  }
21845 
21846  function updateControllers() {
21847 
21848  for ( var i = 0; i < controllers.length; i ++ ) {
21849 
21850  var controller = controllers[ i ];
21851 
21852  var gamepad = findGamepad( i );
21853 
21854  if ( gamepad !== undefined && gamepad.pose !== undefined ) {
21855 
21856  if ( gamepad.pose === null ) return;
21857 
21858  // Pose
21859 
21860  var pose = gamepad.pose;
21861 
21862  if ( pose.hasPosition === false ) controller.position.set( 0.2, - 0.6, - 0.05 );
21863 
21864  if ( pose.position !== null ) controller.position.fromArray( pose.position );
21865  if ( pose.orientation !== null ) controller.quaternion.fromArray( pose.orientation );
21866  controller.matrix.compose( controller.position, controller.quaternion, controller.scale );
21867  controller.matrix.premultiply( standingMatrix );
21868  controller.matrix.decompose( controller.position, controller.quaternion, controller.scale );
21869  controller.matrixWorldNeedsUpdate = true;
21870  controller.visible = true;
21871 
21872  // Trigger
21873 
21874  var buttonId = gamepad.id === 'Daydream Controller' ? 0 : 1;
21875 
21876  if ( triggers[ i ] !== gamepad.buttons[ buttonId ].pressed ) {
21877 
21878  triggers[ i ] = gamepad.buttons[ buttonId ].pressed;
21879 
21880  if ( triggers[ i ] === true ) {
21881 
21882  controller.dispatchEvent( { type: 'selectstart' } );
21883 
21884  } else {
21885 
21886  controller.dispatchEvent( { type: 'selectend' } );
21887  controller.dispatchEvent( { type: 'select' } );
21888 
21889  }
21890 
21891  }
21892 
21893  } else {
21894 
21895  controller.visible = false;
21896 
21897  }
21898 
21899  }
21900 
21901  }
21902 
21903  //
21904 
21905  this.enabled = false;
21906 
21907  this.getController = function ( id ) {
21908 
21909  var controller = controllers[ id ];
21910 
21911  if ( controller === undefined ) {
21912 
21913  controller = new Group();
21914  controller.matrixAutoUpdate = false;
21915  controller.visible = false;
21916 
21917  controllers[ id ] = controller;
21918 
21919  }
21920 
21921  return controller;
21922 
21923  };
21924 
21925  this.getDevice = function () {
21926 
21927  return device;
21928 
21929  };
21930 
21931  this.setDevice = function ( value ) {
21932 
21933  if ( value !== undefined ) device = value;
21934 
21935  animation.setContext( value );
21936 
21937  };
21938 
21939  this.setFramebufferScaleFactor = function ( value ) {
21940 
21941  framebufferScaleFactor = value;
21942 
21943  };
21944 
21945  this.setFrameOfReferenceType = function ( value ) {
21946 
21947  frameOfReferenceType = value;
21948 
21949  };
21950 
21951  this.setPoseTarget = function ( object ) {
21952 
21953  if ( object !== undefined ) poseTarget = object;
21954 
21955  };
21956 
21957  this.getCamera = function ( camera ) {
21958 
21959  var userHeight = frameOfReferenceType === 'stage' ? 1.6 : 0;
21960 
21961  if ( isPresenting() === false ) {
21962 
21963  camera.position.set( 0, userHeight, 0 );
21964  camera.rotation.set( 0, 0, 0 );
21965 
21966  return camera;
21967 
21968  }
21969 
21970  device.depthNear = camera.near;
21971  device.depthFar = camera.far;
21972 
21973  device.getFrameData( frameData );
21974 
21975  //
21976 
21977  if ( frameOfReferenceType === 'stage' ) {
21978 
21979  var stageParameters = device.stageParameters;
21980 
21981  if ( stageParameters ) {
21982 
21983  standingMatrix.fromArray( stageParameters.sittingToStandingTransform );
21984 
21985  } else {
21986 
21987  standingMatrix.makeTranslation( 0, userHeight, 0 );
21988 
21989  }
21990 
21991  }
21992 
21993 
21994  var pose = frameData.pose;
21995  var poseObject = poseTarget !== null ? poseTarget : camera;
21996 
21997  // We want to manipulate poseObject by its position and quaternion components since users may rely on them.
21998  poseObject.matrix.copy( standingMatrix );
21999  poseObject.matrix.decompose( poseObject.position, poseObject.quaternion, poseObject.scale );
22000 
22001  if ( pose.orientation !== null ) {
22002 
22003  tempQuaternion.fromArray( pose.orientation );
22004  poseObject.quaternion.multiply( tempQuaternion );
22005 
22006  }
22007 
22008  if ( pose.position !== null ) {
22009 
22010  tempQuaternion.setFromRotationMatrix( standingMatrix );
22011  tempPosition.fromArray( pose.position );
22012  tempPosition.applyQuaternion( tempQuaternion );
22013  poseObject.position.add( tempPosition );
22014 
22015  }
22016 
22017  poseObject.updateMatrixWorld();
22018 
22019  //
22020 
22021  cameraL.near = camera.near;
22022  cameraR.near = camera.near;
22023 
22024  cameraL.far = camera.far;
22025  cameraR.far = camera.far;
22026 
22027  cameraL.matrixWorldInverse.fromArray( frameData.leftViewMatrix );
22028  cameraR.matrixWorldInverse.fromArray( frameData.rightViewMatrix );
22029 
22030  // TODO (mrdoob) Double check this code
22031 
22032  standingMatrixInverse.getInverse( standingMatrix );
22033 
22034  if ( frameOfReferenceType === 'stage' ) {
22035 
22036  cameraL.matrixWorldInverse.multiply( standingMatrixInverse );
22037  cameraR.matrixWorldInverse.multiply( standingMatrixInverse );
22038 
22039  }
22040 
22041  var parent = poseObject.parent;
22042 
22043  if ( parent !== null ) {
22044 
22045  matrixWorldInverse.getInverse( parent.matrixWorld );
22046 
22047  cameraL.matrixWorldInverse.multiply( matrixWorldInverse );
22048  cameraR.matrixWorldInverse.multiply( matrixWorldInverse );
22049 
22050  }
22051 
22052  // envMap and Mirror needs camera.matrixWorld
22053 
22054  cameraL.matrixWorld.getInverse( cameraL.matrixWorldInverse );
22055  cameraR.matrixWorld.getInverse( cameraR.matrixWorldInverse );
22056 
22057  cameraL.projectionMatrix.fromArray( frameData.leftProjectionMatrix );
22058  cameraR.projectionMatrix.fromArray( frameData.rightProjectionMatrix );
22059 
22060  setProjectionFromUnion( cameraVR, cameraL, cameraR );
22061 
22062  //
22063 
22064  var layers = device.getLayers();
22065 
22066  if ( layers.length ) {
22067 
22068  var layer = layers[ 0 ];
22069 
22070  if ( layer.leftBounds !== null && layer.leftBounds.length === 4 ) {
22071 
22072  cameraL.bounds.fromArray( layer.leftBounds );
22073 
22074  }
22075 
22076  if ( layer.rightBounds !== null && layer.rightBounds.length === 4 ) {
22077 
22078  cameraR.bounds.fromArray( layer.rightBounds );
22079 
22080  }
22081 
22082  }
22083 
22084  updateControllers();
22085 
22086  return cameraVR;
22087 
22088  };
22089 
22090  this.getStandingMatrix = function () {
22091 
22092  return standingMatrix;
22093 
22094  };
22095 
22096  this.isPresenting = isPresenting;
22097 
22098  // Animation Loop
22099 
22100  var animation = new WebGLAnimation();
22101 
22102  this.setAnimationLoop = function ( callback ) {
22103 
22104  animation.setAnimationLoop( callback );
22105 
22106  };
22107 
22108  this.submitFrame = function () {
22109 
22110  if ( isPresenting() ) device.submitFrame();
22111 
22112  };
22113 
22114  this.dispose = function () {
22115 
22116  if ( typeof window !== 'undefined' ) {
22117 
22118  window.removeEventListener( 'vrdisplaypresentchange', onVRDisplayPresentChange );
22119 
22120  }
22121 
22122  };
22123 
22124  }
22125 
22130  function WebXRManager( renderer ) {
22131 
22132  var gl = renderer.context;
22133 
22134  var device = null;
22135  var session = null;
22136 
22137  var framebufferScaleFactor = 1.0;
22138 
22139  var frameOfReference = null;
22140  var frameOfReferenceType = 'stage';
22141 
22142  var pose = null;
22143 
22144  var controllers = [];
22145  var inputSources = [];
22146 
22147  function isPresenting() {
22148 
22149  return session !== null && frameOfReference !== null;
22150 
22151  }
22152 
22153  //
22154 
22155  var cameraL = new PerspectiveCamera();
22156  cameraL.layers.enable( 1 );
22157  cameraL.viewport = new Vector4();
22158 
22159  var cameraR = new PerspectiveCamera();
22160  cameraR.layers.enable( 2 );
22161  cameraR.viewport = new Vector4();
22162 
22163  var cameraVR = new ArrayCamera( [ cameraL, cameraR ] );
22164  cameraVR.layers.enable( 1 );
22165  cameraVR.layers.enable( 2 );
22166 
22167  //
22168 
22169  this.enabled = false;
22170 
22171  this.getController = function ( id ) {
22172 
22173  var controller = controllers[ id ];
22174 
22175  if ( controller === undefined ) {
22176 
22177  controller = new Group();
22178  controller.matrixAutoUpdate = false;
22179  controller.visible = false;
22180 
22181  controllers[ id ] = controller;
22182 
22183  }
22184 
22185  return controller;
22186 
22187  };
22188 
22189  this.getDevice = function () {
22190 
22191  return device;
22192 
22193  };
22194 
22195  this.setDevice = function ( value ) {
22196 
22197  if ( value !== undefined ) device = value;
22198  if ( value instanceof XRDevice ) gl.setCompatibleXRDevice( value );
22199 
22200  };
22201 
22202  //
22203 
22204  function onSessionEvent( event ) {
22205 
22206  var controller = controllers[ inputSources.indexOf( event.inputSource ) ];
22207  if ( controller ) controller.dispatchEvent( { type: event.type } );
22208 
22209  }
22210 
22211  function onSessionEnd() {
22212 
22213  renderer.setFramebuffer( null );
22214  renderer.setRenderTarget( renderer.getRenderTarget() ); // Hack #15830
22215  animation.stop();
22216 
22217  }
22218 
22219  this.setFramebufferScaleFactor = function ( value ) {
22220 
22221  framebufferScaleFactor = value;
22222 
22223  };
22224 
22225  this.setFrameOfReferenceType = function ( value ) {
22226 
22227  frameOfReferenceType = value;
22228 
22229  };
22230 
22231  this.setSession = function ( value ) {
22232 
22233  session = value;
22234 
22235  if ( session !== null ) {
22236 
22237  session.addEventListener( 'select', onSessionEvent );
22238  session.addEventListener( 'selectstart', onSessionEvent );
22239  session.addEventListener( 'selectend', onSessionEvent );
22240  session.addEventListener( 'end', onSessionEnd );
22241 
22242  session.baseLayer = new XRWebGLLayer( session, gl, { framebufferScaleFactor: framebufferScaleFactor } );
22243  session.requestFrameOfReference( frameOfReferenceType ).then( function ( value ) {
22244 
22245  frameOfReference = value;
22246 
22247  renderer.setFramebuffer( session.baseLayer.framebuffer );
22248 
22249  animation.setContext( session );
22250  animation.start();
22251 
22252  } );
22253 
22254  //
22255 
22256  inputSources = session.getInputSources();
22257 
22258  session.addEventListener( 'inputsourceschange', function () {
22259 
22260  inputSources = session.getInputSources();
22261  console.log( inputSources );
22262 
22263  for ( var i = 0; i < controllers.length; i ++ ) {
22264 
22265  var controller = controllers[ i ];
22266  controller.userData.inputSource = inputSources[ i ];
22267 
22268  }
22269 
22270  } );
22271 
22272  }
22273 
22274  };
22275 
22276  function updateCamera( camera, parent ) {
22277 
22278  if ( parent === null ) {
22279 
22280  camera.matrixWorld.copy( camera.matrix );
22281 
22282  } else {
22283 
22284  camera.matrixWorld.multiplyMatrices( parent.matrixWorld, camera.matrix );
22285 
22286  }
22287 
22288  camera.matrixWorldInverse.getInverse( camera.matrixWorld );
22289 
22290  }
22291 
22292  this.getCamera = function ( camera ) {
22293 
22294  if ( isPresenting() ) {
22295 
22296  var parent = camera.parent;
22297  var cameras = cameraVR.cameras;
22298 
22299  updateCamera( cameraVR, parent );
22300 
22301  for ( var i = 0; i < cameras.length; i ++ ) {
22302 
22303  updateCamera( cameras[ i ], parent );
22304 
22305  }
22306 
22307  // update camera and its children
22308 
22309  camera.matrixWorld.copy( cameraVR.matrixWorld );
22310 
22311  var children = camera.children;
22312 
22313  for ( var i = 0, l = children.length; i < l; i ++ ) {
22314 
22315  children[ i ].updateMatrixWorld( true );
22316 
22317  }
22318 
22319  setProjectionFromUnion( cameraVR, cameraL, cameraR );
22320 
22321  return cameraVR;
22322 
22323  }
22324 
22325  return camera;
22326 
22327  };
22328 
22329  this.isPresenting = isPresenting;
22330 
22331  // Animation Loop
22332 
22333  var onAnimationFrameCallback = null;
22334 
22335  function onAnimationFrame( time, frame ) {
22336 
22337  pose = frame.getDevicePose( frameOfReference );
22338 
22339  if ( pose !== null ) {
22340 
22341  var layer = session.baseLayer;
22342  var views = frame.views;
22343 
22344  for ( var i = 0; i < views.length; i ++ ) {
22345 
22346  var view = views[ i ];
22347  var viewport = layer.getViewport( view );
22348  var viewMatrix = pose.getViewMatrix( view );
22349 
22350  var camera = cameraVR.cameras[ i ];
22351  camera.matrix.fromArray( viewMatrix ).getInverse( camera.matrix );
22352  camera.projectionMatrix.fromArray( view.projectionMatrix );
22353  camera.viewport.set( viewport.x, viewport.y, viewport.width, viewport.height );
22354 
22355  if ( i === 0 ) {
22356 
22357  cameraVR.matrix.copy( camera.matrix );
22358 
22359  }
22360 
22361  }
22362 
22363  }
22364 
22365  //
22366 
22367  for ( var i = 0; i < controllers.length; i ++ ) {
22368 
22369  var controller = controllers[ i ];
22370 
22371  var inputSource = inputSources[ i ];
22372 
22373  if ( inputSource ) {
22374 
22375  var inputPose = frame.getInputPose( inputSource, frameOfReference );
22376 
22377  if ( inputPose !== null ) {
22378 
22379  if ( 'targetRay' in inputPose ) {
22380 
22381  controller.matrix.elements = inputPose.targetRay.transformMatrix;
22382 
22383  } else if ( 'pointerMatrix' in inputPose ) {
22384 
22385  // DEPRECATED
22386 
22387  controller.matrix.elements = inputPose.pointerMatrix;
22388 
22389  }
22390 
22391  controller.matrix.decompose( controller.position, controller.rotation, controller.scale );
22392  controller.visible = true;
22393 
22394  continue;
22395 
22396  }
22397 
22398  }
22399 
22400  controller.visible = false;
22401 
22402  }
22403 
22404  if ( onAnimationFrameCallback ) onAnimationFrameCallback( time );
22405 
22406  }
22407 
22408  var animation = new WebGLAnimation();
22409  animation.setAnimationLoop( onAnimationFrame );
22410 
22411  this.setAnimationLoop = function ( callback ) {
22412 
22413  onAnimationFrameCallback = callback;
22414 
22415  };
22416 
22417  this.dispose = function () {};
22418 
22419  // DEPRECATED
22420 
22421  this.getStandingMatrix = function () {
22422 
22423  console.warn( 'THREE.WebXRManager: getStandingMatrix() is no longer needed.' );
22424  return new Matrix4();
22425 
22426  };
22427 
22428  this.submitFrame = function () {};
22429 
22430  }
22431 
22440  function WebGLRenderer( parameters ) {
22441 
22442  console.log( 'THREE.WebGLRenderer', REVISION );
22443 
22444  parameters = parameters || {};
22445 
22446  var _canvas = parameters.canvas !== undefined ? parameters.canvas : document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ),
22447  _context = parameters.context !== undefined ? parameters.context : null,
22448 
22449  _alpha = parameters.alpha !== undefined ? parameters.alpha : false,
22450  _depth = parameters.depth !== undefined ? parameters.depth : true,
22451  _stencil = parameters.stencil !== undefined ? parameters.stencil : true,
22452  _antialias = parameters.antialias !== undefined ? parameters.antialias : false,
22453  _premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true,
22454  _preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false,
22455  _powerPreference = parameters.powerPreference !== undefined ? parameters.powerPreference : 'default';
22456 
22457  var currentRenderList = null;
22458  var currentRenderState = null;
22459 
22460  // public properties
22461 
22462  this.domElement = _canvas;
22463  this.context = null;
22464 
22465  // clearing
22466 
22467  this.autoClear = true;
22468  this.autoClearColor = true;
22469  this.autoClearDepth = true;
22470  this.autoClearStencil = true;
22471 
22472  // scene graph
22473 
22474  this.sortObjects = true;
22475 
22476  // user-defined clipping
22477 
22478  this.clippingPlanes = [];
22479  this.localClippingEnabled = false;
22480 
22481  // physically based shading
22482 
22483  this.gammaFactor = 2.0; // for backwards compatibility
22484  this.gammaInput = false;
22485  this.gammaOutput = false;
22486 
22487  // physical lights
22488 
22489  this.physicallyCorrectLights = false;
22490 
22491  // tone mapping
22492 
22493  this.toneMapping = LinearToneMapping;
22494  this.toneMappingExposure = 1.0;
22495  this.toneMappingWhitePoint = 1.0;
22496 
22497  // morphs
22498 
22499  this.maxMorphTargets = 8;
22500  this.maxMorphNormals = 4;
22501 
22502  // internal properties
22503 
22504  var _this = this,
22505 
22506  _isContextLost = false,
22507 
22508  // internal state cache
22509 
22510  _framebuffer = null,
22511 
22512  _currentRenderTarget = null,
22513  _currentFramebuffer = null,
22514  _currentMaterialId = - 1,
22515 
22516  // geometry and program caching
22517 
22518  _currentGeometryProgram = {
22519  geometry: null,
22520  program: null,
22521  wireframe: false
22522  },
22523 
22524  _currentCamera = null,
22525  _currentArrayCamera = null,
22526 
22527  _currentViewport = new Vector4(),
22528  _currentScissor = new Vector4(),
22529  _currentScissorTest = null,
22530 
22531  //
22532 
22533  _usedTextureUnits = 0,
22534 
22535  //
22536 
22537  _width = _canvas.width,
22538  _height = _canvas.height,
22539 
22540  _pixelRatio = 1,
22541 
22542  _viewport = new Vector4( 0, 0, _width, _height ),
22543  _scissor = new Vector4( 0, 0, _width, _height ),
22544  _scissorTest = false,
22545 
22546  // frustum
22547 
22548  _frustum = new Frustum(),
22549 
22550  // clipping
22551 
22552  _clipping = new WebGLClipping(),
22553  _clippingEnabled = false,
22554  _localClippingEnabled = false,
22555 
22556  // camera matrices cache
22557 
22558  _projScreenMatrix = new Matrix4(),
22559 
22560  _vector3 = new Vector3();
22561 
22562  function getTargetPixelRatio() {
22563 
22564  return _currentRenderTarget === null ? _pixelRatio : 1;
22565 
22566  }
22567 
22568  // initialize
22569 
22570  var _gl;
22571 
22572  try {
22573 
22574  var contextAttributes = {
22575  alpha: _alpha,
22576  depth: _depth,
22577  stencil: _stencil,
22578  antialias: _antialias,
22579  premultipliedAlpha: _premultipliedAlpha,
22580  preserveDrawingBuffer: _preserveDrawingBuffer,
22581  powerPreference: _powerPreference
22582  };
22583 
22584  // event listeners must be registered before WebGL context is created, see #12753
22585 
22586  _canvas.addEventListener( 'webglcontextlost', onContextLost, false );
22587  _canvas.addEventListener( 'webglcontextrestored', onContextRestore, false );
22588 
22589  _gl = _context || _canvas.getContext( 'webgl', contextAttributes ) || _canvas.getContext( 'experimental-webgl', contextAttributes );
22590 
22591  if ( _gl === null ) {
22592 
22593  if ( _canvas.getContext( 'webgl' ) !== null ) {
22594 
22595  throw new Error( 'Error creating WebGL context with your selected attributes.' );
22596 
22597  } else {
22598 
22599  throw new Error( 'Error creating WebGL context.' );
22600 
22601  }
22602 
22603  }
22604 
22605  // Some experimental-webgl implementations do not have getShaderPrecisionFormat
22606 
22607  if ( _gl.getShaderPrecisionFormat === undefined ) {
22608 
22609  _gl.getShaderPrecisionFormat = function () {
22610 
22611  return { 'rangeMin': 1, 'rangeMax': 1, 'precision': 1 };
22612 
22613  };
22614 
22615  }
22616 
22617  } catch ( error ) {
22618 
22619  console.error( 'THREE.WebGLRenderer: ' + error.message );
22620  throw error;
22621 
22622  }
22623 
22624  var extensions, capabilities, state, info;
22625  var properties, textures, attributes, geometries, objects;
22626  var programCache, renderLists, renderStates;
22627 
22628  var background, morphtargets, bufferRenderer, indexedBufferRenderer;
22629 
22630  var utils;
22631 
22632  function initGLContext() {
22633 
22634  extensions = new WebGLExtensions( _gl );
22635 
22636  capabilities = new WebGLCapabilities( _gl, extensions, parameters );
22637 
22638  if ( ! capabilities.isWebGL2 ) {
22639 
22640  extensions.get( 'WEBGL_depth_texture' );
22641  extensions.get( 'OES_texture_float' );
22642  extensions.get( 'OES_texture_half_float' );
22643  extensions.get( 'OES_texture_half_float_linear' );
22644  extensions.get( 'OES_standard_derivatives' );
22645  extensions.get( 'OES_element_index_uint' );
22646  extensions.get( 'ANGLE_instanced_arrays' );
22647 
22648  }
22649 
22650  extensions.get( 'OES_texture_float_linear' );
22651 
22652  utils = new WebGLUtils( _gl, extensions, capabilities );
22653 
22654  state = new WebGLState( _gl, extensions, utils, capabilities );
22655  state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ) );
22656  state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ) );
22657 
22658  info = new WebGLInfo( _gl );
22659  properties = new WebGLProperties();
22660  textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info );
22661  attributes = new WebGLAttributes( _gl );
22662  geometries = new WebGLGeometries( _gl, attributes, info );
22663  objects = new WebGLObjects( geometries, info );
22664  morphtargets = new WebGLMorphtargets( _gl );
22665  programCache = new WebGLPrograms( _this, extensions, capabilities );
22666  renderLists = new WebGLRenderLists();
22667  renderStates = new WebGLRenderStates();
22668 
22669  background = new WebGLBackground( _this, state, objects, _premultipliedAlpha );
22670 
22671  bufferRenderer = new WebGLBufferRenderer( _gl, extensions, info, capabilities );
22672  indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, info, capabilities );
22673 
22674  info.programs = programCache.programs;
22675 
22676  _this.context = _gl;
22677  _this.capabilities = capabilities;
22678  _this.extensions = extensions;
22679  _this.properties = properties;
22680  _this.renderLists = renderLists;
22681  _this.state = state;
22682  _this.info = info;
22683 
22684  }
22685 
22686  initGLContext();
22687 
22688  // vr
22689 
22690  var vr = null;
22691 
22692  if ( typeof navigator !== 'undefined' ) {
22693 
22694  vr = ( 'xr' in navigator ) ? new WebXRManager( _this ) : new WebVRManager( _this );
22695 
22696  }
22697 
22698  this.vr = vr;
22699 
22700  // shadow map
22701 
22702  var shadowMap = new WebGLShadowMap( _this, objects, capabilities.maxTextureSize );
22703 
22704  this.shadowMap = shadowMap;
22705 
22706  // API
22707 
22708  this.getContext = function () {
22709 
22710  return _gl;
22711 
22712  };
22713 
22714  this.getContextAttributes = function () {
22715 
22716  return _gl.getContextAttributes();
22717 
22718  };
22719 
22720  this.forceContextLoss = function () {
22721 
22722  var extension = extensions.get( 'WEBGL_lose_context' );
22723  if ( extension ) extension.loseContext();
22724 
22725  };
22726 
22727  this.forceContextRestore = function () {
22728 
22729  var extension = extensions.get( 'WEBGL_lose_context' );
22730  if ( extension ) extension.restoreContext();
22731 
22732  };
22733 
22734  this.getPixelRatio = function () {
22735 
22736  return _pixelRatio;
22737 
22738  };
22739 
22740  this.setPixelRatio = function ( value ) {
22741 
22742  if ( value === undefined ) return;
22743 
22744  _pixelRatio = value;
22745 
22746  this.setSize( _width, _height, false );
22747 
22748  };
22749 
22750  this.getSize = function ( target ) {
22751 
22752  if ( target === undefined ) {
22753 
22754  console.warn( 'WebGLRenderer: .getsize() now requires a Vector2 as an argument' );
22755 
22756  target = new Vector2();
22757 
22758  }
22759 
22760  return target.set( _width, _height );
22761 
22762  };
22763 
22764  this.setSize = function ( width, height, updateStyle ) {
22765 
22766  if ( vr.isPresenting() ) {
22767 
22768  console.warn( 'THREE.WebGLRenderer: Can\'t change size while VR device is presenting.' );
22769  return;
22770 
22771  }
22772 
22773  _width = width;
22774  _height = height;
22775 
22776  _canvas.width = width * _pixelRatio;
22777  _canvas.height = height * _pixelRatio;
22778 
22779  if ( updateStyle !== false ) {
22780 
22781  _canvas.style.width = width + 'px';
22782  _canvas.style.height = height + 'px';
22783 
22784  }
22785 
22786  this.setViewport( 0, 0, width, height );
22787 
22788  };
22789 
22790  this.getDrawingBufferSize = function ( target ) {
22791 
22792  if ( target === undefined ) {
22793 
22794  console.warn( 'WebGLRenderer: .getdrawingBufferSize() now requires a Vector2 as an argument' );
22795 
22796  target = new Vector2();
22797 
22798  }
22799 
22800  return target.set( _width * _pixelRatio, _height * _pixelRatio );
22801 
22802  };
22803 
22804  this.setDrawingBufferSize = function ( width, height, pixelRatio ) {
22805 
22806  _width = width;
22807  _height = height;
22808 
22809  _pixelRatio = pixelRatio;
22810 
22811  _canvas.width = width * pixelRatio;
22812  _canvas.height = height * pixelRatio;
22813 
22814  this.setViewport( 0, 0, width, height );
22815 
22816  };
22817 
22818  this.getCurrentViewport = function ( target ) {
22819 
22820  if ( target === undefined ) {
22821 
22822  console.warn( 'WebGLRenderer: .getCurrentViewport() now requires a Vector4 as an argument' );
22823 
22824  target = new Vector4();
22825 
22826  }
22827 
22828  return target.copy( _currentViewport );
22829 
22830  };
22831 
22832  this.getViewport = function ( target ) {
22833 
22834  return target.copy( _viewport );
22835 
22836  };
22837 
22838  this.setViewport = function ( x, y, width, height ) {
22839 
22840  if ( x.isVector4 ) {
22841 
22842  _viewport.set( x.x, x.y, x.z, x.w );
22843 
22844  } else {
22845 
22846  _viewport.set( x, y, width, height );
22847 
22848  }
22849 
22850  state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ) );
22851 
22852  };
22853 
22854  this.getScissor = function ( target ) {
22855 
22856  return target.copy( _scissor );
22857 
22858  };
22859 
22860  this.setScissor = function ( x, y, width, height ) {
22861 
22862  if ( x.isVector4 ) {
22863 
22864  _scissor.set( x.x, x.y, x.z, x.w );
22865 
22866  } else {
22867 
22868  _scissor.set( x, y, width, height );
22869 
22870  }
22871 
22872  state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ) );
22873 
22874  };
22875 
22876  this.getScissorTest = function () {
22877 
22878  return _scissorTest;
22879 
22880  };
22881 
22882  this.setScissorTest = function ( boolean ) {
22883 
22884  state.setScissorTest( _scissorTest = boolean );
22885 
22886  };
22887 
22888  // Clearing
22889 
22890  this.getClearColor = function () {
22891 
22892  return background.getClearColor();
22893 
22894  };
22895 
22896  this.setClearColor = function () {
22897 
22898  background.setClearColor.apply( background, arguments );
22899 
22900  };
22901 
22902  this.getClearAlpha = function () {
22903 
22904  return background.getClearAlpha();
22905 
22906  };
22907 
22908  this.setClearAlpha = function () {
22909 
22910  background.setClearAlpha.apply( background, arguments );
22911 
22912  };
22913 
22914  this.clear = function ( color, depth, stencil ) {
22915 
22916  var bits = 0;
22917 
22918  if ( color === undefined || color ) bits |= 16384;
22919  if ( depth === undefined || depth ) bits |= 256;
22920  if ( stencil === undefined || stencil ) bits |= 1024;
22921 
22922  _gl.clear( bits );
22923 
22924  };
22925 
22926  this.clearColor = function () {
22927 
22928  this.clear( true, false, false );
22929 
22930  };
22931 
22932  this.clearDepth = function () {
22933 
22934  this.clear( false, true, false );
22935 
22936  };
22937 
22938  this.clearStencil = function () {
22939 
22940  this.clear( false, false, true );
22941 
22942  };
22943 
22944  //
22945 
22946  this.dispose = function () {
22947 
22948  _canvas.removeEventListener( 'webglcontextlost', onContextLost, false );
22949  _canvas.removeEventListener( 'webglcontextrestored', onContextRestore, false );
22950 
22951  renderLists.dispose();
22952  renderStates.dispose();
22953  properties.dispose();
22954  objects.dispose();
22955 
22956  vr.dispose();
22957 
22958  animation.stop();
22959 
22960  };
22961 
22962  // Events
22963 
22964  function onContextLost( event ) {
22965 
22966  event.preventDefault();
22967 
22968  console.log( 'THREE.WebGLRenderer: Context Lost.' );
22969 
22970  _isContextLost = true;
22971 
22972  }
22973 
22974  function onContextRestore( /* event */ ) {
22975 
22976  console.log( 'THREE.WebGLRenderer: Context Restored.' );
22977 
22978  _isContextLost = false;
22979 
22980  initGLContext();
22981 
22982  }
22983 
22984  function onMaterialDispose( event ) {
22985 
22986  var material = event.target;
22987 
22988  material.removeEventListener( 'dispose', onMaterialDispose );
22989 
22990  deallocateMaterial( material );
22991 
22992  }
22993 
22994  // Buffer deallocation
22995 
22996  function deallocateMaterial( material ) {
22997 
22998  releaseMaterialProgramReference( material );
22999 
23000  properties.remove( material );
23001 
23002  }
23003 
23004 
23005  function releaseMaterialProgramReference( material ) {
23006 
23007  var programInfo = properties.get( material ).program;
23008 
23009  material.program = undefined;
23010 
23011  if ( programInfo !== undefined ) {
23012 
23013  programCache.releaseProgram( programInfo );
23014 
23015  }
23016 
23017  }
23018 
23019  // Buffer rendering
23020 
23021  function renderObjectImmediate( object, program ) {
23022 
23023  object.render( function ( object ) {
23024 
23025  _this.renderBufferImmediate( object, program );
23026 
23027  } );
23028 
23029  }
23030 
23031  this.renderBufferImmediate = function ( object, program ) {
23032 
23033  state.initAttributes();
23034 
23035  var buffers = properties.get( object );
23036 
23037  if ( object.hasPositions && ! buffers.position ) buffers.position = _gl.createBuffer();
23038  if ( object.hasNormals && ! buffers.normal ) buffers.normal = _gl.createBuffer();
23039  if ( object.hasUvs && ! buffers.uv ) buffers.uv = _gl.createBuffer();
23040  if ( object.hasColors && ! buffers.color ) buffers.color = _gl.createBuffer();
23041 
23042  var programAttributes = program.getAttributes();
23043 
23044  if ( object.hasPositions ) {
23045 
23046  _gl.bindBuffer( 34962, buffers.position );
23047  _gl.bufferData( 34962, object.positionArray, 35048 );
23048 
23049  state.enableAttribute( programAttributes.position );
23050  _gl.vertexAttribPointer( programAttributes.position, 3, 5126, false, 0, 0 );
23051 
23052  }
23053 
23054  if ( object.hasNormals ) {
23055 
23056  _gl.bindBuffer( 34962, buffers.normal );
23057  _gl.bufferData( 34962, object.normalArray, 35048 );
23058 
23059  state.enableAttribute( programAttributes.normal );
23060  _gl.vertexAttribPointer( programAttributes.normal, 3, 5126, false, 0, 0 );
23061 
23062  }
23063 
23064  if ( object.hasUvs ) {
23065 
23066  _gl.bindBuffer( 34962, buffers.uv );
23067  _gl.bufferData( 34962, object.uvArray, 35048 );
23068 
23069  state.enableAttribute( programAttributes.uv );
23070  _gl.vertexAttribPointer( programAttributes.uv, 2, 5126, false, 0, 0 );
23071 
23072  }
23073 
23074  if ( object.hasColors ) {
23075 
23076  _gl.bindBuffer( 34962, buffers.color );
23077  _gl.bufferData( 34962, object.colorArray, 35048 );
23078 
23079  state.enableAttribute( programAttributes.color );
23080  _gl.vertexAttribPointer( programAttributes.color, 3, 5126, false, 0, 0 );
23081 
23082  }
23083 
23084  state.disableUnusedAttributes();
23085 
23086  _gl.drawArrays( 4, 0, object.count );
23087 
23088  object.count = 0;
23089 
23090  };
23091 
23092  this.renderBufferDirect = function ( camera, fog, geometry, material, object, group ) {
23093 
23094  var frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 );
23095 
23096  state.setMaterial( material, frontFaceCW );
23097 
23098  var program = setProgram( camera, fog, material, object );
23099 
23100  var updateBuffers = false;
23101 
23102  if ( _currentGeometryProgram.geometry !== geometry.id ||
23103  _currentGeometryProgram.program !== program.id ||
23104  _currentGeometryProgram.wireframe !== ( material.wireframe === true ) ) {
23105 
23106  _currentGeometryProgram.geometry = geometry.id;
23107  _currentGeometryProgram.program = program.id;
23108  _currentGeometryProgram.wireframe = material.wireframe === true;
23109  updateBuffers = true;
23110 
23111  }
23112 
23113  if ( object.morphTargetInfluences ) {
23114 
23115  morphtargets.update( object, geometry, material, program );
23116 
23117  updateBuffers = true;
23118 
23119  }
23120 
23121  //
23122 
23123  var index = geometry.index;
23124  var position = geometry.attributes.position;
23125  var rangeFactor = 1;
23126 
23127  if ( material.wireframe === true ) {
23128 
23129  index = geometries.getWireframeAttribute( geometry );
23130  rangeFactor = 2;
23131 
23132  }
23133 
23134  var attribute;
23135  var renderer = bufferRenderer;
23136 
23137  if ( index !== null ) {
23138 
23139  attribute = attributes.get( index );
23140 
23141  renderer = indexedBufferRenderer;
23142  renderer.setIndex( attribute );
23143 
23144  }
23145 
23146  if ( updateBuffers ) {
23147 
23148  setupVertexAttributes( material, program, geometry );
23149 
23150  if ( index !== null ) {
23151 
23152  _gl.bindBuffer( 34963, attribute.buffer );
23153 
23154  }
23155 
23156  }
23157 
23158  //
23159 
23160  var dataCount = Infinity;
23161 
23162  if ( index !== null ) {
23163 
23164  dataCount = index.count;
23165 
23166  } else if ( position !== undefined ) {
23167 
23168  dataCount = position.count;
23169 
23170  }
23171 
23172  var rangeStart = geometry.drawRange.start * rangeFactor;
23173  var rangeCount = geometry.drawRange.count * rangeFactor;
23174 
23175  var groupStart = group !== null ? group.start * rangeFactor : 0;
23176  var groupCount = group !== null ? group.count * rangeFactor : Infinity;
23177 
23178  var drawStart = Math.max( rangeStart, groupStart );
23179  var drawEnd = Math.min( dataCount, rangeStart + rangeCount, groupStart + groupCount ) - 1;
23180 
23181  var drawCount = Math.max( 0, drawEnd - drawStart + 1 );
23182 
23183  if ( drawCount === 0 ) return;
23184 
23185  //
23186 
23187  if ( object.isMesh ) {
23188 
23189  if ( material.wireframe === true ) {
23190 
23191  state.setLineWidth( material.wireframeLinewidth * getTargetPixelRatio() );
23192  renderer.setMode( 1 );
23193 
23194  } else {
23195 
23196  switch ( object.drawMode ) {
23197 
23198  case TrianglesDrawMode:
23199  renderer.setMode( 4 );
23200  break;
23201 
23202  case TriangleStripDrawMode:
23203  renderer.setMode( 5 );
23204  break;
23205 
23206  case TriangleFanDrawMode:
23207  renderer.setMode( 6 );
23208  break;
23209 
23210  }
23211 
23212  }
23213 
23214 
23215  } else if ( object.isLine ) {
23216 
23217  var lineWidth = material.linewidth;
23218 
23219  if ( lineWidth === undefined ) lineWidth = 1; // Not using Line*Material
23220 
23221  state.setLineWidth( lineWidth * getTargetPixelRatio() );
23222 
23223  if ( object.isLineSegments ) {
23224 
23225  renderer.setMode( 1 );
23226 
23227  } else if ( object.isLineLoop ) {
23228 
23229  renderer.setMode( 2 );
23230 
23231  } else {
23232 
23233  renderer.setMode( 3 );
23234 
23235  }
23236 
23237  } else if ( object.isPoints ) {
23238 
23239  renderer.setMode( 0 );
23240 
23241  } else if ( object.isSprite ) {
23242 
23243  renderer.setMode( 4 );
23244 
23245  }
23246 
23247  if ( geometry && geometry.isInstancedBufferGeometry ) {
23248 
23249  if ( geometry.maxInstancedCount > 0 ) {
23250 
23251  renderer.renderInstances( geometry, drawStart, drawCount );
23252 
23253  }
23254 
23255  } else {
23256 
23257  renderer.render( drawStart, drawCount );
23258 
23259  }
23260 
23261  };
23262 
23263  function setupVertexAttributes( material, program, geometry ) {
23264 
23265  if ( geometry && geometry.isInstancedBufferGeometry && ! capabilities.isWebGL2 ) {
23266 
23267  if ( extensions.get( 'ANGLE_instanced_arrays' ) === null ) {
23268 
23269  console.error( 'THREE.WebGLRenderer.setupVertexAttributes: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
23270  return;
23271 
23272  }
23273 
23274  }
23275 
23276  state.initAttributes();
23277 
23278  var geometryAttributes = geometry.attributes;
23279 
23280  var programAttributes = program.getAttributes();
23281 
23282  var materialDefaultAttributeValues = material.defaultAttributeValues;
23283 
23284  for ( var name in programAttributes ) {
23285 
23286  var programAttribute = programAttributes[ name ];
23287 
23288  if ( programAttribute >= 0 ) {
23289 
23290  var geometryAttribute = geometryAttributes[ name ];
23291 
23292  if ( geometryAttribute !== undefined ) {
23293 
23294  var normalized = geometryAttribute.normalized;
23295  var size = geometryAttribute.itemSize;
23296 
23297  var attribute = attributes.get( geometryAttribute );
23298 
23299  // TODO Attribute may not be available on context restore
23300 
23301  if ( attribute === undefined ) continue;
23302 
23303  var buffer = attribute.buffer;
23304  var type = attribute.type;
23305  var bytesPerElement = attribute.bytesPerElement;
23306 
23307  if ( geometryAttribute.isInterleavedBufferAttribute ) {
23308 
23309  var data = geometryAttribute.data;
23310  var stride = data.stride;
23311  var offset = geometryAttribute.offset;
23312 
23313  if ( data && data.isInstancedInterleavedBuffer ) {
23314 
23315  state.enableAttributeAndDivisor( programAttribute, data.meshPerAttribute );
23316 
23317  if ( geometry.maxInstancedCount === undefined ) {
23318 
23319  geometry.maxInstancedCount = data.meshPerAttribute * data.count;
23320 
23321  }
23322 
23323  } else {
23324 
23325  state.enableAttribute( programAttribute );
23326 
23327  }
23328 
23329  _gl.bindBuffer( 34962, buffer );
23330  _gl.vertexAttribPointer( programAttribute, size, type, normalized, stride * bytesPerElement, offset * bytesPerElement );
23331 
23332  } else {
23333 
23334  if ( geometryAttribute.isInstancedBufferAttribute ) {
23335 
23336  state.enableAttributeAndDivisor( programAttribute, geometryAttribute.meshPerAttribute );
23337 
23338  if ( geometry.maxInstancedCount === undefined ) {
23339 
23340  geometry.maxInstancedCount = geometryAttribute.meshPerAttribute * geometryAttribute.count;
23341 
23342  }
23343 
23344  } else {
23345 
23346  state.enableAttribute( programAttribute );
23347 
23348  }
23349 
23350  _gl.bindBuffer( 34962, buffer );
23351  _gl.vertexAttribPointer( programAttribute, size, type, normalized, 0, 0 );
23352 
23353  }
23354 
23355  } else if ( materialDefaultAttributeValues !== undefined ) {
23356 
23357  var value = materialDefaultAttributeValues[ name ];
23358 
23359  if ( value !== undefined ) {
23360 
23361  switch ( value.length ) {
23362 
23363  case 2:
23364  _gl.vertexAttrib2fv( programAttribute, value );
23365  break;
23366 
23367  case 3:
23368  _gl.vertexAttrib3fv( programAttribute, value );
23369  break;
23370 
23371  case 4:
23372  _gl.vertexAttrib4fv( programAttribute, value );
23373  break;
23374 
23375  default:
23376  _gl.vertexAttrib1fv( programAttribute, value );
23377 
23378  }
23379 
23380  }
23381 
23382  }
23383 
23384  }
23385 
23386  }
23387 
23388  state.disableUnusedAttributes();
23389 
23390  }
23391 
23392  // Compile
23393 
23394  this.compile = function ( scene, camera ) {
23395 
23396  currentRenderState = renderStates.get( scene, camera );
23397  currentRenderState.init();
23398 
23399  scene.traverse( function ( object ) {
23400 
23401  if ( object.isLight ) {
23402 
23403  currentRenderState.pushLight( object );
23404 
23405  if ( object.castShadow ) {
23406 
23407  currentRenderState.pushShadow( object );
23408 
23409  }
23410 
23411  }
23412 
23413  } );
23414 
23415  currentRenderState.setupLights( camera );
23416 
23417  scene.traverse( function ( object ) {
23418 
23419  if ( object.material ) {
23420 
23421  if ( Array.isArray( object.material ) ) {
23422 
23423  for ( var i = 0; i < object.material.length; i ++ ) {
23424 
23425  initMaterial( object.material[ i ], scene.fog, object );
23426 
23427  }
23428 
23429  } else {
23430 
23431  initMaterial( object.material, scene.fog, object );
23432 
23433  }
23434 
23435  }
23436 
23437  } );
23438 
23439  };
23440 
23441  // Animation Loop
23442 
23443  var onAnimationFrameCallback = null;
23444 
23445  function onAnimationFrame( time ) {
23446 
23447  if ( vr.isPresenting() ) return;
23448  if ( onAnimationFrameCallback ) onAnimationFrameCallback( time );
23449 
23450  }
23451 
23452  var animation = new WebGLAnimation();
23453  animation.setAnimationLoop( onAnimationFrame );
23454 
23455  if ( typeof window !== 'undefined' ) animation.setContext( window );
23456 
23457  this.setAnimationLoop = function ( callback ) {
23458 
23459  onAnimationFrameCallback = callback;
23460  vr.setAnimationLoop( callback );
23461 
23462  animation.start();
23463 
23464  };
23465 
23466  // Rendering
23467 
23468  this.render = function ( scene, camera ) {
23469 
23470  var renderTarget, forceClear;
23471 
23472  if ( arguments[ 2 ] !== undefined ) {
23473 
23474  console.warn( 'THREE.WebGLRenderer.render(): the renderTarget argument has been removed. Use .setRenderTarget() instead.' );
23475  renderTarget = arguments[ 2 ];
23476 
23477  }
23478 
23479  if ( arguments[ 3 ] !== undefined ) {
23480 
23481  console.warn( 'THREE.WebGLRenderer.render(): the forceClear argument has been removed. Use .clear() instead.' );
23482  forceClear = arguments[ 3 ];
23483 
23484  }
23485 
23486  if ( ! ( camera && camera.isCamera ) ) {
23487 
23488  console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' );
23489  return;
23490 
23491  }
23492 
23493  if ( _isContextLost ) return;
23494 
23495  // reset caching for this frame
23496 
23497  _currentGeometryProgram.geometry = null;
23498  _currentGeometryProgram.program = null;
23499  _currentGeometryProgram.wireframe = false;
23500  _currentMaterialId = - 1;
23501  _currentCamera = null;
23502 
23503  // update scene graph
23504 
23505  if ( scene.autoUpdate === true ) scene.updateMatrixWorld();
23506 
23507  // update camera matrices and frustum
23508 
23509  if ( camera.parent === null ) camera.updateMatrixWorld();
23510 
23511  if ( vr.enabled ) {
23512 
23513  camera = vr.getCamera( camera );
23514 
23515  }
23516 
23517  //
23518 
23519  currentRenderState = renderStates.get( scene, camera );
23520  currentRenderState.init();
23521 
23522  scene.onBeforeRender( _this, scene, camera, renderTarget || _currentRenderTarget );
23523 
23524  _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
23525  _frustum.setFromMatrix( _projScreenMatrix );
23526 
23527  _localClippingEnabled = this.localClippingEnabled;
23528  _clippingEnabled = _clipping.init( this.clippingPlanes, _localClippingEnabled, camera );
23529 
23530  currentRenderList = renderLists.get( scene, camera );
23531  currentRenderList.init();
23532 
23533  projectObject( scene, camera, 0, _this.sortObjects );
23534 
23535  if ( _this.sortObjects === true ) {
23536 
23537  currentRenderList.sort();
23538 
23539  }
23540 
23541  //
23542 
23543  if ( _clippingEnabled ) _clipping.beginShadows();
23544 
23545  var shadowsArray = currentRenderState.state.shadowsArray;
23546 
23547  shadowMap.render( shadowsArray, scene, camera );
23548 
23549  currentRenderState.setupLights( camera );
23550 
23551  if ( _clippingEnabled ) _clipping.endShadows();
23552 
23553  //
23554 
23555  if ( this.info.autoReset ) this.info.reset();
23556 
23557  if ( renderTarget !== undefined ) {
23558 
23559  this.setRenderTarget( renderTarget );
23560 
23561  }
23562 
23563  //
23564 
23565  background.render( currentRenderList, scene, camera, forceClear );
23566 
23567  // render scene
23568 
23569  var opaqueObjects = currentRenderList.opaque;
23570  var transparentObjects = currentRenderList.transparent;
23571 
23572  if ( scene.overrideMaterial ) {
23573 
23574  var overrideMaterial = scene.overrideMaterial;
23575 
23576  if ( opaqueObjects.length ) renderObjects( opaqueObjects, scene, camera, overrideMaterial );
23577  if ( transparentObjects.length ) renderObjects( transparentObjects, scene, camera, overrideMaterial );
23578 
23579  } else {
23580 
23581  // opaque pass (front-to-back order)
23582 
23583  if ( opaqueObjects.length ) renderObjects( opaqueObjects, scene, camera );
23584 
23585  // transparent pass (back-to-front order)
23586 
23587  if ( transparentObjects.length ) renderObjects( transparentObjects, scene, camera );
23588 
23589  }
23590 
23591  //
23592 
23593  if ( _currentRenderTarget !== null ) {
23594 
23595  // Generate mipmap if we're using any kind of mipmap filtering
23596 
23597  textures.updateRenderTargetMipmap( _currentRenderTarget );
23598 
23599  // resolve multisample renderbuffers to a single-sample texture if necessary
23600 
23601  textures.updateMultisampleRenderTarget( _currentRenderTarget );
23602 
23603  }
23604 
23605  // Ensure depth buffer writing is enabled so it can be cleared on next render
23606 
23607  state.buffers.depth.setTest( true );
23608  state.buffers.depth.setMask( true );
23609  state.buffers.color.setMask( true );
23610 
23611  state.setPolygonOffset( false );
23612 
23613  scene.onAfterRender( _this, scene, camera );
23614 
23615  if ( vr.enabled ) {
23616 
23617  vr.submitFrame();
23618 
23619  }
23620 
23621  // _gl.finish();
23622 
23623  currentRenderList = null;
23624  currentRenderState = null;
23625 
23626  };
23627 
23628  function projectObject( object, camera, groupOrder, sortObjects ) {
23629 
23630  if ( object.visible === false ) return;
23631 
23632  var visible = object.layers.test( camera.layers );
23633 
23634  if ( visible ) {
23635 
23636  if ( object.isGroup ) {
23637 
23638  groupOrder = object.renderOrder;
23639 
23640  } else if ( object.isLight ) {
23641 
23642  currentRenderState.pushLight( object );
23643 
23644  if ( object.castShadow ) {
23645 
23646  currentRenderState.pushShadow( object );
23647 
23648  }
23649 
23650  } else if ( object.isSprite ) {
23651 
23652  if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) {
23653 
23654  if ( sortObjects ) {
23655 
23656  _vector3.setFromMatrixPosition( object.matrixWorld )
23657  .applyMatrix4( _projScreenMatrix );
23658 
23659  }
23660 
23661  var geometry = objects.update( object );
23662  var material = object.material;
23663 
23664  currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null );
23665 
23666  }
23667 
23668  } else if ( object.isImmediateRenderObject ) {
23669 
23670  if ( sortObjects ) {
23671 
23672  _vector3.setFromMatrixPosition( object.matrixWorld )
23673  .applyMatrix4( _projScreenMatrix );
23674 
23675  }
23676 
23677  currentRenderList.push( object, null, object.material, groupOrder, _vector3.z, null );
23678 
23679  } else if ( object.isMesh || object.isLine || object.isPoints ) {
23680 
23681  if ( object.isSkinnedMesh ) {
23682 
23683  object.skeleton.update();
23684 
23685  }
23686 
23687  if ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) {
23688 
23689  if ( sortObjects ) {
23690 
23691  _vector3.setFromMatrixPosition( object.matrixWorld )
23692  .applyMatrix4( _projScreenMatrix );
23693 
23694  }
23695 
23696  var geometry = objects.update( object );
23697  var material = object.material;
23698 
23699  if ( Array.isArray( material ) ) {
23700 
23701  var groups = geometry.groups;
23702 
23703  for ( var i = 0, l = groups.length; i < l; i ++ ) {
23704 
23705  var group = groups[ i ];
23706  var groupMaterial = material[ group.materialIndex ];
23707 
23708  if ( groupMaterial && groupMaterial.visible ) {
23709 
23710  currentRenderList.push( object, geometry, groupMaterial, groupOrder, _vector3.z, group );
23711 
23712  }
23713 
23714  }
23715 
23716  } else if ( material.visible ) {
23717 
23718  currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null );
23719 
23720  }
23721 
23722  }
23723 
23724  }
23725 
23726  }
23727 
23728  var children = object.children;
23729 
23730  for ( var i = 0, l = children.length; i < l; i ++ ) {
23731 
23732  projectObject( children[ i ], camera, groupOrder, sortObjects );
23733 
23734  }
23735 
23736  }
23737 
23738  function renderObjects( renderList, scene, camera, overrideMaterial ) {
23739 
23740  for ( var i = 0, l = renderList.length; i < l; i ++ ) {
23741 
23742  var renderItem = renderList[ i ];
23743 
23744  var object = renderItem.object;
23745  var geometry = renderItem.geometry;
23746  var material = overrideMaterial === undefined ? renderItem.material : overrideMaterial;
23747  var group = renderItem.group;
23748 
23749  if ( camera.isArrayCamera ) {
23750 
23751  _currentArrayCamera = camera;
23752 
23753  var cameras = camera.cameras;
23754 
23755  for ( var j = 0, jl = cameras.length; j < jl; j ++ ) {
23756 
23757  var camera2 = cameras[ j ];
23758 
23759  if ( object.layers.test( camera2.layers ) ) {
23760 
23761  if ( 'viewport' in camera2 ) { // XR
23762 
23763  state.viewport( _currentViewport.copy( camera2.viewport ) );
23764 
23765  } else {
23766 
23767  var bounds = camera2.bounds;
23768 
23769  var x = bounds.x * _width;
23770  var y = bounds.y * _height;
23771  var width = bounds.z * _width;
23772  var height = bounds.w * _height;
23773 
23774  state.viewport( _currentViewport.set( x, y, width, height ).multiplyScalar( _pixelRatio ) );
23775 
23776  }
23777 
23778  currentRenderState.setupLights( camera2 );
23779 
23780  renderObject( object, scene, camera2, geometry, material, group );
23781 
23782  }
23783 
23784  }
23785 
23786  } else {
23787 
23788  _currentArrayCamera = null;
23789 
23790  renderObject( object, scene, camera, geometry, material, group );
23791 
23792  }
23793 
23794  }
23795 
23796  }
23797 
23798  function renderObject( object, scene, camera, geometry, material, group ) {
23799 
23800  object.onBeforeRender( _this, scene, camera, geometry, material, group );
23801  currentRenderState = renderStates.get( scene, _currentArrayCamera || camera );
23802 
23803  object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
23804  object.normalMatrix.getNormalMatrix( object.modelViewMatrix );
23805 
23806  if ( object.isImmediateRenderObject ) {
23807 
23808  state.setMaterial( material );
23809 
23810  var program = setProgram( camera, scene.fog, material, object );
23811 
23812  _currentGeometryProgram.geometry = null;
23813  _currentGeometryProgram.program = null;
23814  _currentGeometryProgram.wireframe = false;
23815 
23816  renderObjectImmediate( object, program );
23817 
23818  } else {
23819 
23820  _this.renderBufferDirect( camera, scene.fog, geometry, material, object, group );
23821 
23822  }
23823 
23824  object.onAfterRender( _this, scene, camera, geometry, material, group );
23825  currentRenderState = renderStates.get( scene, _currentArrayCamera || camera );
23826 
23827  }
23828 
23829  function initMaterial( material, fog, object ) {
23830 
23831  var materialProperties = properties.get( material );
23832 
23833  var lights = currentRenderState.state.lights;
23834  var shadowsArray = currentRenderState.state.shadowsArray;
23835 
23836  var lightsHash = materialProperties.lightsHash;
23837  var lightsStateHash = lights.state.hash;
23838 
23839  var parameters = programCache.getParameters(
23840  material, lights.state, shadowsArray, fog, _clipping.numPlanes, _clipping.numIntersection, object );
23841 
23842  var code = programCache.getProgramCode( material, parameters );
23843 
23844  var program = materialProperties.program;
23845  var programChange = true;
23846 
23847  if ( program === undefined ) {
23848 
23849  // new material
23850  material.addEventListener( 'dispose', onMaterialDispose );
23851 
23852  } else if ( program.code !== code ) {
23853 
23854  // changed glsl or parameters
23855  releaseMaterialProgramReference( material );
23856 
23857  } else if ( lightsHash.stateID !== lightsStateHash.stateID ||
23858  lightsHash.directionalLength !== lightsStateHash.directionalLength ||
23859  lightsHash.pointLength !== lightsStateHash.pointLength ||
23860  lightsHash.spotLength !== lightsStateHash.spotLength ||
23861  lightsHash.rectAreaLength !== lightsStateHash.rectAreaLength ||
23862  lightsHash.hemiLength !== lightsStateHash.hemiLength ||
23863  lightsHash.shadowsLength !== lightsStateHash.shadowsLength ) {
23864 
23865  lightsHash.stateID = lightsStateHash.stateID;
23866  lightsHash.directionalLength = lightsStateHash.directionalLength;
23867  lightsHash.pointLength = lightsStateHash.pointLength;
23868  lightsHash.spotLength = lightsStateHash.spotLength;
23869  lightsHash.rectAreaLength = lightsStateHash.rectAreaLength;
23870  lightsHash.hemiLength = lightsStateHash.hemiLength;
23871  lightsHash.shadowsLength = lightsStateHash.shadowsLength;
23872 
23873  programChange = false;
23874 
23875  } else if ( parameters.shaderID !== undefined ) {
23876 
23877  // same glsl and uniform list
23878  return;
23879 
23880  } else {
23881 
23882  // only rebuild uniform list
23883  programChange = false;
23884 
23885  }
23886 
23887  if ( programChange ) {
23888 
23889  if ( parameters.shaderID ) {
23890 
23891  var shader = ShaderLib[ parameters.shaderID ];
23892 
23893  materialProperties.shader = {
23894  name: material.type,
23895  uniforms: cloneUniforms( shader.uniforms ),
23896  vertexShader: shader.vertexShader,
23897  fragmentShader: shader.fragmentShader
23898  };
23899 
23900  } else {
23901 
23902  materialProperties.shader = {
23903  name: material.type,
23904  uniforms: material.uniforms,
23905  vertexShader: material.vertexShader,
23906  fragmentShader: material.fragmentShader
23907  };
23908 
23909  }
23910 
23911  material.onBeforeCompile( materialProperties.shader, _this );
23912 
23913  // Computing code again as onBeforeCompile may have changed the shaders
23914  code = programCache.getProgramCode( material, parameters );
23915 
23916  program = programCache.acquireProgram( material, materialProperties.shader, parameters, code );
23917 
23918  materialProperties.program = program;
23919  material.program = program;
23920 
23921  }
23922 
23923  var programAttributes = program.getAttributes();
23924 
23925  if ( material.morphTargets ) {
23926 
23927  material.numSupportedMorphTargets = 0;
23928 
23929  for ( var i = 0; i < _this.maxMorphTargets; i ++ ) {
23930 
23931  if ( programAttributes[ 'morphTarget' + i ] >= 0 ) {
23932 
23933  material.numSupportedMorphTargets ++;
23934 
23935  }
23936 
23937  }
23938 
23939  }
23940 
23941  if ( material.morphNormals ) {
23942 
23943  material.numSupportedMorphNormals = 0;
23944 
23945  for ( var i = 0; i < _this.maxMorphNormals; i ++ ) {
23946 
23947  if ( programAttributes[ 'morphNormal' + i ] >= 0 ) {
23948 
23949  material.numSupportedMorphNormals ++;
23950 
23951  }
23952 
23953  }
23954 
23955  }
23956 
23957  var uniforms = materialProperties.shader.uniforms;
23958 
23959  if ( ! material.isShaderMaterial &&
23960  ! material.isRawShaderMaterial ||
23961  material.clipping === true ) {
23962 
23963  materialProperties.numClippingPlanes = _clipping.numPlanes;
23964  materialProperties.numIntersection = _clipping.numIntersection;
23965  uniforms.clippingPlanes = _clipping.uniform;
23966 
23967  }
23968 
23969  materialProperties.fog = fog;
23970 
23971  // store the light setup it was created for
23972  if ( lightsHash === undefined ) {
23973 
23974  materialProperties.lightsHash = lightsHash = {};
23975 
23976  }
23977 
23978  lightsHash.stateID = lightsStateHash.stateID;
23979  lightsHash.directionalLength = lightsStateHash.directionalLength;
23980  lightsHash.pointLength = lightsStateHash.pointLength;
23981  lightsHash.spotLength = lightsStateHash.spotLength;
23982  lightsHash.rectAreaLength = lightsStateHash.rectAreaLength;
23983  lightsHash.hemiLength = lightsStateHash.hemiLength;
23984  lightsHash.shadowsLength = lightsStateHash.shadowsLength;
23985 
23986  if ( material.lights ) {
23987 
23988  // wire up the material to this renderer's lighting state
23989 
23990  uniforms.ambientLightColor.value = lights.state.ambient;
23991  uniforms.directionalLights.value = lights.state.directional;
23992  uniforms.spotLights.value = lights.state.spot;
23993  uniforms.rectAreaLights.value = lights.state.rectArea;
23994  uniforms.pointLights.value = lights.state.point;
23995  uniforms.hemisphereLights.value = lights.state.hemi;
23996 
23997  uniforms.directionalShadowMap.value = lights.state.directionalShadowMap;
23998  uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix;
23999  uniforms.spotShadowMap.value = lights.state.spotShadowMap;
24000  uniforms.spotShadowMatrix.value = lights.state.spotShadowMatrix;
24001  uniforms.pointShadowMap.value = lights.state.pointShadowMap;
24002  uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix;
24003  // TODO (abelnation): add area lights shadow info to uniforms
24004 
24005  }
24006 
24007  var progUniforms = materialProperties.program.getUniforms(),
24008  uniformsList =
24009  WebGLUniforms.seqWithValue( progUniforms.seq, uniforms );
24010 
24011  materialProperties.uniformsList = uniformsList;
24012 
24013  }
24014 
24015  function setProgram( camera, fog, material, object ) {
24016 
24017  _usedTextureUnits = 0;
24018 
24019  var materialProperties = properties.get( material );
24020  var lights = currentRenderState.state.lights;
24021 
24022  var lightsHash = materialProperties.lightsHash;
24023  var lightsStateHash = lights.state.hash;
24024 
24025  if ( _clippingEnabled ) {
24026 
24027  if ( _localClippingEnabled || camera !== _currentCamera ) {
24028 
24029  var useCache =
24030  camera === _currentCamera &&
24031  material.id === _currentMaterialId;
24032 
24033  // we might want to call this function with some ClippingGroup
24034  // object instead of the material, once it becomes feasible
24035  // (#8465, #8379)
24036  _clipping.setState(
24037  material.clippingPlanes, material.clipIntersection, material.clipShadows,
24038  camera, materialProperties, useCache );
24039 
24040  }
24041 
24042  }
24043 
24044  if ( material.needsUpdate === false ) {
24045 
24046  if ( materialProperties.program === undefined ) {
24047 
24048  material.needsUpdate = true;
24049 
24050  } else if ( material.fog && materialProperties.fog !== fog ) {
24051 
24052  material.needsUpdate = true;
24053 
24054  } else if ( material.lights && ( lightsHash.stateID !== lightsStateHash.stateID ||
24055  lightsHash.directionalLength !== lightsStateHash.directionalLength ||
24056  lightsHash.pointLength !== lightsStateHash.pointLength ||
24057  lightsHash.spotLength !== lightsStateHash.spotLength ||
24058  lightsHash.rectAreaLength !== lightsStateHash.rectAreaLength ||
24059  lightsHash.hemiLength !== lightsStateHash.hemiLength ||
24060  lightsHash.shadowsLength !== lightsStateHash.shadowsLength ) ) {
24061 
24062  material.needsUpdate = true;
24063 
24064  } else if ( materialProperties.numClippingPlanes !== undefined &&
24065  ( materialProperties.numClippingPlanes !== _clipping.numPlanes ||
24066  materialProperties.numIntersection !== _clipping.numIntersection ) ) {
24067 
24068  material.needsUpdate = true;
24069 
24070  }
24071 
24072  }
24073 
24074  if ( material.needsUpdate ) {
24075 
24076  initMaterial( material, fog, object );
24077  material.needsUpdate = false;
24078 
24079  }
24080 
24081  var refreshProgram = false;
24082  var refreshMaterial = false;
24083  var refreshLights = false;
24084 
24085  var program = materialProperties.program,
24086  p_uniforms = program.getUniforms(),
24087  m_uniforms = materialProperties.shader.uniforms;
24088 
24089  if ( state.useProgram( program.program ) ) {
24090 
24091  refreshProgram = true;
24092  refreshMaterial = true;
24093  refreshLights = true;
24094 
24095  }
24096 
24097  if ( material.id !== _currentMaterialId ) {
24098 
24099  _currentMaterialId = material.id;
24100 
24101  refreshMaterial = true;
24102 
24103  }
24104 
24105  if ( refreshProgram || _currentCamera !== camera ) {
24106 
24107  p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix );
24108 
24109  if ( capabilities.logarithmicDepthBuffer ) {
24110 
24111  p_uniforms.setValue( _gl, 'logDepthBufFC',
24112  2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) );
24113 
24114  }
24115 
24116  if ( _currentCamera !== camera ) {
24117 
24118  _currentCamera = camera;
24119 
24120  // lighting uniforms depend on the camera so enforce an update
24121  // now, in case this material supports lights - or later, when
24122  // the next material that does gets activated:
24123 
24124  refreshMaterial = true; // set to true on material change
24125  refreshLights = true; // remains set until update done
24126 
24127  }
24128 
24129  // load material specific uniforms
24130  // (shader material also gets them for the sake of genericity)
24131 
24132  if ( material.isShaderMaterial ||
24133  material.isMeshPhongMaterial ||
24134  material.isMeshStandardMaterial ||
24135  material.envMap ) {
24136 
24137  var uCamPos = p_uniforms.map.cameraPosition;
24138 
24139  if ( uCamPos !== undefined ) {
24140 
24141  uCamPos.setValue( _gl,
24142  _vector3.setFromMatrixPosition( camera.matrixWorld ) );
24143 
24144  }
24145 
24146  }
24147 
24148  if ( material.isMeshPhongMaterial ||
24149  material.isMeshLambertMaterial ||
24150  material.isMeshBasicMaterial ||
24151  material.isMeshStandardMaterial ||
24152  material.isShaderMaterial ||
24153  material.skinning ) {
24154 
24155  p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse );
24156 
24157  }
24158 
24159  }
24160 
24161  // skinning uniforms must be set even if material didn't change
24162  // auto-setting of texture unit for bone texture must go before other textures
24163  // not sure why, but otherwise weird things happen
24164 
24165  if ( material.skinning ) {
24166 
24167  p_uniforms.setOptional( _gl, object, 'bindMatrix' );
24168  p_uniforms.setOptional( _gl, object, 'bindMatrixInverse' );
24169 
24170  var skeleton = object.skeleton;
24171 
24172  if ( skeleton ) {
24173 
24174  var bones = skeleton.bones;
24175 
24176  if ( capabilities.floatVertexTextures ) {
24177 
24178  if ( skeleton.boneTexture === undefined ) {
24179 
24180  // layout (1 matrix = 4 pixels)
24181  // RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)
24182  // with 8x8 pixel texture max 16 bones * 4 pixels = (8 * 8)
24183  // 16x16 pixel texture max 64 bones * 4 pixels = (16 * 16)
24184  // 32x32 pixel texture max 256 bones * 4 pixels = (32 * 32)
24185  // 64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64)
24186 
24187 
24188  var size = Math.sqrt( bones.length * 4 ); // 4 pixels needed for 1 matrix
24189  size = _Math.ceilPowerOfTwo( size );
24190  size = Math.max( size, 4 );
24191 
24192  var boneMatrices = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel
24193  boneMatrices.set( skeleton.boneMatrices ); // copy current values
24194 
24195  var boneTexture = new DataTexture( boneMatrices, size, size, RGBAFormat, FloatType );
24196  boneTexture.needsUpdate = true;
24197 
24198  skeleton.boneMatrices = boneMatrices;
24199  skeleton.boneTexture = boneTexture;
24200  skeleton.boneTextureSize = size;
24201 
24202  }
24203 
24204  p_uniforms.setValue( _gl, 'boneTexture', skeleton.boneTexture );
24205  p_uniforms.setValue( _gl, 'boneTextureSize', skeleton.boneTextureSize );
24206 
24207  } else {
24208 
24209  p_uniforms.setOptional( _gl, skeleton, 'boneMatrices' );
24210 
24211  }
24212 
24213  }
24214 
24215  }
24216 
24217  if ( refreshMaterial ) {
24218 
24219  p_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure );
24220  p_uniforms.setValue( _gl, 'toneMappingWhitePoint', _this.toneMappingWhitePoint );
24221 
24222  if ( material.lights ) {
24223 
24224  // the current material requires lighting info
24225 
24226  // note: all lighting uniforms are always set correctly
24227  // they simply reference the renderer's state for their
24228  // values
24229  //
24230  // use the current material's .needsUpdate flags to set
24231  // the GL state when required
24232 
24233  markUniformsLightsNeedsUpdate( m_uniforms, refreshLights );
24234 
24235  }
24236 
24237  // refresh uniforms common to several materials
24238 
24239  if ( fog && material.fog ) {
24240 
24241  refreshUniformsFog( m_uniforms, fog );
24242 
24243  }
24244 
24245  if ( material.isMeshBasicMaterial ) {
24246 
24247  refreshUniformsCommon( m_uniforms, material );
24248 
24249  } else if ( material.isMeshLambertMaterial ) {
24250 
24251  refreshUniformsCommon( m_uniforms, material );
24252  refreshUniformsLambert( m_uniforms, material );
24253 
24254  } else if ( material.isMeshPhongMaterial ) {
24255 
24256  refreshUniformsCommon( m_uniforms, material );
24257 
24258  if ( material.isMeshToonMaterial ) {
24259 
24260  refreshUniformsToon( m_uniforms, material );
24261 
24262  } else {
24263 
24264  refreshUniformsPhong( m_uniforms, material );
24265 
24266  }
24267 
24268  } else if ( material.isMeshStandardMaterial ) {
24269 
24270  refreshUniformsCommon( m_uniforms, material );
24271 
24272  if ( material.isMeshPhysicalMaterial ) {
24273 
24274  refreshUniformsPhysical( m_uniforms, material );
24275 
24276  } else {
24277 
24278  refreshUniformsStandard( m_uniforms, material );
24279 
24280  }
24281 
24282  } else if ( material.isMeshMatcapMaterial ) {
24283 
24284  refreshUniformsCommon( m_uniforms, material );
24285 
24286  refreshUniformsMatcap( m_uniforms, material );
24287 
24288  } else if ( material.isMeshDepthMaterial ) {
24289 
24290  refreshUniformsCommon( m_uniforms, material );
24291  refreshUniformsDepth( m_uniforms, material );
24292 
24293  } else if ( material.isMeshDistanceMaterial ) {
24294 
24295  refreshUniformsCommon( m_uniforms, material );
24296  refreshUniformsDistance( m_uniforms, material );
24297 
24298  } else if ( material.isMeshNormalMaterial ) {
24299 
24300  refreshUniformsCommon( m_uniforms, material );
24301  refreshUniformsNormal( m_uniforms, material );
24302 
24303  } else if ( material.isLineBasicMaterial ) {
24304 
24305  refreshUniformsLine( m_uniforms, material );
24306 
24307  if ( material.isLineDashedMaterial ) {
24308 
24309  refreshUniformsDash( m_uniforms, material );
24310 
24311  }
24312 
24313  } else if ( material.isPointsMaterial ) {
24314 
24315  refreshUniformsPoints( m_uniforms, material );
24316 
24317  } else if ( material.isSpriteMaterial ) {
24318 
24319  refreshUniformsSprites( m_uniforms, material );
24320 
24321  } else if ( material.isShadowMaterial ) {
24322 
24323  m_uniforms.color.value = material.color;
24324  m_uniforms.opacity.value = material.opacity;
24325 
24326  }
24327 
24328  // RectAreaLight Texture
24329  // TODO (mrdoob): Find a nicer implementation
24330 
24331  if ( m_uniforms.ltc_1 !== undefined ) m_uniforms.ltc_1.value = UniformsLib.LTC_1;
24332  if ( m_uniforms.ltc_2 !== undefined ) m_uniforms.ltc_2.value = UniformsLib.LTC_2;
24333 
24334  WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, _this );
24335 
24336  }
24337 
24338  if ( material.isShaderMaterial && material.uniformsNeedUpdate === true ) {
24339 
24340  WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, _this );
24341  material.uniformsNeedUpdate = false;
24342 
24343  }
24344 
24345  if ( material.isSpriteMaterial ) {
24346 
24347  p_uniforms.setValue( _gl, 'center', object.center );
24348 
24349  }
24350 
24351  // common matrices
24352 
24353  p_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix );
24354  p_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix );
24355  p_uniforms.setValue( _gl, 'modelMatrix', object.matrixWorld );
24356 
24357  return program;
24358 
24359  }
24360 
24361  // Uniforms (refresh uniforms objects)
24362 
24363  function refreshUniformsCommon( uniforms, material ) {
24364 
24365  uniforms.opacity.value = material.opacity;
24366 
24367  if ( material.color ) {
24368 
24369  uniforms.diffuse.value = material.color;
24370 
24371  }
24372 
24373  if ( material.emissive ) {
24374 
24375  uniforms.emissive.value.copy( material.emissive ).multiplyScalar( material.emissiveIntensity );
24376 
24377  }
24378 
24379  if ( material.map ) {
24380 
24381  uniforms.map.value = material.map;
24382 
24383  }
24384 
24385  if ( material.alphaMap ) {
24386 
24387  uniforms.alphaMap.value = material.alphaMap;
24388 
24389  }
24390 
24391  if ( material.specularMap ) {
24392 
24393  uniforms.specularMap.value = material.specularMap;
24394 
24395  }
24396 
24397  if ( material.envMap ) {
24398 
24399  uniforms.envMap.value = material.envMap;
24400 
24401  // don't flip CubeTexture envMaps, flip everything else:
24402  // WebGLRenderTargetCube will be flipped for backwards compatibility
24403  // WebGLRenderTargetCube.texture will be flipped because it's a Texture and NOT a CubeTexture
24404  // this check must be handled differently, or removed entirely, if WebGLRenderTargetCube uses a CubeTexture in the future
24405  uniforms.flipEnvMap.value = material.envMap.isCubeTexture ? - 1 : 1;
24406 
24407  uniforms.reflectivity.value = material.reflectivity;
24408  uniforms.refractionRatio.value = material.refractionRatio;
24409 
24410  uniforms.maxMipLevel.value = properties.get( material.envMap ).__maxMipLevel;
24411 
24412  }
24413 
24414  if ( material.lightMap ) {
24415 
24416  uniforms.lightMap.value = material.lightMap;
24417  uniforms.lightMapIntensity.value = material.lightMapIntensity;
24418 
24419  }
24420 
24421  if ( material.aoMap ) {
24422 
24423  uniforms.aoMap.value = material.aoMap;
24424  uniforms.aoMapIntensity.value = material.aoMapIntensity;
24425 
24426  }
24427 
24428  // uv repeat and offset setting priorities
24429  // 1. color map
24430  // 2. specular map
24431  // 3. normal map
24432  // 4. bump map
24433  // 5. alpha map
24434  // 6. emissive map
24435 
24436  var uvScaleMap;
24437 
24438  if ( material.map ) {
24439 
24440  uvScaleMap = material.map;
24441 
24442  } else if ( material.specularMap ) {
24443 
24444  uvScaleMap = material.specularMap;
24445 
24446  } else if ( material.displacementMap ) {
24447 
24448  uvScaleMap = material.displacementMap;
24449 
24450  } else if ( material.normalMap ) {
24451 
24452  uvScaleMap = material.normalMap;
24453 
24454  } else if ( material.bumpMap ) {
24455 
24456  uvScaleMap = material.bumpMap;
24457 
24458  } else if ( material.roughnessMap ) {
24459 
24460  uvScaleMap = material.roughnessMap;
24461 
24462  } else if ( material.metalnessMap ) {
24463 
24464  uvScaleMap = material.metalnessMap;
24465 
24466  } else if ( material.alphaMap ) {
24467 
24468  uvScaleMap = material.alphaMap;
24469 
24470  } else if ( material.emissiveMap ) {
24471 
24472  uvScaleMap = material.emissiveMap;
24473 
24474  }
24475 
24476  if ( uvScaleMap !== undefined ) {
24477 
24478  // backwards compatibility
24479  if ( uvScaleMap.isWebGLRenderTarget ) {
24480 
24481  uvScaleMap = uvScaleMap.texture;
24482 
24483  }
24484 
24485  if ( uvScaleMap.matrixAutoUpdate === true ) {
24486 
24487  uvScaleMap.updateMatrix();
24488 
24489  }
24490 
24491  uniforms.uvTransform.value.copy( uvScaleMap.matrix );
24492 
24493  }
24494 
24495  }
24496 
24497  function refreshUniformsLine( uniforms, material ) {
24498 
24499  uniforms.diffuse.value = material.color;
24500  uniforms.opacity.value = material.opacity;
24501 
24502  }
24503 
24504  function refreshUniformsDash( uniforms, material ) {
24505 
24506  uniforms.dashSize.value = material.dashSize;
24507  uniforms.totalSize.value = material.dashSize + material.gapSize;
24508  uniforms.scale.value = material.scale;
24509 
24510  }
24511 
24512  function refreshUniformsPoints( uniforms, material ) {
24513 
24514  uniforms.diffuse.value = material.color;
24515  uniforms.opacity.value = material.opacity;
24516  uniforms.size.value = material.size * _pixelRatio;
24517  uniforms.scale.value = _height * 0.5;
24518 
24519  uniforms.map.value = material.map;
24520 
24521  if ( material.map !== null ) {
24522 
24523  if ( material.map.matrixAutoUpdate === true ) {
24524 
24525  material.map.updateMatrix();
24526 
24527  }
24528 
24529  uniforms.uvTransform.value.copy( material.map.matrix );
24530 
24531  }
24532 
24533  }
24534 
24535  function refreshUniformsSprites( uniforms, material ) {
24536 
24537  uniforms.diffuse.value = material.color;
24538  uniforms.opacity.value = material.opacity;
24539  uniforms.rotation.value = material.rotation;
24540  uniforms.map.value = material.map;
24541 
24542  if ( material.map !== null ) {
24543 
24544  if ( material.map.matrixAutoUpdate === true ) {
24545 
24546  material.map.updateMatrix();
24547 
24548  }
24549 
24550  uniforms.uvTransform.value.copy( material.map.matrix );
24551 
24552  }
24553 
24554  }
24555 
24556  function refreshUniformsFog( uniforms, fog ) {
24557 
24558  uniforms.fogColor.value = fog.color;
24559 
24560  if ( fog.isFog ) {
24561 
24562  uniforms.fogNear.value = fog.near;
24563  uniforms.fogFar.value = fog.far;
24564 
24565  } else if ( fog.isFogExp2 ) {
24566 
24567  uniforms.fogDensity.value = fog.density;
24568 
24569  }
24570 
24571  }
24572 
24573  function refreshUniformsLambert( uniforms, material ) {
24574 
24575  if ( material.emissiveMap ) {
24576 
24577  uniforms.emissiveMap.value = material.emissiveMap;
24578 
24579  }
24580 
24581  }
24582 
24583  function refreshUniformsPhong( uniforms, material ) {
24584 
24585  uniforms.specular.value = material.specular;
24586  uniforms.shininess.value = Math.max( material.shininess, 1e-4 ); // to prevent pow( 0.0, 0.0 )
24587 
24588  if ( material.emissiveMap ) {
24589 
24590  uniforms.emissiveMap.value = material.emissiveMap;
24591 
24592  }
24593 
24594  if ( material.bumpMap ) {
24595 
24596  uniforms.bumpMap.value = material.bumpMap;
24597  uniforms.bumpScale.value = material.bumpScale;
24598  if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;
24599 
24600  }
24601 
24602  if ( material.normalMap ) {
24603 
24604  uniforms.normalMap.value = material.normalMap;
24605  uniforms.normalScale.value.copy( material.normalScale );
24606  if ( material.side === BackSide ) uniforms.normalScale.value.negate();
24607 
24608  }
24609 
24610  if ( material.displacementMap ) {
24611 
24612  uniforms.displacementMap.value = material.displacementMap;
24613  uniforms.displacementScale.value = material.displacementScale;
24614  uniforms.displacementBias.value = material.displacementBias;
24615 
24616  }
24617 
24618  }
24619 
24620  function refreshUniformsToon( uniforms, material ) {
24621 
24622  refreshUniformsPhong( uniforms, material );
24623 
24624  if ( material.gradientMap ) {
24625 
24626  uniforms.gradientMap.value = material.gradientMap;
24627 
24628  }
24629 
24630  }
24631 
24632  function refreshUniformsStandard( uniforms, material ) {
24633 
24634  uniforms.roughness.value = material.roughness;
24635  uniforms.metalness.value = material.metalness;
24636 
24637  if ( material.roughnessMap ) {
24638 
24639  uniforms.roughnessMap.value = material.roughnessMap;
24640 
24641  }
24642 
24643  if ( material.metalnessMap ) {
24644 
24645  uniforms.metalnessMap.value = material.metalnessMap;
24646 
24647  }
24648 
24649  if ( material.emissiveMap ) {
24650 
24651  uniforms.emissiveMap.value = material.emissiveMap;
24652 
24653  }
24654 
24655  if ( material.bumpMap ) {
24656 
24657  uniforms.bumpMap.value = material.bumpMap;
24658  uniforms.bumpScale.value = material.bumpScale;
24659  if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;
24660 
24661  }
24662 
24663  if ( material.normalMap ) {
24664 
24665  uniforms.normalMap.value = material.normalMap;
24666  uniforms.normalScale.value.copy( material.normalScale );
24667  if ( material.side === BackSide ) uniforms.normalScale.value.negate();
24668 
24669  }
24670 
24671  if ( material.displacementMap ) {
24672 
24673  uniforms.displacementMap.value = material.displacementMap;
24674  uniforms.displacementScale.value = material.displacementScale;
24675  uniforms.displacementBias.value = material.displacementBias;
24676 
24677  }
24678 
24679  if ( material.envMap ) {
24680 
24681  //uniforms.envMap.value = material.envMap; // part of uniforms common
24682  uniforms.envMapIntensity.value = material.envMapIntensity;
24683 
24684  }
24685 
24686  }
24687 
24688  function refreshUniformsPhysical( uniforms, material ) {
24689 
24690  refreshUniformsStandard( uniforms, material );
24691 
24692  uniforms.reflectivity.value = material.reflectivity; // also part of uniforms common
24693 
24694  uniforms.clearCoat.value = material.clearCoat;
24695  uniforms.clearCoatRoughness.value = material.clearCoatRoughness;
24696 
24697  }
24698 
24699  function refreshUniformsMatcap( uniforms, material ) {
24700 
24701  if ( material.matcap ) {
24702 
24703  uniforms.matcap.value = material.matcap;
24704 
24705  }
24706 
24707  if ( material.bumpMap ) {
24708 
24709  uniforms.bumpMap.value = material.bumpMap;
24710  uniforms.bumpScale.value = material.bumpScale;
24711  if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;
24712 
24713  }
24714 
24715  if ( material.normalMap ) {
24716 
24717  uniforms.normalMap.value = material.normalMap;
24718  uniforms.normalScale.value.copy( material.normalScale );
24719  if ( material.side === BackSide ) uniforms.normalScale.value.negate();
24720 
24721  }
24722 
24723  if ( material.displacementMap ) {
24724 
24725  uniforms.displacementMap.value = material.displacementMap;
24726  uniforms.displacementScale.value = material.displacementScale;
24727  uniforms.displacementBias.value = material.displacementBias;
24728 
24729  }
24730 
24731  }
24732 
24733  function refreshUniformsDepth( uniforms, material ) {
24734 
24735  if ( material.displacementMap ) {
24736 
24737  uniforms.displacementMap.value = material.displacementMap;
24738  uniforms.displacementScale.value = material.displacementScale;
24739  uniforms.displacementBias.value = material.displacementBias;
24740 
24741  }
24742 
24743  }
24744 
24745  function refreshUniformsDistance( uniforms, material ) {
24746 
24747  if ( material.displacementMap ) {
24748 
24749  uniforms.displacementMap.value = material.displacementMap;
24750  uniforms.displacementScale.value = material.displacementScale;
24751  uniforms.displacementBias.value = material.displacementBias;
24752 
24753  }
24754 
24755  uniforms.referencePosition.value.copy( material.referencePosition );
24756  uniforms.nearDistance.value = material.nearDistance;
24757  uniforms.farDistance.value = material.farDistance;
24758 
24759  }
24760 
24761  function refreshUniformsNormal( uniforms, material ) {
24762 
24763  if ( material.bumpMap ) {
24764 
24765  uniforms.bumpMap.value = material.bumpMap;
24766  uniforms.bumpScale.value = material.bumpScale;
24767  if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;
24768 
24769  }
24770 
24771  if ( material.normalMap ) {
24772 
24773  uniforms.normalMap.value = material.normalMap;
24774  uniforms.normalScale.value.copy( material.normalScale );
24775  if ( material.side === BackSide ) uniforms.normalScale.value.negate();
24776 
24777  }
24778 
24779  if ( material.displacementMap ) {
24780 
24781  uniforms.displacementMap.value = material.displacementMap;
24782  uniforms.displacementScale.value = material.displacementScale;
24783  uniforms.displacementBias.value = material.displacementBias;
24784 
24785  }
24786 
24787  }
24788 
24789  // If uniforms are marked as clean, they don't need to be loaded to the GPU.
24790 
24791  function markUniformsLightsNeedsUpdate( uniforms, value ) {
24792 
24793  uniforms.ambientLightColor.needsUpdate = value;
24794 
24795  uniforms.directionalLights.needsUpdate = value;
24796  uniforms.pointLights.needsUpdate = value;
24797  uniforms.spotLights.needsUpdate = value;
24798  uniforms.rectAreaLights.needsUpdate = value;
24799  uniforms.hemisphereLights.needsUpdate = value;
24800 
24801  }
24802 
24803  // Textures
24804 
24805  function allocTextureUnit() {
24806 
24807  var textureUnit = _usedTextureUnits;
24808 
24809  if ( textureUnit >= capabilities.maxTextures ) {
24810 
24811  console.warn( 'THREE.WebGLRenderer: Trying to use ' + textureUnit + ' texture units while this GPU supports only ' + capabilities.maxTextures );
24812 
24813  }
24814 
24815  _usedTextureUnits += 1;
24816 
24817  return textureUnit;
24818 
24819  }
24820 
24821  this.allocTextureUnit = allocTextureUnit;
24822 
24823  // this.setTexture2D = setTexture2D;
24824  this.setTexture2D = ( function () {
24825 
24826  var warned = false;
24827 
24828  // backwards compatibility: peel texture.texture
24829  return function setTexture2D( texture, slot ) {
24830 
24831  if ( texture && texture.isWebGLRenderTarget ) {
24832 
24833  if ( ! warned ) {
24834 
24835  console.warn( "THREE.WebGLRenderer.setTexture2D: don't use render targets as textures. Use their .texture property instead." );
24836  warned = true;
24837 
24838  }
24839 
24840  texture = texture.texture;
24841 
24842  }
24843 
24844  textures.setTexture2D( texture, slot );
24845 
24846  };
24847 
24848  }() );
24849 
24850  this.setTexture3D = ( function () {
24851 
24852  // backwards compatibility: peel texture.texture
24853  return function setTexture3D( texture, slot ) {
24854 
24855  textures.setTexture3D( texture, slot );
24856 
24857  };
24858 
24859  }() );
24860 
24861  this.setTexture = ( function () {
24862 
24863  var warned = false;
24864 
24865  return function setTexture( texture, slot ) {
24866 
24867  if ( ! warned ) {
24868 
24869  console.warn( "THREE.WebGLRenderer: .setTexture is deprecated, use setTexture2D instead." );
24870  warned = true;
24871 
24872  }
24873 
24874  textures.setTexture2D( texture, slot );
24875 
24876  };
24877 
24878  }() );
24879 
24880  this.setTextureCube = ( function () {
24881 
24882  var warned = false;
24883 
24884  return function setTextureCube( texture, slot ) {
24885 
24886  // backwards compatibility: peel texture.texture
24887  if ( texture && texture.isWebGLRenderTargetCube ) {
24888 
24889  if ( ! warned ) {
24890 
24891  console.warn( "THREE.WebGLRenderer.setTextureCube: don't use cube render targets as textures. Use their .texture property instead." );
24892  warned = true;
24893 
24894  }
24895 
24896  texture = texture.texture;
24897 
24898  }
24899 
24900  // currently relying on the fact that WebGLRenderTargetCube.texture is a Texture and NOT a CubeTexture
24901  // TODO: unify these code paths
24902  if ( ( texture && texture.isCubeTexture ) ||
24903  ( Array.isArray( texture.image ) && texture.image.length === 6 ) ) {
24904 
24905  // CompressedTexture can have Array in image :/
24906 
24907  // this function alone should take care of cube textures
24908  textures.setTextureCube( texture, slot );
24909 
24910  } else {
24911 
24912  // assumed: texture property of THREE.WebGLRenderTargetCube
24913 
24914  textures.setTextureCubeDynamic( texture, slot );
24915 
24916  }
24917 
24918  };
24919 
24920  }() );
24921 
24922  //
24923 
24924  this.setFramebuffer = function ( value ) {
24925 
24926  _framebuffer = value;
24927 
24928  };
24929 
24930  this.getRenderTarget = function () {
24931 
24932  return _currentRenderTarget;
24933 
24934  };
24935 
24936  this.setRenderTarget = function ( renderTarget, activeCubeFace, activeMipMapLevel ) {
24937 
24938  _currentRenderTarget = renderTarget;
24939 
24940  if ( renderTarget && properties.get( renderTarget ).__webglFramebuffer === undefined ) {
24941 
24942  textures.setupRenderTarget( renderTarget );
24943 
24944  }
24945 
24946  var framebuffer = _framebuffer;
24947  var isCube = false;
24948 
24949  if ( renderTarget ) {
24950 
24951  var __webglFramebuffer = properties.get( renderTarget ).__webglFramebuffer;
24952 
24953  if ( renderTarget.isWebGLRenderTargetCube ) {
24954 
24955  framebuffer = __webglFramebuffer[ activeCubeFace || 0 ];
24956  isCube = true;
24957 
24958  } else if ( renderTarget.isWebGLMultisampleRenderTarget ) {
24959 
24960  framebuffer = properties.get( renderTarget ).__webglMultisampledFramebuffer;
24961 
24962  } else {
24963 
24964  framebuffer = __webglFramebuffer;
24965 
24966  }
24967 
24968  _currentViewport.copy( renderTarget.viewport );
24969  _currentScissor.copy( renderTarget.scissor );
24970  _currentScissorTest = renderTarget.scissorTest;
24971 
24972  } else {
24973 
24974  _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio );
24975  _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio );
24976  _currentScissorTest = _scissorTest;
24977 
24978  }
24979 
24980  if ( _currentFramebuffer !== framebuffer ) {
24981 
24982  _gl.bindFramebuffer( 36160, framebuffer );
24983  _currentFramebuffer = framebuffer;
24984 
24985  }
24986 
24987  state.viewport( _currentViewport );
24988  state.scissor( _currentScissor );
24989  state.setScissorTest( _currentScissorTest );
24990 
24991  if ( isCube ) {
24992 
24993  var textureProperties = properties.get( renderTarget.texture );
24994  _gl.framebufferTexture2D( 36160, 36064, 34069 + activeCubeFace || 0, textureProperties.__webglTexture, activeMipMapLevel || 0 );
24995 
24996  }
24997 
24998  };
24999 
25000  this.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer ) {
25001 
25002  if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) {
25003 
25004  console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' );
25005  return;
25006 
25007  }
25008 
25009  var framebuffer = properties.get( renderTarget ).__webglFramebuffer;
25010 
25011  if ( framebuffer ) {
25012 
25013  var restore = false;
25014 
25015  if ( framebuffer !== _currentFramebuffer ) {
25016 
25017  _gl.bindFramebuffer( 36160, framebuffer );
25018 
25019  restore = true;
25020 
25021  }
25022 
25023  try {
25024 
25025  var texture = renderTarget.texture;
25026  var textureFormat = texture.format;
25027  var textureType = texture.type;
25028 
25029  if ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== _gl.getParameter( 35739 ) ) {
25030 
25031  console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' );
25032  return;
25033 
25034  }
25035 
25036  if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( 35738 ) && // IE11, Edge and Chrome Mac < 52 (#9513)
25037  ! ( textureType === FloatType && ( capabilities.isWebGL2 || extensions.get( 'OES_texture_float' ) || extensions.get( 'WEBGL_color_buffer_float' ) ) ) && // Chrome Mac >= 52 and Firefox
25038  ! ( textureType === HalfFloatType && ( capabilities.isWebGL2 ? extensions.get( 'EXT_color_buffer_float' ) : extensions.get( 'EXT_color_buffer_half_float' ) ) ) ) {
25039 
25040  console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' );
25041  return;
25042 
25043  }
25044 
25045  if ( _gl.checkFramebufferStatus( 36160 ) === 36053 ) {
25046 
25047  // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604)
25048 
25049  if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) {
25050 
25051  _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer );
25052 
25053  }
25054 
25055  } else {
25056 
25057  console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.' );
25058 
25059  }
25060 
25061  } finally {
25062 
25063  if ( restore ) {
25064 
25065  _gl.bindFramebuffer( 36160, _currentFramebuffer );
25066 
25067  }
25068 
25069  }
25070 
25071  }
25072 
25073  };
25074 
25075  this.copyFramebufferToTexture = function ( position, texture, level ) {
25076 
25077  var width = texture.image.width;
25078  var height = texture.image.height;
25079  var glFormat = utils.convert( texture.format );
25080 
25081  this.setTexture2D( texture, 0 );
25082 
25083  _gl.copyTexImage2D( 3553, level || 0, glFormat, position.x, position.y, width, height, 0 );
25084 
25085  };
25086 
25087  this.copyTextureToTexture = function ( position, srcTexture, dstTexture, level ) {
25088 
25089  var width = srcTexture.image.width;
25090  var height = srcTexture.image.height;
25091  var glFormat = utils.convert( dstTexture.format );
25092  var glType = utils.convert( dstTexture.type );
25093 
25094  this.setTexture2D( dstTexture, 0 );
25095 
25096  if ( srcTexture.isDataTexture ) {
25097 
25098  _gl.texSubImage2D( 3553, level || 0, position.x, position.y, width, height, glFormat, glType, srcTexture.image.data );
25099 
25100  } else {
25101 
25102  _gl.texSubImage2D( 3553, level || 0, position.x, position.y, glFormat, glType, srcTexture.image );
25103 
25104  }
25105 
25106  };
25107 
25108  }
25109 
25115  function FogExp2( color, density ) {
25116 
25117  this.name = '';
25118 
25119  this.color = new Color( color );
25120  this.density = ( density !== undefined ) ? density : 0.00025;
25121 
25122  }
25123 
25124  Object.assign( FogExp2.prototype, {
25125 
25126  isFogExp2: true,
25127 
25128  clone: function () {
25129 
25130  return new FogExp2( this.color, this.density );
25131 
25132  },
25133 
25134  toJSON: function ( /* meta */ ) {
25135 
25136  return {
25137  type: 'FogExp2',
25138  color: this.color.getHex(),
25139  density: this.density
25140  };
25141 
25142  }
25143 
25144  } );
25145 
25151  function Fog( color, near, far ) {
25152 
25153  this.name = '';
25154 
25155  this.color = new Color( color );
25156 
25157  this.near = ( near !== undefined ) ? near : 1;
25158  this.far = ( far !== undefined ) ? far : 1000;
25159 
25160  }
25161 
25162  Object.assign( Fog.prototype, {
25163 
25164  isFog: true,
25165 
25166  clone: function () {
25167 
25168  return new Fog( this.color, this.near, this.far );
25169 
25170  },
25171 
25172  toJSON: function ( /* meta */ ) {
25173 
25174  return {
25175  type: 'Fog',
25176  color: this.color.getHex(),
25177  near: this.near,
25178  far: this.far
25179  };
25180 
25181  }
25182 
25183  } );
25184 
25189  function Scene() {
25190 
25191  Object3D.call( this );
25192 
25193  this.type = 'Scene';
25194 
25195  this.background = null;
25196  this.fog = null;
25197  this.overrideMaterial = null;
25198 
25199  this.autoUpdate = true; // checked by the renderer
25200 
25201  }
25202 
25203  Scene.prototype = Object.assign( Object.create( Object3D.prototype ), {
25204 
25205  constructor: Scene,
25206 
25207  isScene: true,
25208 
25209  copy: function ( source, recursive ) {
25210 
25211  Object3D.prototype.copy.call( this, source, recursive );
25212 
25213  if ( source.background !== null ) this.background = source.background.clone();
25214  if ( source.fog !== null ) this.fog = source.fog.clone();
25215  if ( source.overrideMaterial !== null ) this.overrideMaterial = source.overrideMaterial.clone();
25216 
25217  this.autoUpdate = source.autoUpdate;
25218  this.matrixAutoUpdate = source.matrixAutoUpdate;
25219 
25220  return this;
25221 
25222  },
25223 
25224  toJSON: function ( meta ) {
25225 
25226  var data = Object3D.prototype.toJSON.call( this, meta );
25227 
25228  if ( this.background !== null ) data.object.background = this.background.toJSON( meta );
25229  if ( this.fog !== null ) data.object.fog = this.fog.toJSON();
25230 
25231  return data;
25232 
25233  },
25234 
25235  dispose: function () {
25236 
25237  this.dispatchEvent( { type: 'dispose' } );
25238 
25239  }
25240 
25241  } );
25242 
25247  function InterleavedBuffer( array, stride ) {
25248 
25249  this.array = array;
25250  this.stride = stride;
25251  this.count = array !== undefined ? array.length / stride : 0;
25252 
25253  this.dynamic = false;
25254  this.updateRange = { offset: 0, count: - 1 };
25255 
25256  this.version = 0;
25257 
25258  }
25259 
25260  Object.defineProperty( InterleavedBuffer.prototype, 'needsUpdate', {
25261 
25262  set: function ( value ) {
25263 
25264  if ( value === true ) this.version ++;
25265 
25266  }
25267 
25268  } );
25269 
25270  Object.assign( InterleavedBuffer.prototype, {
25271 
25272  isInterleavedBuffer: true,
25273 
25274  onUploadCallback: function () {},
25275 
25276  setArray: function ( array ) {
25277 
25278  if ( Array.isArray( array ) ) {
25279 
25280  throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' );
25281 
25282  }
25283 
25284  this.count = array !== undefined ? array.length / this.stride : 0;
25285  this.array = array;
25286 
25287  return this;
25288 
25289  },
25290 
25291  setDynamic: function ( value ) {
25292 
25293  this.dynamic = value;
25294 
25295  return this;
25296 
25297  },
25298 
25299  copy: function ( source ) {
25300 
25301  this.array = new source.array.constructor( source.array );
25302  this.count = source.count;
25303  this.stride = source.stride;
25304  this.dynamic = source.dynamic;
25305 
25306  return this;
25307 
25308  },
25309 
25310  copyAt: function ( index1, attribute, index2 ) {
25311 
25312  index1 *= this.stride;
25313  index2 *= attribute.stride;
25314 
25315  for ( var i = 0, l = this.stride; i < l; i ++ ) {
25316 
25317  this.array[ index1 + i ] = attribute.array[ index2 + i ];
25318 
25319  }
25320 
25321  return this;
25322 
25323  },
25324 
25325  set: function ( value, offset ) {
25326 
25327  if ( offset === undefined ) offset = 0;
25328 
25329  this.array.set( value, offset );
25330 
25331  return this;
25332 
25333  },
25334 
25335  clone: function () {
25336 
25337  return new this.constructor().copy( this );
25338 
25339  },
25340 
25341  onUpload: function ( callback ) {
25342 
25343  this.onUploadCallback = callback;
25344 
25345  return this;
25346 
25347  }
25348 
25349  } );
25350 
25355  function InterleavedBufferAttribute( interleavedBuffer, itemSize, offset, normalized ) {
25356 
25357  this.data = interleavedBuffer;
25358  this.itemSize = itemSize;
25359  this.offset = offset;
25360 
25361  this.normalized = normalized === true;
25362 
25363  }
25364 
25365  Object.defineProperties( InterleavedBufferAttribute.prototype, {
25366 
25367  count: {
25368 
25369  get: function () {
25370 
25371  return this.data.count;
25372 
25373  }
25374 
25375  },
25376 
25377  array: {
25378 
25379  get: function () {
25380 
25381  return this.data.array;
25382 
25383  }
25384 
25385  }
25386 
25387  } );
25388 
25389  Object.assign( InterleavedBufferAttribute.prototype, {
25390 
25391  isInterleavedBufferAttribute: true,
25392 
25393  setX: function ( index, x ) {
25394 
25395  this.data.array[ index * this.data.stride + this.offset ] = x;
25396 
25397  return this;
25398 
25399  },
25400 
25401  setY: function ( index, y ) {
25402 
25403  this.data.array[ index * this.data.stride + this.offset + 1 ] = y;
25404 
25405  return this;
25406 
25407  },
25408 
25409  setZ: function ( index, z ) {
25410 
25411  this.data.array[ index * this.data.stride + this.offset + 2 ] = z;
25412 
25413  return this;
25414 
25415  },
25416 
25417  setW: function ( index, w ) {
25418 
25419  this.data.array[ index * this.data.stride + this.offset + 3 ] = w;
25420 
25421  return this;
25422 
25423  },
25424 
25425  getX: function ( index ) {
25426 
25427  return this.data.array[ index * this.data.stride + this.offset ];
25428 
25429  },
25430 
25431  getY: function ( index ) {
25432 
25433  return this.data.array[ index * this.data.stride + this.offset + 1 ];
25434 
25435  },
25436 
25437  getZ: function ( index ) {
25438 
25439  return this.data.array[ index * this.data.stride + this.offset + 2 ];
25440 
25441  },
25442 
25443  getW: function ( index ) {
25444 
25445  return this.data.array[ index * this.data.stride + this.offset + 3 ];
25446 
25447  },
25448 
25449  setXY: function ( index, x, y ) {
25450 
25451  index = index * this.data.stride + this.offset;
25452 
25453  this.data.array[ index + 0 ] = x;
25454  this.data.array[ index + 1 ] = y;
25455 
25456  return this;
25457 
25458  },
25459 
25460  setXYZ: function ( index, x, y, z ) {
25461 
25462  index = index * this.data.stride + this.offset;
25463 
25464  this.data.array[ index + 0 ] = x;
25465  this.data.array[ index + 1 ] = y;
25466  this.data.array[ index + 2 ] = z;
25467 
25468  return this;
25469 
25470  },
25471 
25472  setXYZW: function ( index, x, y, z, w ) {
25473 
25474  index = index * this.data.stride + this.offset;
25475 
25476  this.data.array[ index + 0 ] = x;
25477  this.data.array[ index + 1 ] = y;
25478  this.data.array[ index + 2 ] = z;
25479  this.data.array[ index + 3 ] = w;
25480 
25481  return this;
25482 
25483  }
25484 
25485  } );
25486 
25498  function SpriteMaterial( parameters ) {
25499 
25500  Material.call( this );
25501 
25502  this.type = 'SpriteMaterial';
25503 
25504  this.color = new Color( 0xffffff );
25505  this.map = null;
25506 
25507  this.rotation = 0;
25508 
25509  this.sizeAttenuation = true;
25510 
25511  this.lights = false;
25512  this.transparent = true;
25513 
25514  this.setValues( parameters );
25515 
25516  }
25517 
25518  SpriteMaterial.prototype = Object.create( Material.prototype );
25519  SpriteMaterial.prototype.constructor = SpriteMaterial;
25520  SpriteMaterial.prototype.isSpriteMaterial = true;
25521 
25522  SpriteMaterial.prototype.copy = function ( source ) {
25523 
25524  Material.prototype.copy.call( this, source );
25525 
25526  this.color.copy( source.color );
25527  this.map = source.map;
25528 
25529  this.rotation = source.rotation;
25530 
25531  this.sizeAttenuation = source.sizeAttenuation;
25532 
25533  return this;
25534 
25535  };
25536 
25542  var geometry;
25543 
25544  function Sprite( material ) {
25545 
25546  Object3D.call( this );
25547 
25548  this.type = 'Sprite';
25549 
25550  if ( geometry === undefined ) {
25551 
25552  geometry = new BufferGeometry();
25553 
25554  var float32Array = new Float32Array( [
25555  - 0.5, - 0.5, 0, 0, 0,
25556  0.5, - 0.5, 0, 1, 0,
25557  0.5, 0.5, 0, 1, 1,
25558  - 0.5, 0.5, 0, 0, 1
25559  ] );
25560 
25561  var interleavedBuffer = new InterleavedBuffer( float32Array, 5 );
25562 
25563  geometry.setIndex( [ 0, 1, 2, 0, 2, 3 ] );
25564  geometry.addAttribute( 'position', new InterleavedBufferAttribute( interleavedBuffer, 3, 0, false ) );
25565  geometry.addAttribute( 'uv', new InterleavedBufferAttribute( interleavedBuffer, 2, 3, false ) );
25566 
25567  }
25568 
25569  this.geometry = geometry;
25570  this.material = ( material !== undefined ) ? material : new SpriteMaterial();
25571 
25572  this.center = new Vector2( 0.5, 0.5 );
25573 
25574  }
25575 
25576  Sprite.prototype = Object.assign( Object.create( Object3D.prototype ), {
25577 
25578  constructor: Sprite,
25579 
25580  isSprite: true,
25581 
25582  raycast: ( function () {
25583 
25584  var intersectPoint = new Vector3();
25585  var worldScale = new Vector3();
25586  var mvPosition = new Vector3();
25587 
25588  var alignedPosition = new Vector2();
25589  var rotatedPosition = new Vector2();
25590  var viewWorldMatrix = new Matrix4();
25591 
25592  var vA = new Vector3();
25593  var vB = new Vector3();
25594  var vC = new Vector3();
25595 
25596  var uvA = new Vector2();
25597  var uvB = new Vector2();
25598  var uvC = new Vector2();
25599 
25600  function transformVertex( vertexPosition, mvPosition, center, scale, sin, cos ) {
25601 
25602  // compute position in camera space
25603  alignedPosition.subVectors( vertexPosition, center ).addScalar( 0.5 ).multiply( scale );
25604 
25605  // to check if rotation is not zero
25606  if ( sin !== undefined ) {
25607 
25608  rotatedPosition.x = ( cos * alignedPosition.x ) - ( sin * alignedPosition.y );
25609  rotatedPosition.y = ( sin * alignedPosition.x ) + ( cos * alignedPosition.y );
25610 
25611  } else {
25612 
25613  rotatedPosition.copy( alignedPosition );
25614 
25615  }
25616 
25617 
25618  vertexPosition.copy( mvPosition );
25619  vertexPosition.x += rotatedPosition.x;
25620  vertexPosition.y += rotatedPosition.y;
25621 
25622  // transform to world space
25623  vertexPosition.applyMatrix4( viewWorldMatrix );
25624 
25625  }
25626 
25627  return function raycast( raycaster, intersects ) {
25628 
25629  worldScale.setFromMatrixScale( this.matrixWorld );
25630  viewWorldMatrix.getInverse( this.modelViewMatrix ).premultiply( this.matrixWorld );
25631  mvPosition.setFromMatrixPosition( this.modelViewMatrix );
25632 
25633  var rotation = this.material.rotation;
25634  var sin, cos;
25635  if ( rotation !== 0 ) {
25636 
25637  cos = Math.cos( rotation );
25638  sin = Math.sin( rotation );
25639 
25640  }
25641 
25642  var center = this.center;
25643 
25644  transformVertex( vA.set( - 0.5, - 0.5, 0 ), mvPosition, center, worldScale, sin, cos );
25645  transformVertex( vB.set( 0.5, - 0.5, 0 ), mvPosition, center, worldScale, sin, cos );
25646  transformVertex( vC.set( 0.5, 0.5, 0 ), mvPosition, center, worldScale, sin, cos );
25647 
25648  uvA.set( 0, 0 );
25649  uvB.set( 1, 0 );
25650  uvC.set( 1, 1 );
25651 
25652  // check first triangle
25653  var intersect = raycaster.ray.intersectTriangle( vA, vB, vC, false, intersectPoint );
25654 
25655  if ( intersect === null ) {
25656 
25657  // check second triangle
25658  transformVertex( vB.set( - 0.5, 0.5, 0 ), mvPosition, center, worldScale, sin, cos );
25659  uvB.set( 0, 1 );
25660 
25661  intersect = raycaster.ray.intersectTriangle( vA, vC, vB, false, intersectPoint );
25662  if ( intersect === null ) {
25663 
25664  return;
25665 
25666  }
25667 
25668  }
25669 
25670  var distance = raycaster.ray.origin.distanceTo( intersectPoint );
25671 
25672  if ( distance < raycaster.near || distance > raycaster.far ) return;
25673 
25674  intersects.push( {
25675 
25676  distance: distance,
25677  point: intersectPoint.clone(),
25678  uv: Triangle.getUV( intersectPoint, vA, vB, vC, uvA, uvB, uvC, new Vector2() ),
25679  face: null,
25680  object: this
25681 
25682  } );
25683 
25684  };
25685 
25686  }() ),
25687 
25688  clone: function () {
25689 
25690  return new this.constructor( this.material ).copy( this );
25691 
25692  },
25693 
25694  copy: function ( source ) {
25695 
25696  Object3D.prototype.copy.call( this, source );
25697 
25698  if ( source.center !== undefined ) this.center.copy( source.center );
25699 
25700  return this;
25701 
25702  }
25703 
25704 
25705  } );
25706 
25713  function LOD() {
25714 
25715  Object3D.call( this );
25716 
25717  this.type = 'LOD';
25718 
25719  Object.defineProperties( this, {
25720  levels: {
25721  enumerable: true,
25722  value: []
25723  }
25724  } );
25725 
25726  }
25727 
25728  LOD.prototype = Object.assign( Object.create( Object3D.prototype ), {
25729 
25730  constructor: LOD,
25731 
25732  copy: function ( source ) {
25733 
25734  Object3D.prototype.copy.call( this, source, false );
25735 
25736  var levels = source.levels;
25737 
25738  for ( var i = 0, l = levels.length; i < l; i ++ ) {
25739 
25740  var level = levels[ i ];
25741 
25742  this.addLevel( level.object.clone(), level.distance );
25743 
25744  }
25745 
25746  return this;
25747 
25748  },
25749 
25750  addLevel: function ( object, distance ) {
25751 
25752  if ( distance === undefined ) distance = 0;
25753 
25754  distance = Math.abs( distance );
25755 
25756  var levels = this.levels;
25757 
25758  for ( var l = 0; l < levels.length; l ++ ) {
25759 
25760  if ( distance < levels[ l ].distance ) {
25761 
25762  break;
25763 
25764  }
25765 
25766  }
25767 
25768  levels.splice( l, 0, { distance: distance, object: object } );
25769 
25770  this.add( object );
25771 
25772  },
25773 
25774  getObjectForDistance: function ( distance ) {
25775 
25776  var levels = this.levels;
25777 
25778  for ( var i = 1, l = levels.length; i < l; i ++ ) {
25779 
25780  if ( distance < levels[ i ].distance ) {
25781 
25782  break;
25783 
25784  }
25785 
25786  }
25787 
25788  return levels[ i - 1 ].object;
25789 
25790  },
25791 
25792  raycast: ( function () {
25793 
25794  var matrixPosition = new Vector3();
25795 
25796  return function raycast( raycaster, intersects ) {
25797 
25798  matrixPosition.setFromMatrixPosition( this.matrixWorld );
25799 
25800  var distance = raycaster.ray.origin.distanceTo( matrixPosition );
25801 
25802  this.getObjectForDistance( distance ).raycast( raycaster, intersects );
25803 
25804  };
25805 
25806  }() ),
25807 
25808  update: function () {
25809 
25810  var v1 = new Vector3();
25811  var v2 = new Vector3();
25812 
25813  return function update( camera ) {
25814 
25815  var levels = this.levels;
25816 
25817  if ( levels.length > 1 ) {
25818 
25819  v1.setFromMatrixPosition( camera.matrixWorld );
25820  v2.setFromMatrixPosition( this.matrixWorld );
25821 
25822  var distance = v1.distanceTo( v2 );
25823 
25824  levels[ 0 ].object.visible = true;
25825 
25826  for ( var i = 1, l = levels.length; i < l; i ++ ) {
25827 
25828  if ( distance >= levels[ i ].distance ) {
25829 
25830  levels[ i - 1 ].object.visible = false;
25831  levels[ i ].object.visible = true;
25832 
25833  } else {
25834 
25835  break;
25836 
25837  }
25838 
25839  }
25840 
25841  for ( ; i < l; i ++ ) {
25842 
25843  levels[ i ].object.visible = false;
25844 
25845  }
25846 
25847  }
25848 
25849  };
25850 
25851  }(),
25852 
25853  toJSON: function ( meta ) {
25854 
25855  var data = Object3D.prototype.toJSON.call( this, meta );
25856 
25857  data.object.levels = [];
25858 
25859  var levels = this.levels;
25860 
25861  for ( var i = 0, l = levels.length; i < l; i ++ ) {
25862 
25863  var level = levels[ i ];
25864 
25865  data.object.levels.push( {
25866  object: level.object.uuid,
25867  distance: level.distance
25868  } );
25869 
25870  }
25871 
25872  return data;
25873 
25874  }
25875 
25876  } );
25877 
25884  function SkinnedMesh( geometry, material ) {
25885 
25886  if ( geometry && geometry.isGeometry ) {
25887 
25888  console.error( 'THREE.SkinnedMesh no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );
25889 
25890  }
25891 
25892  Mesh.call( this, geometry, material );
25893 
25894  this.type = 'SkinnedMesh';
25895 
25896  this.bindMode = 'attached';
25897  this.bindMatrix = new Matrix4();
25898  this.bindMatrixInverse = new Matrix4();
25899 
25900  }
25901 
25902  SkinnedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), {
25903 
25904  constructor: SkinnedMesh,
25905 
25906  isSkinnedMesh: true,
25907 
25908  bind: function ( skeleton, bindMatrix ) {
25909 
25910  this.skeleton = skeleton;
25911 
25912  if ( bindMatrix === undefined ) {
25913 
25914  this.updateMatrixWorld( true );
25915 
25916  this.skeleton.calculateInverses();
25917 
25918  bindMatrix = this.matrixWorld;
25919 
25920  }
25921 
25922  this.bindMatrix.copy( bindMatrix );
25923  this.bindMatrixInverse.getInverse( bindMatrix );
25924 
25925  },
25926 
25927  pose: function () {
25928 
25929  this.skeleton.pose();
25930 
25931  },
25932 
25933  normalizeSkinWeights: function () {
25934 
25935  var vector = new Vector4();
25936 
25937  var skinWeight = this.geometry.attributes.skinWeight;
25938 
25939  for ( var i = 0, l = skinWeight.count; i < l; i ++ ) {
25940 
25941  vector.x = skinWeight.getX( i );
25942  vector.y = skinWeight.getY( i );
25943  vector.z = skinWeight.getZ( i );
25944  vector.w = skinWeight.getW( i );
25945 
25946  var scale = 1.0 / vector.manhattanLength();
25947 
25948  if ( scale !== Infinity ) {
25949 
25950  vector.multiplyScalar( scale );
25951 
25952  } else {
25953 
25954  vector.set( 1, 0, 0, 0 ); // do something reasonable
25955 
25956  }
25957 
25958  skinWeight.setXYZW( i, vector.x, vector.y, vector.z, vector.w );
25959 
25960  }
25961 
25962  },
25963 
25964  updateMatrixWorld: function ( force ) {
25965 
25966  Mesh.prototype.updateMatrixWorld.call( this, force );
25967 
25968  if ( this.bindMode === 'attached' ) {
25969 
25970  this.bindMatrixInverse.getInverse( this.matrixWorld );
25971 
25972  } else if ( this.bindMode === 'detached' ) {
25973 
25974  this.bindMatrixInverse.getInverse( this.bindMatrix );
25975 
25976  } else {
25977 
25978  console.warn( 'THREE.SkinnedMesh: Unrecognized bindMode: ' + this.bindMode );
25979 
25980  }
25981 
25982  },
25983 
25984  clone: function () {
25985 
25986  return new this.constructor( this.geometry, this.material ).copy( this );
25987 
25988  }
25989 
25990  } );
25991 
25999  function Skeleton( bones, boneInverses ) {
26000 
26001  // copy the bone array
26002 
26003  bones = bones || [];
26004 
26005  this.bones = bones.slice( 0 );
26006  this.boneMatrices = new Float32Array( this.bones.length * 16 );
26007 
26008  // use the supplied bone inverses or calculate the inverses
26009 
26010  if ( boneInverses === undefined ) {
26011 
26012  this.calculateInverses();
26013 
26014  } else {
26015 
26016  if ( this.bones.length === boneInverses.length ) {
26017 
26018  this.boneInverses = boneInverses.slice( 0 );
26019 
26020  } else {
26021 
26022  console.warn( 'THREE.Skeleton boneInverses is the wrong length.' );
26023 
26024  this.boneInverses = [];
26025 
26026  for ( var i = 0, il = this.bones.length; i < il; i ++ ) {
26027 
26028  this.boneInverses.push( new Matrix4() );
26029 
26030  }
26031 
26032  }
26033 
26034  }
26035 
26036  }
26037 
26038  Object.assign( Skeleton.prototype, {
26039 
26040  calculateInverses: function () {
26041 
26042  this.boneInverses = [];
26043 
26044  for ( var i = 0, il = this.bones.length; i < il; i ++ ) {
26045 
26046  var inverse = new Matrix4();
26047 
26048  if ( this.bones[ i ] ) {
26049 
26050  inverse.getInverse( this.bones[ i ].matrixWorld );
26051 
26052  }
26053 
26054  this.boneInverses.push( inverse );
26055 
26056  }
26057 
26058  },
26059 
26060  pose: function () {
26061 
26062  var bone, i, il;
26063 
26064  // recover the bind-time world matrices
26065 
26066  for ( i = 0, il = this.bones.length; i < il; i ++ ) {
26067 
26068  bone = this.bones[ i ];
26069 
26070  if ( bone ) {
26071 
26072  bone.matrixWorld.getInverse( this.boneInverses[ i ] );
26073 
26074  }
26075 
26076  }
26077 
26078  // compute the local matrices, positions, rotations and scales
26079 
26080  for ( i = 0, il = this.bones.length; i < il; i ++ ) {
26081 
26082  bone = this.bones[ i ];
26083 
26084  if ( bone ) {
26085 
26086  if ( bone.parent && bone.parent.isBone ) {
26087 
26088  bone.matrix.getInverse( bone.parent.matrixWorld );
26089  bone.matrix.multiply( bone.matrixWorld );
26090 
26091  } else {
26092 
26093  bone.matrix.copy( bone.matrixWorld );
26094 
26095  }
26096 
26097  bone.matrix.decompose( bone.position, bone.quaternion, bone.scale );
26098 
26099  }
26100 
26101  }
26102 
26103  },
26104 
26105  update: ( function () {
26106 
26107  var offsetMatrix = new Matrix4();
26108  var identityMatrix = new Matrix4();
26109 
26110  return function update() {
26111 
26112  var bones = this.bones;
26113  var boneInverses = this.boneInverses;
26114  var boneMatrices = this.boneMatrices;
26115  var boneTexture = this.boneTexture;
26116 
26117  // flatten bone matrices to array
26118 
26119  for ( var i = 0, il = bones.length; i < il; i ++ ) {
26120 
26121  // compute the offset between the current and the original transform
26122 
26123  var matrix = bones[ i ] ? bones[ i ].matrixWorld : identityMatrix;
26124 
26125  offsetMatrix.multiplyMatrices( matrix, boneInverses[ i ] );
26126  offsetMatrix.toArray( boneMatrices, i * 16 );
26127 
26128  }
26129 
26130  if ( boneTexture !== undefined ) {
26131 
26132  boneTexture.needsUpdate = true;
26133 
26134  }
26135 
26136  };
26137 
26138  } )(),
26139 
26140  clone: function () {
26141 
26142  return new Skeleton( this.bones, this.boneInverses );
26143 
26144  },
26145 
26146  getBoneByName: function ( name ) {
26147 
26148  for ( var i = 0, il = this.bones.length; i < il; i ++ ) {
26149 
26150  var bone = this.bones[ i ];
26151 
26152  if ( bone.name === name ) {
26153 
26154  return bone;
26155 
26156  }
26157 
26158  }
26159 
26160  return undefined;
26161 
26162  }
26163 
26164  } );
26165 
26172  function Bone() {
26173 
26174  Object3D.call( this );
26175 
26176  this.type = 'Bone';
26177 
26178  }
26179 
26180  Bone.prototype = Object.assign( Object.create( Object3D.prototype ), {
26181 
26182  constructor: Bone,
26183 
26184  isBone: true
26185 
26186  } );
26187 
26202  function LineBasicMaterial( parameters ) {
26203 
26204  Material.call( this );
26205 
26206  this.type = 'LineBasicMaterial';
26207 
26208  this.color = new Color( 0xffffff );
26209 
26210  this.linewidth = 1;
26211  this.linecap = 'round';
26212  this.linejoin = 'round';
26213 
26214  this.lights = false;
26215 
26216  this.setValues( parameters );
26217 
26218  }
26219 
26220  LineBasicMaterial.prototype = Object.create( Material.prototype );
26221  LineBasicMaterial.prototype.constructor = LineBasicMaterial;
26222 
26223  LineBasicMaterial.prototype.isLineBasicMaterial = true;
26224 
26225  LineBasicMaterial.prototype.copy = function ( source ) {
26226 
26227  Material.prototype.copy.call( this, source );
26228 
26229  this.color.copy( source.color );
26230 
26231  this.linewidth = source.linewidth;
26232  this.linecap = source.linecap;
26233  this.linejoin = source.linejoin;
26234 
26235  return this;
26236 
26237  };
26238 
26243  function Line( geometry, material, mode ) {
26244 
26245  if ( mode === 1 ) {
26246 
26247  console.error( 'THREE.Line: parameter THREE.LinePieces no longer supported. Use THREE.LineSegments instead.' );
26248 
26249  }
26250 
26251  Object3D.call( this );
26252 
26253  this.type = 'Line';
26254 
26255  this.geometry = geometry !== undefined ? geometry : new BufferGeometry();
26256  this.material = material !== undefined ? material : new LineBasicMaterial( { color: Math.random() * 0xffffff } );
26257 
26258  }
26259 
26260  Line.prototype = Object.assign( Object.create( Object3D.prototype ), {
26261 
26262  constructor: Line,
26263 
26264  isLine: true,
26265 
26266  computeLineDistances: ( function () {
26267 
26268  var start = new Vector3();
26269  var end = new Vector3();
26270 
26271  return function computeLineDistances() {
26272 
26273  var geometry = this.geometry;
26274 
26275  if ( geometry.isBufferGeometry ) {
26276 
26277  // we assume non-indexed geometry
26278 
26279  if ( geometry.index === null ) {
26280 
26281  var positionAttribute = geometry.attributes.position;
26282  var lineDistances = [ 0 ];
26283 
26284  for ( var i = 1, l = positionAttribute.count; i < l; i ++ ) {
26285 
26286  start.fromBufferAttribute( positionAttribute, i - 1 );
26287  end.fromBufferAttribute( positionAttribute, i );
26288 
26289  lineDistances[ i ] = lineDistances[ i - 1 ];
26290  lineDistances[ i ] += start.distanceTo( end );
26291 
26292  }
26293 
26294  geometry.addAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );
26295 
26296  } else {
26297 
26298  console.warn( 'THREE.Line.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );
26299 
26300  }
26301 
26302  } else if ( geometry.isGeometry ) {
26303 
26304  var vertices = geometry.vertices;
26305  var lineDistances = geometry.lineDistances;
26306 
26307  lineDistances[ 0 ] = 0;
26308 
26309  for ( var i = 1, l = vertices.length; i < l; i ++ ) {
26310 
26311  lineDistances[ i ] = lineDistances[ i - 1 ];
26312  lineDistances[ i ] += vertices[ i - 1 ].distanceTo( vertices[ i ] );
26313 
26314  }
26315 
26316  }
26317 
26318  return this;
26319 
26320  };
26321 
26322  }() ),
26323 
26324  raycast: ( function () {
26325 
26326  var inverseMatrix = new Matrix4();
26327  var ray = new Ray();
26328  var sphere = new Sphere();
26329 
26330  return function raycast( raycaster, intersects ) {
26331 
26332  var precision = raycaster.linePrecision;
26333 
26334  var geometry = this.geometry;
26335  var matrixWorld = this.matrixWorld;
26336 
26337  // Checking boundingSphere distance to ray
26338 
26339  if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
26340 
26341  sphere.copy( geometry.boundingSphere );
26342  sphere.applyMatrix4( matrixWorld );
26343  sphere.radius += precision;
26344 
26345  if ( raycaster.ray.intersectsSphere( sphere ) === false ) return;
26346 
26347  //
26348 
26349  inverseMatrix.getInverse( matrixWorld );
26350  ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix );
26351 
26352  var localPrecision = precision / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
26353  var localPrecisionSq = localPrecision * localPrecision;
26354 
26355  var vStart = new Vector3();
26356  var vEnd = new Vector3();
26357  var interSegment = new Vector3();
26358  var interRay = new Vector3();
26359  var step = ( this && this.isLineSegments ) ? 2 : 1;
26360 
26361  if ( geometry.isBufferGeometry ) {
26362 
26363  var index = geometry.index;
26364  var attributes = geometry.attributes;
26365  var positions = attributes.position.array;
26366 
26367  if ( index !== null ) {
26368 
26369  var indices = index.array;
26370 
26371  for ( var i = 0, l = indices.length - 1; i < l; i += step ) {
26372 
26373  var a = indices[ i ];
26374  var b = indices[ i + 1 ];
26375 
26376  vStart.fromArray( positions, a * 3 );
26377  vEnd.fromArray( positions, b * 3 );
26378 
26379  var distSq = ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
26380 
26381  if ( distSq > localPrecisionSq ) continue;
26382 
26383  interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
26384 
26385  var distance = raycaster.ray.origin.distanceTo( interRay );
26386 
26387  if ( distance < raycaster.near || distance > raycaster.far ) continue;
26388 
26389  intersects.push( {
26390 
26391  distance: distance,
26392  // What do we want? intersection point on the ray or on the segment??
26393  // point: raycaster.ray.at( distance ),
26394  point: interSegment.clone().applyMatrix4( this.matrixWorld ),
26395  index: i,
26396  face: null,
26397  faceIndex: null,
26398  object: this
26399 
26400  } );
26401 
26402  }
26403 
26404  } else {
26405 
26406  for ( var i = 0, l = positions.length / 3 - 1; i < l; i += step ) {
26407 
26408  vStart.fromArray( positions, 3 * i );
26409  vEnd.fromArray( positions, 3 * i + 3 );
26410 
26411  var distSq = ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
26412 
26413  if ( distSq > localPrecisionSq ) continue;
26414 
26415  interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
26416 
26417  var distance = raycaster.ray.origin.distanceTo( interRay );
26418 
26419  if ( distance < raycaster.near || distance > raycaster.far ) continue;
26420 
26421  intersects.push( {
26422 
26423  distance: distance,
26424  // What do we want? intersection point on the ray or on the segment??
26425  // point: raycaster.ray.at( distance ),
26426  point: interSegment.clone().applyMatrix4( this.matrixWorld ),
26427  index: i,
26428  face: null,
26429  faceIndex: null,
26430  object: this
26431 
26432  } );
26433 
26434  }
26435 
26436  }
26437 
26438  } else if ( geometry.isGeometry ) {
26439 
26440  var vertices = geometry.vertices;
26441  var nbVertices = vertices.length;
26442 
26443  for ( var i = 0; i < nbVertices - 1; i += step ) {
26444 
26445  var distSq = ray.distanceSqToSegment( vertices[ i ], vertices[ i + 1 ], interRay, interSegment );
26446 
26447  if ( distSq > localPrecisionSq ) continue;
26448 
26449  interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
26450 
26451  var distance = raycaster.ray.origin.distanceTo( interRay );
26452 
26453  if ( distance < raycaster.near || distance > raycaster.far ) continue;
26454 
26455  intersects.push( {
26456 
26457  distance: distance,
26458  // What do we want? intersection point on the ray or on the segment??
26459  // point: raycaster.ray.at( distance ),
26460  point: interSegment.clone().applyMatrix4( this.matrixWorld ),
26461  index: i,
26462  face: null,
26463  faceIndex: null,
26464  object: this
26465 
26466  } );
26467 
26468  }
26469 
26470  }
26471 
26472  };
26473 
26474  }() ),
26475 
26476  copy: function ( source ) {
26477 
26478  Object3D.prototype.copy.call( this, source );
26479 
26480  this.geometry.copy( source.geometry );
26481  this.material.copy( source.material );
26482 
26483  return this;
26484 
26485  },
26486 
26487  clone: function () {
26488 
26489  return new this.constructor().copy( this );
26490 
26491  }
26492 
26493  } );
26494 
26499  function LineSegments( geometry, material ) {
26500 
26501  Line.call( this, geometry, material );
26502 
26503  this.type = 'LineSegments';
26504 
26505  }
26506 
26507  LineSegments.prototype = Object.assign( Object.create( Line.prototype ), {
26508 
26509  constructor: LineSegments,
26510 
26511  isLineSegments: true,
26512 
26513  computeLineDistances: ( function () {
26514 
26515  var start = new Vector3();
26516  var end = new Vector3();
26517 
26518  return function computeLineDistances() {
26519 
26520  var geometry = this.geometry;
26521 
26522  if ( geometry.isBufferGeometry ) {
26523 
26524  // we assume non-indexed geometry
26525 
26526  if ( geometry.index === null ) {
26527 
26528  var positionAttribute = geometry.attributes.position;
26529  var lineDistances = [];
26530 
26531  for ( var i = 0, l = positionAttribute.count; i < l; i += 2 ) {
26532 
26533  start.fromBufferAttribute( positionAttribute, i );
26534  end.fromBufferAttribute( positionAttribute, i + 1 );
26535 
26536  lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ];
26537  lineDistances[ i + 1 ] = lineDistances[ i ] + start.distanceTo( end );
26538 
26539  }
26540 
26541  geometry.addAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );
26542 
26543  } else {
26544 
26545  console.warn( 'THREE.LineSegments.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );
26546 
26547  }
26548 
26549  } else if ( geometry.isGeometry ) {
26550 
26551  var vertices = geometry.vertices;
26552  var lineDistances = geometry.lineDistances;
26553 
26554  for ( var i = 0, l = vertices.length; i < l; i += 2 ) {
26555 
26556  start.copy( vertices[ i ] );
26557  end.copy( vertices[ i + 1 ] );
26558 
26559  lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ];
26560  lineDistances[ i + 1 ] = lineDistances[ i ] + start.distanceTo( end );
26561 
26562  }
26563 
26564  }
26565 
26566  return this;
26567 
26568  };
26569 
26570  }() )
26571 
26572  } );
26573 
26578  function LineLoop( geometry, material ) {
26579 
26580  Line.call( this, geometry, material );
26581 
26582  this.type = 'LineLoop';
26583 
26584  }
26585 
26586  LineLoop.prototype = Object.assign( Object.create( Line.prototype ), {
26587 
26588  constructor: LineLoop,
26589 
26590  isLineLoop: true,
26591 
26592  } );
26593 
26610  function PointsMaterial( parameters ) {
26611 
26612  Material.call( this );
26613 
26614  this.type = 'PointsMaterial';
26615 
26616  this.color = new Color( 0xffffff );
26617 
26618  this.map = null;
26619 
26620  this.size = 1;
26621  this.sizeAttenuation = true;
26622 
26623  this.morphTargets = false;
26624 
26625  this.lights = false;
26626 
26627  this.setValues( parameters );
26628 
26629  }
26630 
26631  PointsMaterial.prototype = Object.create( Material.prototype );
26632  PointsMaterial.prototype.constructor = PointsMaterial;
26633 
26634  PointsMaterial.prototype.isPointsMaterial = true;
26635 
26636  PointsMaterial.prototype.copy = function ( source ) {
26637 
26638  Material.prototype.copy.call( this, source );
26639 
26640  this.color.copy( source.color );
26641 
26642  this.map = source.map;
26643 
26644  this.size = source.size;
26645  this.sizeAttenuation = source.sizeAttenuation;
26646 
26647  this.morphTargets = source.morphTargets;
26648 
26649  return this;
26650 
26651  };
26652 
26657  function Points( geometry, material ) {
26658 
26659  Object3D.call( this );
26660 
26661  this.type = 'Points';
26662 
26663  this.geometry = geometry !== undefined ? geometry : new BufferGeometry();
26664  this.material = material !== undefined ? material : new PointsMaterial( { color: Math.random() * 0xffffff } );
26665 
26666  }
26667 
26668  Points.prototype = Object.assign( Object.create( Object3D.prototype ), {
26669 
26670  constructor: Points,
26671 
26672  isPoints: true,
26673 
26674  raycast: ( function () {
26675 
26676  var inverseMatrix = new Matrix4();
26677  var ray = new Ray();
26678  var sphere = new Sphere();
26679 
26680  return function raycast( raycaster, intersects ) {
26681 
26682  var object = this;
26683  var geometry = this.geometry;
26684  var matrixWorld = this.matrixWorld;
26685  var threshold = raycaster.params.Points.threshold;
26686 
26687  // Checking boundingSphere distance to ray
26688 
26689  if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
26690 
26691  sphere.copy( geometry.boundingSphere );
26692  sphere.applyMatrix4( matrixWorld );
26693  sphere.radius += threshold;
26694 
26695  if ( raycaster.ray.intersectsSphere( sphere ) === false ) return;
26696 
26697  //
26698 
26699  inverseMatrix.getInverse( matrixWorld );
26700  ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix );
26701 
26702  var localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
26703  var localThresholdSq = localThreshold * localThreshold;
26704  var position = new Vector3();
26705  var intersectPoint = new Vector3();
26706 
26707  function testPoint( point, index ) {
26708 
26709  var rayPointDistanceSq = ray.distanceSqToPoint( point );
26710 
26711  if ( rayPointDistanceSq < localThresholdSq ) {
26712 
26713  ray.closestPointToPoint( point, intersectPoint );
26714  intersectPoint.applyMatrix4( matrixWorld );
26715 
26716  var distance = raycaster.ray.origin.distanceTo( intersectPoint );
26717 
26718  if ( distance < raycaster.near || distance > raycaster.far ) return;
26719 
26720  intersects.push( {
26721 
26722  distance: distance,
26723  distanceToRay: Math.sqrt( rayPointDistanceSq ),
26724  point: intersectPoint.clone(),
26725  index: index,
26726  face: null,
26727  object: object
26728 
26729  } );
26730 
26731  }
26732 
26733  }
26734 
26735  if ( geometry.isBufferGeometry ) {
26736 
26737  var index = geometry.index;
26738  var attributes = geometry.attributes;
26739  var positions = attributes.position.array;
26740 
26741  if ( index !== null ) {
26742 
26743  var indices = index.array;
26744 
26745  for ( var i = 0, il = indices.length; i < il; i ++ ) {
26746 
26747  var a = indices[ i ];
26748 
26749  position.fromArray( positions, a * 3 );
26750 
26751  testPoint( position, a );
26752 
26753  }
26754 
26755  } else {
26756 
26757  for ( var i = 0, l = positions.length / 3; i < l; i ++ ) {
26758 
26759  position.fromArray( positions, i * 3 );
26760 
26761  testPoint( position, i );
26762 
26763  }
26764 
26765  }
26766 
26767  } else {
26768 
26769  var vertices = geometry.vertices;
26770 
26771  for ( var i = 0, l = vertices.length; i < l; i ++ ) {
26772 
26773  testPoint( vertices[ i ], i );
26774 
26775  }
26776 
26777  }
26778 
26779  };
26780 
26781  }() ),
26782 
26783  clone: function () {
26784 
26785  return new this.constructor( this.geometry, this.material ).copy( this );
26786 
26787  }
26788 
26789  } );
26790 
26795  function VideoTexture( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
26796 
26797  Texture.call( this, video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
26798 
26799  this.format = format !== undefined ? format : RGBFormat;
26800 
26801  this.minFilter = minFilter !== undefined ? minFilter : LinearFilter;
26802  this.magFilter = magFilter !== undefined ? magFilter : LinearFilter;
26803 
26804  this.generateMipmaps = false;
26805 
26806  }
26807 
26808  VideoTexture.prototype = Object.assign( Object.create( Texture.prototype ), {
26809 
26810  constructor: VideoTexture,
26811 
26812  isVideoTexture: true,
26813 
26814  update: function () {
26815 
26816  var video = this.image;
26817 
26818  if ( video.readyState >= video.HAVE_CURRENT_DATA ) {
26819 
26820  this.needsUpdate = true;
26821 
26822  }
26823 
26824  }
26825 
26826  } );
26827 
26832  function CompressedTexture( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) {
26833 
26834  Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
26835 
26836  this.image = { width: width, height: height };
26837  this.mipmaps = mipmaps;
26838 
26839  // no flipping for cube textures
26840  // (also flipping doesn't work for compressed textures )
26841 
26842  this.flipY = false;
26843 
26844  // can't generate mipmaps for compressed textures
26845  // mips must be embedded in DDS files
26846 
26847  this.generateMipmaps = false;
26848 
26849  }
26850 
26851  CompressedTexture.prototype = Object.create( Texture.prototype );
26852  CompressedTexture.prototype.constructor = CompressedTexture;
26853 
26854  CompressedTexture.prototype.isCompressedTexture = true;
26855 
26860  function CanvasTexture( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
26861 
26862  Texture.call( this, canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
26863 
26864  this.needsUpdate = true;
26865 
26866  }
26867 
26868  CanvasTexture.prototype = Object.create( Texture.prototype );
26869  CanvasTexture.prototype.constructor = CanvasTexture;
26870  CanvasTexture.prototype.isCanvasTexture = true;
26871 
26877  function DepthTexture( width, height, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format ) {
26878 
26879  format = format !== undefined ? format : DepthFormat;
26880 
26881  if ( format !== DepthFormat && format !== DepthStencilFormat ) {
26882 
26883  throw new Error( 'DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat' );
26884 
26885  }
26886 
26887  if ( type === undefined && format === DepthFormat ) type = UnsignedShortType;
26888  if ( type === undefined && format === DepthStencilFormat ) type = UnsignedInt248Type;
26889 
26890  Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
26891 
26892  this.image = { width: width, height: height };
26893 
26894  this.magFilter = magFilter !== undefined ? magFilter : NearestFilter;
26895  this.minFilter = minFilter !== undefined ? minFilter : NearestFilter;
26896 
26897  this.flipY = false;
26898  this.generateMipmaps = false;
26899 
26900  }
26901 
26902  DepthTexture.prototype = Object.create( Texture.prototype );
26903  DepthTexture.prototype.constructor = DepthTexture;
26904  DepthTexture.prototype.isDepthTexture = true;
26905 
26911  function WireframeGeometry( geometry ) {
26912 
26913  BufferGeometry.call( this );
26914 
26915  this.type = 'WireframeGeometry';
26916 
26917  // buffer
26918 
26919  var vertices = [];
26920 
26921  // helper variables
26922 
26923  var i, j, l, o, ol;
26924  var edge = [ 0, 0 ], edges = {}, e, edge1, edge2;
26925  var key, keys = [ 'a', 'b', 'c' ];
26926  var vertex;
26927 
26928  // different logic for Geometry and BufferGeometry
26929 
26930  if ( geometry && geometry.isGeometry ) {
26931 
26932  // create a data structure that contains all edges without duplicates
26933 
26934  var faces = geometry.faces;
26935 
26936  for ( i = 0, l = faces.length; i < l; i ++ ) {
26937 
26938  var face = faces[ i ];
26939 
26940  for ( j = 0; j < 3; j ++ ) {
26941 
26942  edge1 = face[ keys[ j ] ];
26943  edge2 = face[ keys[ ( j + 1 ) % 3 ] ];
26944  edge[ 0 ] = Math.min( edge1, edge2 ); // sorting prevents duplicates
26945  edge[ 1 ] = Math.max( edge1, edge2 );
26946 
26947  key = edge[ 0 ] + ',' + edge[ 1 ];
26948 
26949  if ( edges[ key ] === undefined ) {
26950 
26951  edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ] };
26952 
26953  }
26954 
26955  }
26956 
26957  }
26958 
26959  // generate vertices
26960 
26961  for ( key in edges ) {
26962 
26963  e = edges[ key ];
26964 
26965  vertex = geometry.vertices[ e.index1 ];
26966  vertices.push( vertex.x, vertex.y, vertex.z );
26967 
26968  vertex = geometry.vertices[ e.index2 ];
26969  vertices.push( vertex.x, vertex.y, vertex.z );
26970 
26971  }
26972 
26973  } else if ( geometry && geometry.isBufferGeometry ) {
26974 
26975  var position, indices, groups;
26976  var group, start, count;
26977  var index1, index2;
26978 
26979  vertex = new Vector3();
26980 
26981  if ( geometry.index !== null ) {
26982 
26983  // indexed BufferGeometry
26984 
26985  position = geometry.attributes.position;
26986  indices = geometry.index;
26987  groups = geometry.groups;
26988 
26989  if ( groups.length === 0 ) {
26990 
26991  groups = [ { start: 0, count: indices.count, materialIndex: 0 } ];
26992 
26993  }
26994 
26995  // create a data structure that contains all eges without duplicates
26996 
26997  for ( o = 0, ol = groups.length; o < ol; ++ o ) {
26998 
26999  group = groups[ o ];
27000 
27001  start = group.start;
27002  count = group.count;
27003 
27004  for ( i = start, l = ( start + count ); i < l; i += 3 ) {
27005 
27006  for ( j = 0; j < 3; j ++ ) {
27007 
27008  edge1 = indices.getX( i + j );
27009  edge2 = indices.getX( i + ( j + 1 ) % 3 );
27010  edge[ 0 ] = Math.min( edge1, edge2 ); // sorting prevents duplicates
27011  edge[ 1 ] = Math.max( edge1, edge2 );
27012 
27013  key = edge[ 0 ] + ',' + edge[ 1 ];
27014 
27015  if ( edges[ key ] === undefined ) {
27016 
27017  edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ] };
27018 
27019  }
27020 
27021  }
27022 
27023  }
27024 
27025  }
27026 
27027  // generate vertices
27028 
27029  for ( key in edges ) {
27030 
27031  e = edges[ key ];
27032 
27033  vertex.fromBufferAttribute( position, e.index1 );
27034  vertices.push( vertex.x, vertex.y, vertex.z );
27035 
27036  vertex.fromBufferAttribute( position, e.index2 );
27037  vertices.push( vertex.x, vertex.y, vertex.z );
27038 
27039  }
27040 
27041  } else {
27042 
27043  // non-indexed BufferGeometry
27044 
27045  position = geometry.attributes.position;
27046 
27047  for ( i = 0, l = ( position.count / 3 ); i < l; i ++ ) {
27048 
27049  for ( j = 0; j < 3; j ++ ) {
27050 
27051  // three edges per triangle, an edge is represented as (index1, index2)
27052  // e.g. the first triangle has the following edges: (0,1),(1,2),(2,0)
27053 
27054  index1 = 3 * i + j;
27055  vertex.fromBufferAttribute( position, index1 );
27056  vertices.push( vertex.x, vertex.y, vertex.z );
27057 
27058  index2 = 3 * i + ( ( j + 1 ) % 3 );
27059  vertex.fromBufferAttribute( position, index2 );
27060  vertices.push( vertex.x, vertex.y, vertex.z );
27061 
27062  }
27063 
27064  }
27065 
27066  }
27067 
27068  }
27069 
27070  // build geometry
27071 
27072  this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
27073 
27074  }
27075 
27076  WireframeGeometry.prototype = Object.create( BufferGeometry.prototype );
27077  WireframeGeometry.prototype.constructor = WireframeGeometry;
27078 
27087  // ParametricGeometry
27088 
27089  function ParametricGeometry( func, slices, stacks ) {
27090 
27091  Geometry.call( this );
27092 
27093  this.type = 'ParametricGeometry';
27094 
27095  this.parameters = {
27096  func: func,
27097  slices: slices,
27098  stacks: stacks
27099  };
27100 
27101  this.fromBufferGeometry( new ParametricBufferGeometry( func, slices, stacks ) );
27102  this.mergeVertices();
27103 
27104  }
27105 
27106  ParametricGeometry.prototype = Object.create( Geometry.prototype );
27107  ParametricGeometry.prototype.constructor = ParametricGeometry;
27108 
27109  // ParametricBufferGeometry
27110 
27111  function ParametricBufferGeometry( func, slices, stacks ) {
27112 
27113  BufferGeometry.call( this );
27114 
27115  this.type = 'ParametricBufferGeometry';
27116 
27117  this.parameters = {
27118  func: func,
27119  slices: slices,
27120  stacks: stacks
27121  };
27122 
27123  // buffers
27124 
27125  var indices = [];
27126  var vertices = [];
27127  var normals = [];
27128  var uvs = [];
27129 
27130  var EPS = 0.00001;
27131 
27132  var normal = new Vector3();
27133 
27134  var p0 = new Vector3(), p1 = new Vector3();
27135  var pu = new Vector3(), pv = new Vector3();
27136 
27137  var i, j;
27138 
27139  if ( func.length < 3 ) {
27140 
27141  console.error( 'THREE.ParametricGeometry: Function must now modify a Vector3 as third parameter.' );
27142 
27143  }
27144 
27145  // generate vertices, normals and uvs
27146 
27147  var sliceCount = slices + 1;
27148 
27149  for ( i = 0; i <= stacks; i ++ ) {
27150 
27151  var v = i / stacks;
27152 
27153  for ( j = 0; j <= slices; j ++ ) {
27154 
27155  var u = j / slices;
27156 
27157  // vertex
27158 
27159  func( u, v, p0 );
27160  vertices.push( p0.x, p0.y, p0.z );
27161 
27162  // normal
27163 
27164  // approximate tangent vectors via finite differences
27165 
27166  if ( u - EPS >= 0 ) {
27167 
27168  func( u - EPS, v, p1 );
27169  pu.subVectors( p0, p1 );
27170 
27171  } else {
27172 
27173  func( u + EPS, v, p1 );
27174  pu.subVectors( p1, p0 );
27175 
27176  }
27177 
27178  if ( v - EPS >= 0 ) {
27179 
27180  func( u, v - EPS, p1 );
27181  pv.subVectors( p0, p1 );
27182 
27183  } else {
27184 
27185  func( u, v + EPS, p1 );
27186  pv.subVectors( p1, p0 );
27187 
27188  }
27189 
27190  // cross product of tangent vectors returns surface normal
27191 
27192  normal.crossVectors( pu, pv ).normalize();
27193  normals.push( normal.x, normal.y, normal.z );
27194 
27195  // uv
27196 
27197  uvs.push( u, v );
27198 
27199  }
27200 
27201  }
27202 
27203  // generate indices
27204 
27205  for ( i = 0; i < stacks; i ++ ) {
27206 
27207  for ( j = 0; j < slices; j ++ ) {
27208 
27209  var a = i * sliceCount + j;
27210  var b = i * sliceCount + j + 1;
27211  var c = ( i + 1 ) * sliceCount + j + 1;
27212  var d = ( i + 1 ) * sliceCount + j;
27213 
27214  // faces one and two
27215 
27216  indices.push( a, b, d );
27217  indices.push( b, c, d );
27218 
27219  }
27220 
27221  }
27222 
27223  // build geometry
27224 
27225  this.setIndex( indices );
27226  this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
27227  this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
27228  this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
27229 
27230  }
27231 
27232  ParametricBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
27233  ParametricBufferGeometry.prototype.constructor = ParametricBufferGeometry;
27234 
27242  // PolyhedronGeometry
27243 
27244  function PolyhedronGeometry( vertices, indices, radius, detail ) {
27245 
27246  Geometry.call( this );
27247 
27248  this.type = 'PolyhedronGeometry';
27249 
27250  this.parameters = {
27251  vertices: vertices,
27252  indices: indices,
27253  radius: radius,
27254  detail: detail
27255  };
27256 
27257  this.fromBufferGeometry( new PolyhedronBufferGeometry( vertices, indices, radius, detail ) );
27258  this.mergeVertices();
27259 
27260  }
27261 
27262  PolyhedronGeometry.prototype = Object.create( Geometry.prototype );
27263  PolyhedronGeometry.prototype.constructor = PolyhedronGeometry;
27264 
27265  // PolyhedronBufferGeometry
27266 
27267  function PolyhedronBufferGeometry( vertices, indices, radius, detail ) {
27268 
27269  BufferGeometry.call( this );
27270 
27271  this.type = 'PolyhedronBufferGeometry';
27272 
27273  this.parameters = {
27274  vertices: vertices,
27275  indices: indices,
27276  radius: radius,
27277  detail: detail
27278  };
27279 
27280  radius = radius || 1;
27281  detail = detail || 0;
27282 
27283  // default buffer data
27284 
27285  var vertexBuffer = [];
27286  var uvBuffer = [];
27287 
27288  // the subdivision creates the vertex buffer data
27289 
27290  subdivide( detail );
27291 
27292  // all vertices should lie on a conceptual sphere with a given radius
27293 
27294  appplyRadius( radius );
27295 
27296  // finally, create the uv data
27297 
27298  generateUVs();
27299 
27300  // build non-indexed geometry
27301 
27302  this.addAttribute( 'position', new Float32BufferAttribute( vertexBuffer, 3 ) );
27303  this.addAttribute( 'normal', new Float32BufferAttribute( vertexBuffer.slice(), 3 ) );
27304  this.addAttribute( 'uv', new Float32BufferAttribute( uvBuffer, 2 ) );
27305 
27306  if ( detail === 0 ) {
27307 
27308  this.computeVertexNormals(); // flat normals
27309 
27310  } else {
27311 
27312  this.normalizeNormals(); // smooth normals
27313 
27314  }
27315 
27316  // helper functions
27317 
27318  function subdivide( detail ) {
27319 
27320  var a = new Vector3();
27321  var b = new Vector3();
27322  var c = new Vector3();
27323 
27324  // iterate over all faces and apply a subdivison with the given detail value
27325 
27326  for ( var i = 0; i < indices.length; i += 3 ) {
27327 
27328  // get the vertices of the face
27329 
27330  getVertexByIndex( indices[ i + 0 ], a );
27331  getVertexByIndex( indices[ i + 1 ], b );
27332  getVertexByIndex( indices[ i + 2 ], c );
27333 
27334  // perform subdivision
27335 
27336  subdivideFace( a, b, c, detail );
27337 
27338  }
27339 
27340  }
27341 
27342  function subdivideFace( a, b, c, detail ) {
27343 
27344  var cols = Math.pow( 2, detail );
27345 
27346  // we use this multidimensional array as a data structure for creating the subdivision
27347 
27348  var v = [];
27349 
27350  var i, j;
27351 
27352  // construct all of the vertices for this subdivision
27353 
27354  for ( i = 0; i <= cols; i ++ ) {
27355 
27356  v[ i ] = [];
27357 
27358  var aj = a.clone().lerp( c, i / cols );
27359  var bj = b.clone().lerp( c, i / cols );
27360 
27361  var rows = cols - i;
27362 
27363  for ( j = 0; j <= rows; j ++ ) {
27364 
27365  if ( j === 0 && i === cols ) {
27366 
27367  v[ i ][ j ] = aj;
27368 
27369  } else {
27370 
27371  v[ i ][ j ] = aj.clone().lerp( bj, j / rows );
27372 
27373  }
27374 
27375  }
27376 
27377  }
27378 
27379  // construct all of the faces
27380 
27381  for ( i = 0; i < cols; i ++ ) {
27382 
27383  for ( j = 0; j < 2 * ( cols - i ) - 1; j ++ ) {
27384 
27385  var k = Math.floor( j / 2 );
27386 
27387  if ( j % 2 === 0 ) {
27388 
27389  pushVertex( v[ i ][ k + 1 ] );
27390  pushVertex( v[ i + 1 ][ k ] );
27391  pushVertex( v[ i ][ k ] );
27392 
27393  } else {
27394 
27395  pushVertex( v[ i ][ k + 1 ] );
27396  pushVertex( v[ i + 1 ][ k + 1 ] );
27397  pushVertex( v[ i + 1 ][ k ] );
27398 
27399  }
27400 
27401  }
27402 
27403  }
27404 
27405  }
27406 
27407  function appplyRadius( radius ) {
27408 
27409  var vertex = new Vector3();
27410 
27411  // iterate over the entire buffer and apply the radius to each vertex
27412 
27413  for ( var i = 0; i < vertexBuffer.length; i += 3 ) {
27414 
27415  vertex.x = vertexBuffer[ i + 0 ];
27416  vertex.y = vertexBuffer[ i + 1 ];
27417  vertex.z = vertexBuffer[ i + 2 ];
27418 
27419  vertex.normalize().multiplyScalar( radius );
27420 
27421  vertexBuffer[ i + 0 ] = vertex.x;
27422  vertexBuffer[ i + 1 ] = vertex.y;
27423  vertexBuffer[ i + 2 ] = vertex.z;
27424 
27425  }
27426 
27427  }
27428 
27429  function generateUVs() {
27430 
27431  var vertex = new Vector3();
27432 
27433  for ( var i = 0; i < vertexBuffer.length; i += 3 ) {
27434 
27435  vertex.x = vertexBuffer[ i + 0 ];
27436  vertex.y = vertexBuffer[ i + 1 ];
27437  vertex.z = vertexBuffer[ i + 2 ];
27438 
27439  var u = azimuth( vertex ) / 2 / Math.PI + 0.5;
27440  var v = inclination( vertex ) / Math.PI + 0.5;
27441  uvBuffer.push( u, 1 - v );
27442 
27443  }
27444 
27445  correctUVs();
27446 
27447  correctSeam();
27448 
27449  }
27450 
27451  function correctSeam() {
27452 
27453  // handle case when face straddles the seam, see #3269
27454 
27455  for ( var i = 0; i < uvBuffer.length; i += 6 ) {
27456 
27457  // uv data of a single face
27458 
27459  var x0 = uvBuffer[ i + 0 ];
27460  var x1 = uvBuffer[ i + 2 ];
27461  var x2 = uvBuffer[ i + 4 ];
27462 
27463  var max = Math.max( x0, x1, x2 );
27464  var min = Math.min( x0, x1, x2 );
27465 
27466  // 0.9 is somewhat arbitrary
27467 
27468  if ( max > 0.9 && min < 0.1 ) {
27469 
27470  if ( x0 < 0.2 ) uvBuffer[ i + 0 ] += 1;
27471  if ( x1 < 0.2 ) uvBuffer[ i + 2 ] += 1;
27472  if ( x2 < 0.2 ) uvBuffer[ i + 4 ] += 1;
27473 
27474  }
27475 
27476  }
27477 
27478  }
27479 
27480  function pushVertex( vertex ) {
27481 
27482  vertexBuffer.push( vertex.x, vertex.y, vertex.z );
27483 
27484  }
27485 
27486  function getVertexByIndex( index, vertex ) {
27487 
27488  var stride = index * 3;
27489 
27490  vertex.x = vertices[ stride + 0 ];
27491  vertex.y = vertices[ stride + 1 ];
27492  vertex.z = vertices[ stride + 2 ];
27493 
27494  }
27495 
27496  function correctUVs() {
27497 
27498  var a = new Vector3();
27499  var b = new Vector3();
27500  var c = new Vector3();
27501 
27502  var centroid = new Vector3();
27503 
27504  var uvA = new Vector2();
27505  var uvB = new Vector2();
27506  var uvC = new Vector2();
27507 
27508  for ( var i = 0, j = 0; i < vertexBuffer.length; i += 9, j += 6 ) {
27509 
27510  a.set( vertexBuffer[ i + 0 ], vertexBuffer[ i + 1 ], vertexBuffer[ i + 2 ] );
27511  b.set( vertexBuffer[ i + 3 ], vertexBuffer[ i + 4 ], vertexBuffer[ i + 5 ] );
27512  c.set( vertexBuffer[ i + 6 ], vertexBuffer[ i + 7 ], vertexBuffer[ i + 8 ] );
27513 
27514  uvA.set( uvBuffer[ j + 0 ], uvBuffer[ j + 1 ] );
27515  uvB.set( uvBuffer[ j + 2 ], uvBuffer[ j + 3 ] );
27516  uvC.set( uvBuffer[ j + 4 ], uvBuffer[ j + 5 ] );
27517 
27518  centroid.copy( a ).add( b ).add( c ).divideScalar( 3 );
27519 
27520  var azi = azimuth( centroid );
27521 
27522  correctUV( uvA, j + 0, a, azi );
27523  correctUV( uvB, j + 2, b, azi );
27524  correctUV( uvC, j + 4, c, azi );
27525 
27526  }
27527 
27528  }
27529 
27530  function correctUV( uv, stride, vector, azimuth ) {
27531 
27532  if ( ( azimuth < 0 ) && ( uv.x === 1 ) ) {
27533 
27534  uvBuffer[ stride ] = uv.x - 1;
27535 
27536  }
27537 
27538  if ( ( vector.x === 0 ) && ( vector.z === 0 ) ) {
27539 
27540  uvBuffer[ stride ] = azimuth / 2 / Math.PI + 0.5;
27541 
27542  }
27543 
27544  }
27545 
27546  // Angle around the Y axis, counter-clockwise when looking from above.
27547 
27548  function azimuth( vector ) {
27549 
27550  return Math.atan2( vector.z, - vector.x );
27551 
27552  }
27553 
27554 
27555  // Angle above the XZ plane.
27556 
27557  function inclination( vector ) {
27558 
27559  return Math.atan2( - vector.y, Math.sqrt( ( vector.x * vector.x ) + ( vector.z * vector.z ) ) );
27560 
27561  }
27562 
27563  }
27564 
27565  PolyhedronBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
27566  PolyhedronBufferGeometry.prototype.constructor = PolyhedronBufferGeometry;
27567 
27573  // TetrahedronGeometry
27574 
27575  function TetrahedronGeometry( radius, detail ) {
27576 
27577  Geometry.call( this );
27578 
27579  this.type = 'TetrahedronGeometry';
27580 
27581  this.parameters = {
27582  radius: radius,
27583  detail: detail
27584  };
27585 
27586  this.fromBufferGeometry( new TetrahedronBufferGeometry( radius, detail ) );
27587  this.mergeVertices();
27588 
27589  }
27590 
27591  TetrahedronGeometry.prototype = Object.create( Geometry.prototype );
27592  TetrahedronGeometry.prototype.constructor = TetrahedronGeometry;
27593 
27594  // TetrahedronBufferGeometry
27595 
27596  function TetrahedronBufferGeometry( radius, detail ) {
27597 
27598  var vertices = [
27599  1, 1, 1, - 1, - 1, 1, - 1, 1, - 1, 1, - 1, - 1
27600  ];
27601 
27602  var indices = [
27603  2, 1, 0, 0, 3, 2, 1, 3, 0, 2, 3, 1
27604  ];
27605 
27606  PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail );
27607 
27608  this.type = 'TetrahedronBufferGeometry';
27609 
27610  this.parameters = {
27611  radius: radius,
27612  detail: detail
27613  };
27614 
27615  }
27616 
27617  TetrahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype );
27618  TetrahedronBufferGeometry.prototype.constructor = TetrahedronBufferGeometry;
27619 
27625  // OctahedronGeometry
27626 
27627  function OctahedronGeometry( radius, detail ) {
27628 
27629  Geometry.call( this );
27630 
27631  this.type = 'OctahedronGeometry';
27632 
27633  this.parameters = {
27634  radius: radius,
27635  detail: detail
27636  };
27637 
27638  this.fromBufferGeometry( new OctahedronBufferGeometry( radius, detail ) );
27639  this.mergeVertices();
27640 
27641  }
27642 
27643  OctahedronGeometry.prototype = Object.create( Geometry.prototype );
27644  OctahedronGeometry.prototype.constructor = OctahedronGeometry;
27645 
27646  // OctahedronBufferGeometry
27647 
27648  function OctahedronBufferGeometry( radius, detail ) {
27649 
27650  var vertices = [
27651  1, 0, 0, - 1, 0, 0, 0, 1, 0,
27652  0, - 1, 0, 0, 0, 1, 0, 0, - 1
27653  ];
27654 
27655  var indices = [
27656  0, 2, 4, 0, 4, 3, 0, 3, 5,
27657  0, 5, 2, 1, 2, 5, 1, 5, 3,
27658  1, 3, 4, 1, 4, 2
27659  ];
27660 
27661  PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail );
27662 
27663  this.type = 'OctahedronBufferGeometry';
27664 
27665  this.parameters = {
27666  radius: radius,
27667  detail: detail
27668  };
27669 
27670  }
27671 
27672  OctahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype );
27673  OctahedronBufferGeometry.prototype.constructor = OctahedronBufferGeometry;
27674 
27680  // IcosahedronGeometry
27681 
27682  function IcosahedronGeometry( radius, detail ) {
27683 
27684  Geometry.call( this );
27685 
27686  this.type = 'IcosahedronGeometry';
27687 
27688  this.parameters = {
27689  radius: radius,
27690  detail: detail
27691  };
27692 
27693  this.fromBufferGeometry( new IcosahedronBufferGeometry( radius, detail ) );
27694  this.mergeVertices();
27695 
27696  }
27697 
27698  IcosahedronGeometry.prototype = Object.create( Geometry.prototype );
27699  IcosahedronGeometry.prototype.constructor = IcosahedronGeometry;
27700 
27701  // IcosahedronBufferGeometry
27702 
27703  function IcosahedronBufferGeometry( radius, detail ) {
27704 
27705  var t = ( 1 + Math.sqrt( 5 ) ) / 2;
27706 
27707  var vertices = [
27708  - 1, t, 0, 1, t, 0, - 1, - t, 0, 1, - t, 0,
27709  0, - 1, t, 0, 1, t, 0, - 1, - t, 0, 1, - t,
27710  t, 0, - 1, t, 0, 1, - t, 0, - 1, - t, 0, 1
27711  ];
27712 
27713  var indices = [
27714  0, 11, 5, 0, 5, 1, 0, 1, 7, 0, 7, 10, 0, 10, 11,
27715  1, 5, 9, 5, 11, 4, 11, 10, 2, 10, 7, 6, 7, 1, 8,
27716  3, 9, 4, 3, 4, 2, 3, 2, 6, 3, 6, 8, 3, 8, 9,
27717  4, 9, 5, 2, 4, 11, 6, 2, 10, 8, 6, 7, 9, 8, 1
27718  ];
27719 
27720  PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail );
27721 
27722  this.type = 'IcosahedronBufferGeometry';
27723 
27724  this.parameters = {
27725  radius: radius,
27726  detail: detail
27727  };
27728 
27729  }
27730 
27731  IcosahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype );
27732  IcosahedronBufferGeometry.prototype.constructor = IcosahedronBufferGeometry;
27733 
27739  // DodecahedronGeometry
27740 
27741  function DodecahedronGeometry( radius, detail ) {
27742 
27743  Geometry.call( this );
27744 
27745  this.type = 'DodecahedronGeometry';
27746 
27747  this.parameters = {
27748  radius: radius,
27749  detail: detail
27750  };
27751 
27752  this.fromBufferGeometry( new DodecahedronBufferGeometry( radius, detail ) );
27753  this.mergeVertices();
27754 
27755  }
27756 
27757  DodecahedronGeometry.prototype = Object.create( Geometry.prototype );
27758  DodecahedronGeometry.prototype.constructor = DodecahedronGeometry;
27759 
27760  // DodecahedronBufferGeometry
27761 
27762  function DodecahedronBufferGeometry( radius, detail ) {
27763 
27764  var t = ( 1 + Math.sqrt( 5 ) ) / 2;
27765  var r = 1 / t;
27766 
27767  var vertices = [
27768 
27769  // (±1, ±1, ±1)
27770  - 1, - 1, - 1, - 1, - 1, 1,
27771  - 1, 1, - 1, - 1, 1, 1,
27772  1, - 1, - 1, 1, - 1, 1,
27773  1, 1, - 1, 1, 1, 1,
27774 
27775  // (0, ±1/φ, ±φ)
27776  0, - r, - t, 0, - r, t,
27777  0, r, - t, 0, r, t,
27778 
27779  // (±1/φ, ±φ, 0)
27780  - r, - t, 0, - r, t, 0,
27781  r, - t, 0, r, t, 0,
27782 
27783  // (±φ, 0, ±1/φ)
27784  - t, 0, - r, t, 0, - r,
27785  - t, 0, r, t, 0, r
27786  ];
27787 
27788  var indices = [
27789  3, 11, 7, 3, 7, 15, 3, 15, 13,
27790  7, 19, 17, 7, 17, 6, 7, 6, 15,
27791  17, 4, 8, 17, 8, 10, 17, 10, 6,
27792  8, 0, 16, 8, 16, 2, 8, 2, 10,
27793  0, 12, 1, 0, 1, 18, 0, 18, 16,
27794  6, 10, 2, 6, 2, 13, 6, 13, 15,
27795  2, 16, 18, 2, 18, 3, 2, 3, 13,
27796  18, 1, 9, 18, 9, 11, 18, 11, 3,
27797  4, 14, 12, 4, 12, 0, 4, 0, 8,
27798  11, 9, 5, 11, 5, 19, 11, 19, 7,
27799  19, 5, 14, 19, 14, 4, 19, 4, 17,
27800  1, 12, 14, 1, 14, 5, 1, 5, 9
27801  ];
27802 
27803  PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail );
27804 
27805  this.type = 'DodecahedronBufferGeometry';
27806 
27807  this.parameters = {
27808  radius: radius,
27809  detail: detail
27810  };
27811 
27812  }
27813 
27814  DodecahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype );
27815  DodecahedronBufferGeometry.prototype.constructor = DodecahedronBufferGeometry;
27816 
27827  // TubeGeometry
27828 
27829  function TubeGeometry( path, tubularSegments, radius, radialSegments, closed, taper ) {
27830 
27831  Geometry.call( this );
27832 
27833  this.type = 'TubeGeometry';
27834 
27835  this.parameters = {
27836  path: path,
27837  tubularSegments: tubularSegments,
27838  radius: radius,
27839  radialSegments: radialSegments,
27840  closed: closed
27841  };
27842 
27843  if ( taper !== undefined ) console.warn( 'THREE.TubeGeometry: taper has been removed.' );
27844 
27845  var bufferGeometry = new TubeBufferGeometry( path, tubularSegments, radius, radialSegments, closed );
27846 
27847  // expose internals
27848 
27849  this.tangents = bufferGeometry.tangents;
27850  this.normals = bufferGeometry.normals;
27851  this.binormals = bufferGeometry.binormals;
27852 
27853  // create geometry
27854 
27855  this.fromBufferGeometry( bufferGeometry );
27856  this.mergeVertices();
27857 
27858  }
27859 
27860  TubeGeometry.prototype = Object.create( Geometry.prototype );
27861  TubeGeometry.prototype.constructor = TubeGeometry;
27862 
27863  // TubeBufferGeometry
27864 
27865  function TubeBufferGeometry( path, tubularSegments, radius, radialSegments, closed ) {
27866 
27867  BufferGeometry.call( this );
27868 
27869  this.type = 'TubeBufferGeometry';
27870 
27871  this.parameters = {
27872  path: path,
27873  tubularSegments: tubularSegments,
27874  radius: radius,
27875  radialSegments: radialSegments,
27876  closed: closed
27877  };
27878 
27879  tubularSegments = tubularSegments || 64;
27880  radius = radius || 1;
27881  radialSegments = radialSegments || 8;
27882  closed = closed || false;
27883 
27884  var frames = path.computeFrenetFrames( tubularSegments, closed );
27885 
27886  // expose internals
27887 
27888  this.tangents = frames.tangents;
27889  this.normals = frames.normals;
27890  this.binormals = frames.binormals;
27891 
27892  // helper variables
27893 
27894  var vertex = new Vector3();
27895  var normal = new Vector3();
27896  var uv = new Vector2();
27897  var P = new Vector3();
27898 
27899  var i, j;
27900 
27901  // buffer
27902 
27903  var vertices = [];
27904  var normals = [];
27905  var uvs = [];
27906  var indices = [];
27907 
27908  // create buffer data
27909 
27910  generateBufferData();
27911 
27912  // build geometry
27913 
27914  this.setIndex( indices );
27915  this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
27916  this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
27917  this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
27918 
27919  // functions
27920 
27921  function generateBufferData() {
27922 
27923  for ( i = 0; i < tubularSegments; i ++ ) {
27924 
27925  generateSegment( i );
27926 
27927  }
27928 
27929  // if the geometry is not closed, generate the last row of vertices and normals
27930  // at the regular position on the given path
27931  //
27932  // if the geometry is closed, duplicate the first row of vertices and normals (uvs will differ)
27933 
27934  generateSegment( ( closed === false ) ? tubularSegments : 0 );
27935 
27936  // uvs are generated in a separate function.
27937  // this makes it easy compute correct values for closed geometries
27938 
27939  generateUVs();
27940 
27941  // finally create faces
27942 
27943  generateIndices();
27944 
27945  }
27946 
27947  function generateSegment( i ) {
27948 
27949  // we use getPointAt to sample evenly distributed points from the given path
27950 
27951  P = path.getPointAt( i / tubularSegments, P );
27952 
27953  // retrieve corresponding normal and binormal
27954 
27955  var N = frames.normals[ i ];
27956  var B = frames.binormals[ i ];
27957 
27958  // generate normals and vertices for the current segment
27959 
27960  for ( j = 0; j <= radialSegments; j ++ ) {
27961 
27962  var v = j / radialSegments * Math.PI * 2;
27963 
27964  var sin = Math.sin( v );
27965  var cos = - Math.cos( v );
27966 
27967  // normal
27968 
27969  normal.x = ( cos * N.x + sin * B.x );
27970  normal.y = ( cos * N.y + sin * B.y );
27971  normal.z = ( cos * N.z + sin * B.z );
27972  normal.normalize();
27973 
27974  normals.push( normal.x, normal.y, normal.z );
27975 
27976  // vertex
27977 
27978  vertex.x = P.x + radius * normal.x;
27979  vertex.y = P.y + radius * normal.y;
27980  vertex.z = P.z + radius * normal.z;
27981 
27982  vertices.push( vertex.x, vertex.y, vertex.z );
27983 
27984  }
27985 
27986  }
27987 
27988  function generateIndices() {
27989 
27990  for ( j = 1; j <= tubularSegments; j ++ ) {
27991 
27992  for ( i = 1; i <= radialSegments; i ++ ) {
27993 
27994  var a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 );
27995  var b = ( radialSegments + 1 ) * j + ( i - 1 );
27996  var c = ( radialSegments + 1 ) * j + i;
27997  var d = ( radialSegments + 1 ) * ( j - 1 ) + i;
27998 
27999  // faces
28000 
28001  indices.push( a, b, d );
28002  indices.push( b, c, d );
28003 
28004  }
28005 
28006  }
28007 
28008  }
28009 
28010  function generateUVs() {
28011 
28012  for ( i = 0; i <= tubularSegments; i ++ ) {
28013 
28014  for ( j = 0; j <= radialSegments; j ++ ) {
28015 
28016  uv.x = i / tubularSegments;
28017  uv.y = j / radialSegments;
28018 
28019  uvs.push( uv.x, uv.y );
28020 
28021  }
28022 
28023  }
28024 
28025  }
28026 
28027  }
28028 
28029  TubeBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
28030  TubeBufferGeometry.prototype.constructor = TubeBufferGeometry;
28031 
28032  TubeBufferGeometry.prototype.toJSON = function () {
28033 
28034  var data = BufferGeometry.prototype.toJSON.call( this );
28035 
28036  data.path = this.parameters.path.toJSON();
28037 
28038  return data;
28039 
28040  };
28041 
28049  // TorusKnotGeometry
28050 
28051  function TorusKnotGeometry( radius, tube, tubularSegments, radialSegments, p, q, heightScale ) {
28052 
28053  Geometry.call( this );
28054 
28055  this.type = 'TorusKnotGeometry';
28056 
28057  this.parameters = {
28058  radius: radius,
28059  tube: tube,
28060  tubularSegments: tubularSegments,
28061  radialSegments: radialSegments,
28062  p: p,
28063  q: q
28064  };
28065 
28066  if ( heightScale !== undefined ) console.warn( 'THREE.TorusKnotGeometry: heightScale has been deprecated. Use .scale( x, y, z ) instead.' );
28067 
28068  this.fromBufferGeometry( new TorusKnotBufferGeometry( radius, tube, tubularSegments, radialSegments, p, q ) );
28069  this.mergeVertices();
28070 
28071  }
28072 
28073  TorusKnotGeometry.prototype = Object.create( Geometry.prototype );
28074  TorusKnotGeometry.prototype.constructor = TorusKnotGeometry;
28075 
28076  // TorusKnotBufferGeometry
28077 
28078  function TorusKnotBufferGeometry( radius, tube, tubularSegments, radialSegments, p, q ) {
28079 
28080  BufferGeometry.call( this );
28081 
28082  this.type = 'TorusKnotBufferGeometry';
28083 
28084  this.parameters = {
28085  radius: radius,
28086  tube: tube,
28087  tubularSegments: tubularSegments,
28088  radialSegments: radialSegments,
28089  p: p,
28090  q: q
28091  };
28092 
28093  radius = radius || 1;
28094  tube = tube || 0.4;
28095  tubularSegments = Math.floor( tubularSegments ) || 64;
28096  radialSegments = Math.floor( radialSegments ) || 8;
28097  p = p || 2;
28098  q = q || 3;
28099 
28100  // buffers
28101 
28102  var indices = [];
28103  var vertices = [];
28104  var normals = [];
28105  var uvs = [];
28106 
28107  // helper variables
28108 
28109  var i, j;
28110 
28111  var vertex = new Vector3();
28112  var normal = new Vector3();
28113 
28114  var P1 = new Vector3();
28115  var P2 = new Vector3();
28116 
28117  var B = new Vector3();
28118  var T = new Vector3();
28119  var N = new Vector3();
28120 
28121  // generate vertices, normals and uvs
28122 
28123  for ( i = 0; i <= tubularSegments; ++ i ) {
28124 
28125  // the radian "u" is used to calculate the position on the torus curve of the current tubular segement
28126 
28127  var u = i / tubularSegments * p * Math.PI * 2;
28128 
28129  // now we calculate two points. P1 is our current position on the curve, P2 is a little farther ahead.
28130  // these points are used to create a special "coordinate space", which is necessary to calculate the correct vertex positions
28131 
28132  calculatePositionOnCurve( u, p, q, radius, P1 );
28133  calculatePositionOnCurve( u + 0.01, p, q, radius, P2 );
28134 
28135  // calculate orthonormal basis
28136 
28137  T.subVectors( P2, P1 );
28138  N.addVectors( P2, P1 );
28139  B.crossVectors( T, N );
28140  N.crossVectors( B, T );
28141 
28142  // normalize B, N. T can be ignored, we don't use it
28143 
28144  B.normalize();
28145  N.normalize();
28146 
28147  for ( j = 0; j <= radialSegments; ++ j ) {
28148 
28149  // now calculate the vertices. they are nothing more than an extrusion of the torus curve.
28150  // because we extrude a shape in the xy-plane, there is no need to calculate a z-value.
28151 
28152  var v = j / radialSegments * Math.PI * 2;
28153  var cx = - tube * Math.cos( v );
28154  var cy = tube * Math.sin( v );
28155 
28156  // now calculate the final vertex position.
28157  // first we orient the extrusion with our basis vectos, then we add it to the current position on the curve
28158 
28159  vertex.x = P1.x + ( cx * N.x + cy * B.x );
28160  vertex.y = P1.y + ( cx * N.y + cy * B.y );
28161  vertex.z = P1.z + ( cx * N.z + cy * B.z );
28162 
28163  vertices.push( vertex.x, vertex.y, vertex.z );
28164 
28165  // normal (P1 is always the center/origin of the extrusion, thus we can use it to calculate the normal)
28166 
28167  normal.subVectors( vertex, P1 ).normalize();
28168 
28169  normals.push( normal.x, normal.y, normal.z );
28170 
28171  // uv
28172 
28173  uvs.push( i / tubularSegments );
28174  uvs.push( j / radialSegments );
28175 
28176  }
28177 
28178  }
28179 
28180  // generate indices
28181 
28182  for ( j = 1; j <= tubularSegments; j ++ ) {
28183 
28184  for ( i = 1; i <= radialSegments; i ++ ) {
28185 
28186  // indices
28187 
28188  var a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 );
28189  var b = ( radialSegments + 1 ) * j + ( i - 1 );
28190  var c = ( radialSegments + 1 ) * j + i;
28191  var d = ( radialSegments + 1 ) * ( j - 1 ) + i;
28192 
28193  // faces
28194 
28195  indices.push( a, b, d );
28196  indices.push( b, c, d );
28197 
28198  }
28199 
28200  }
28201 
28202  // build geometry
28203 
28204  this.setIndex( indices );
28205  this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
28206  this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
28207  this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
28208 
28209  // this function calculates the current position on the torus curve
28210 
28211  function calculatePositionOnCurve( u, p, q, radius, position ) {
28212 
28213  var cu = Math.cos( u );
28214  var su = Math.sin( u );
28215  var quOverP = q / p * u;
28216  var cs = Math.cos( quOverP );
28217 
28218  position.x = radius * ( 2 + cs ) * 0.5 * cu;
28219  position.y = radius * ( 2 + cs ) * su * 0.5;
28220  position.z = radius * Math.sin( quOverP ) * 0.5;
28221 
28222  }
28223 
28224  }
28225 
28226  TorusKnotBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
28227  TorusKnotBufferGeometry.prototype.constructor = TorusKnotBufferGeometry;
28228 
28235  // TorusGeometry
28236 
28237  function TorusGeometry( radius, tube, radialSegments, tubularSegments, arc ) {
28238 
28239  Geometry.call( this );
28240 
28241  this.type = 'TorusGeometry';
28242 
28243  this.parameters = {
28244  radius: radius,
28245  tube: tube,
28246  radialSegments: radialSegments,
28247  tubularSegments: tubularSegments,
28248  arc: arc
28249  };
28250 
28251  this.fromBufferGeometry( new TorusBufferGeometry( radius, tube, radialSegments, tubularSegments, arc ) );
28252  this.mergeVertices();
28253 
28254  }
28255 
28256  TorusGeometry.prototype = Object.create( Geometry.prototype );
28257  TorusGeometry.prototype.constructor = TorusGeometry;
28258 
28259  // TorusBufferGeometry
28260 
28261  function TorusBufferGeometry( radius, tube, radialSegments, tubularSegments, arc ) {
28262 
28263  BufferGeometry.call( this );
28264 
28265  this.type = 'TorusBufferGeometry';
28266 
28267  this.parameters = {
28268  radius: radius,
28269  tube: tube,
28270  radialSegments: radialSegments,
28271  tubularSegments: tubularSegments,
28272  arc: arc
28273  };
28274 
28275  radius = radius || 1;
28276  tube = tube || 0.4;
28277  radialSegments = Math.floor( radialSegments ) || 8;
28278  tubularSegments = Math.floor( tubularSegments ) || 6;
28279  arc = arc || Math.PI * 2;
28280 
28281  // buffers
28282 
28283  var indices = [];
28284  var vertices = [];
28285  var normals = [];
28286  var uvs = [];
28287 
28288  // helper variables
28289 
28290  var center = new Vector3();
28291  var vertex = new Vector3();
28292  var normal = new Vector3();
28293 
28294  var j, i;
28295 
28296  // generate vertices, normals and uvs
28297 
28298  for ( j = 0; j <= radialSegments; j ++ ) {
28299 
28300  for ( i = 0; i <= tubularSegments; i ++ ) {
28301 
28302  var u = i / tubularSegments * arc;
28303  var v = j / radialSegments * Math.PI * 2;
28304 
28305  // vertex
28306 
28307  vertex.x = ( radius + tube * Math.cos( v ) ) * Math.cos( u );
28308  vertex.y = ( radius + tube * Math.cos( v ) ) * Math.sin( u );
28309  vertex.z = tube * Math.sin( v );
28310 
28311  vertices.push( vertex.x, vertex.y, vertex.z );
28312 
28313  // normal
28314 
28315  center.x = radius * Math.cos( u );
28316  center.y = radius * Math.sin( u );
28317  normal.subVectors( vertex, center ).normalize();
28318 
28319  normals.push( normal.x, normal.y, normal.z );
28320 
28321  // uv
28322 
28323  uvs.push( i / tubularSegments );
28324  uvs.push( j / radialSegments );
28325 
28326  }
28327 
28328  }
28329 
28330  // generate indices
28331 
28332  for ( j = 1; j <= radialSegments; j ++ ) {
28333 
28334  for ( i = 1; i <= tubularSegments; i ++ ) {
28335 
28336  // indices
28337 
28338  var a = ( tubularSegments + 1 ) * j + i - 1;
28339  var b = ( tubularSegments + 1 ) * ( j - 1 ) + i - 1;
28340  var c = ( tubularSegments + 1 ) * ( j - 1 ) + i;
28341  var d = ( tubularSegments + 1 ) * j + i;
28342 
28343  // faces
28344 
28345  indices.push( a, b, d );
28346  indices.push( b, c, d );
28347 
28348  }
28349 
28350  }
28351 
28352  // build geometry
28353 
28354  this.setIndex( indices );
28355  this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
28356  this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
28357  this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
28358 
28359  }
28360 
28361  TorusBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
28362  TorusBufferGeometry.prototype.constructor = TorusBufferGeometry;
28363 
28369  var Earcut = {
28370 
28371  triangulate: function ( data, holeIndices, dim ) {
28372 
28373  dim = dim || 2;
28374 
28375  var hasHoles = holeIndices && holeIndices.length,
28376  outerLen = hasHoles ? holeIndices[ 0 ] * dim : data.length,
28377  outerNode = linkedList( data, 0, outerLen, dim, true ),
28378  triangles = [];
28379 
28380  if ( ! outerNode ) return triangles;
28381 
28382  var minX, minY, maxX, maxY, x, y, invSize;
28383 
28384  if ( hasHoles ) outerNode = eliminateHoles( data, holeIndices, outerNode, dim );
28385 
28386  // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox
28387 
28388  if ( data.length > 80 * dim ) {
28389 
28390  minX = maxX = data[ 0 ];
28391  minY = maxY = data[ 1 ];
28392 
28393  for ( var i = dim; i < outerLen; i += dim ) {
28394 
28395  x = data[ i ];
28396  y = data[ i + 1 ];
28397  if ( x < minX ) minX = x;
28398  if ( y < minY ) minY = y;
28399  if ( x > maxX ) maxX = x;
28400  if ( y > maxY ) maxY = y;
28401 
28402  }
28403 
28404  // minX, minY and invSize are later used to transform coords into integers for z-order calculation
28405 
28406  invSize = Math.max( maxX - minX, maxY - minY );
28407  invSize = invSize !== 0 ? 1 / invSize : 0;
28408 
28409  }
28410 
28411  earcutLinked( outerNode, triangles, dim, minX, minY, invSize );
28412 
28413  return triangles;
28414 
28415  }
28416 
28417  };
28418 
28419  // create a circular doubly linked list from polygon points in the specified winding order
28420 
28421  function linkedList( data, start, end, dim, clockwise ) {
28422 
28423  var i, last;
28424 
28425  if ( clockwise === ( signedArea( data, start, end, dim ) > 0 ) ) {
28426 
28427  for ( i = start; i < end; i += dim ) last = insertNode( i, data[ i ], data[ i + 1 ], last );
28428 
28429  } else {
28430 
28431  for ( i = end - dim; i >= start; i -= dim ) last = insertNode( i, data[ i ], data[ i + 1 ], last );
28432 
28433  }
28434 
28435  if ( last && equals( last, last.next ) ) {
28436 
28437  removeNode( last );
28438  last = last.next;
28439 
28440  }
28441 
28442  return last;
28443 
28444  }
28445 
28446  // eliminate colinear or duplicate points
28447 
28448  function filterPoints( start, end ) {
28449 
28450  if ( ! start ) return start;
28451  if ( ! end ) end = start;
28452 
28453  var p = start, again;
28454 
28455  do {
28456 
28457  again = false;
28458 
28459  if ( ! p.steiner && ( equals( p, p.next ) || area( p.prev, p, p.next ) === 0 ) ) {
28460 
28461  removeNode( p );
28462  p = end = p.prev;
28463  if ( p === p.next ) break;
28464  again = true;
28465 
28466  } else {
28467 
28468  p = p.next;
28469 
28470  }
28471 
28472  } while ( again || p !== end );
28473 
28474  return end;
28475 
28476  }
28477 
28478  // main ear slicing loop which triangulates a polygon (given as a linked list)
28479 
28480  function earcutLinked( ear, triangles, dim, minX, minY, invSize, pass ) {
28481 
28482  if ( ! ear ) return;
28483 
28484  // interlink polygon nodes in z-order
28485 
28486  if ( ! pass && invSize ) indexCurve( ear, minX, minY, invSize );
28487 
28488  var stop = ear, prev, next;
28489 
28490  // iterate through ears, slicing them one by one
28491 
28492  while ( ear.prev !== ear.next ) {
28493 
28494  prev = ear.prev;
28495  next = ear.next;
28496 
28497  if ( invSize ? isEarHashed( ear, minX, minY, invSize ) : isEar( ear ) ) {
28498 
28499  // cut off the triangle
28500  triangles.push( prev.i / dim );
28501  triangles.push( ear.i / dim );
28502  triangles.push( next.i / dim );
28503 
28504  removeNode( ear );
28505 
28506  // skipping the next vertice leads to less sliver triangles
28507  ear = next.next;
28508  stop = next.next;
28509 
28510  continue;
28511 
28512  }
28513 
28514  ear = next;
28515 
28516  // if we looped through the whole remaining polygon and can't find any more ears
28517 
28518  if ( ear === stop ) {
28519 
28520  // try filtering points and slicing again
28521 
28522  if ( ! pass ) {
28523 
28524  earcutLinked( filterPoints( ear ), triangles, dim, minX, minY, invSize, 1 );
28525 
28526  // if this didn't work, try curing all small self-intersections locally
28527 
28528  } else if ( pass === 1 ) {
28529 
28530  ear = cureLocalIntersections( ear, triangles, dim );
28531  earcutLinked( ear, triangles, dim, minX, minY, invSize, 2 );
28532 
28533  // as a last resort, try splitting the remaining polygon into two
28534 
28535  } else if ( pass === 2 ) {
28536 
28537  splitEarcut( ear, triangles, dim, minX, minY, invSize );
28538 
28539  }
28540 
28541  break;
28542 
28543  }
28544 
28545  }
28546 
28547  }
28548 
28549  // check whether a polygon node forms a valid ear with adjacent nodes
28550 
28551  function isEar( ear ) {
28552 
28553  var a = ear.prev,
28554  b = ear,
28555  c = ear.next;
28556 
28557  if ( area( a, b, c ) >= 0 ) return false; // reflex, can't be an ear
28558 
28559  // now make sure we don't have other points inside the potential ear
28560  var p = ear.next.next;
28561 
28562  while ( p !== ear.prev ) {
28563 
28564  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 ) {
28565 
28566  return false;
28567 
28568  }
28569 
28570  p = p.next;
28571 
28572  }
28573 
28574  return true;
28575 
28576  }
28577 
28578  function isEarHashed( ear, minX, minY, invSize ) {
28579 
28580  var a = ear.prev,
28581  b = ear,
28582  c = ear.next;
28583 
28584  if ( area( a, b, c ) >= 0 ) return false; // reflex, can't be an ear
28585 
28586  // triangle bbox; min & max are calculated like this for speed
28587 
28588  var minTX = a.x < b.x ? ( a.x < c.x ? a.x : c.x ) : ( b.x < c.x ? b.x : c.x ),
28589  minTY = a.y < b.y ? ( a.y < c.y ? a.y : c.y ) : ( b.y < c.y ? b.y : c.y ),
28590  maxTX = a.x > b.x ? ( a.x > c.x ? a.x : c.x ) : ( b.x > c.x ? b.x : c.x ),
28591  maxTY = a.y > b.y ? ( a.y > c.y ? a.y : c.y ) : ( b.y > c.y ? b.y : c.y );
28592 
28593  // z-order range for the current triangle bbox;
28594 
28595  var minZ = zOrder( minTX, minTY, minX, minY, invSize ),
28596  maxZ = zOrder( maxTX, maxTY, minX, minY, invSize );
28597 
28598  // first look for points inside the triangle in increasing z-order
28599 
28600  var p = ear.nextZ;
28601 
28602  while ( p && p.z <= maxZ ) {
28603 
28604  if ( p !== ear.prev && p !== ear.next &&
28605  pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) &&
28606  area( p.prev, p, p.next ) >= 0 ) return false;
28607  p = p.nextZ;
28608 
28609  }
28610 
28611  // then look for points in decreasing z-order
28612 
28613  p = ear.prevZ;
28614 
28615  while ( p && p.z >= minZ ) {
28616 
28617  if ( p !== ear.prev && p !== ear.next &&
28618  pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) &&
28619  area( p.prev, p, p.next ) >= 0 ) return false;
28620 
28621  p = p.prevZ;
28622 
28623  }
28624 
28625  return true;
28626 
28627  }
28628 
28629  // go through all polygon nodes and cure small local self-intersections
28630 
28631  function cureLocalIntersections( start, triangles, dim ) {
28632 
28633  var p = start;
28634 
28635  do {
28636 
28637  var a = p.prev, b = p.next.next;
28638 
28639  if ( ! equals( a, b ) && intersects( a, p, p.next, b ) && locallyInside( a, b ) && locallyInside( b, a ) ) {
28640 
28641  triangles.push( a.i / dim );
28642  triangles.push( p.i / dim );
28643  triangles.push( b.i / dim );
28644 
28645  // remove two nodes involved
28646 
28647  removeNode( p );
28648  removeNode( p.next );
28649 
28650  p = start = b;
28651 
28652  }
28653 
28654  p = p.next;
28655 
28656  } while ( p !== start );
28657 
28658  return p;
28659 
28660  }
28661 
28662  // try splitting polygon into two and triangulate them independently
28663 
28664  function splitEarcut( start, triangles, dim, minX, minY, invSize ) {
28665 
28666  // look for a valid diagonal that divides the polygon into two
28667 
28668  var a = start;
28669 
28670  do {
28671 
28672  var b = a.next.next;
28673 
28674  while ( b !== a.prev ) {
28675 
28676  if ( a.i !== b.i && isValidDiagonal( a, b ) ) {
28677 
28678  // split the polygon in two by the diagonal
28679 
28680  var c = splitPolygon( a, b );
28681 
28682  // filter colinear points around the cuts
28683 
28684  a = filterPoints( a, a.next );
28685  c = filterPoints( c, c.next );
28686 
28687  // run earcut on each half
28688 
28689  earcutLinked( a, triangles, dim, minX, minY, invSize );
28690  earcutLinked( c, triangles, dim, minX, minY, invSize );
28691  return;
28692 
28693  }
28694 
28695  b = b.next;
28696 
28697  }
28698 
28699  a = a.next;
28700 
28701  } while ( a !== start );
28702 
28703  }
28704 
28705  // link every hole into the outer loop, producing a single-ring polygon without holes
28706 
28707  function eliminateHoles( data, holeIndices, outerNode, dim ) {
28708 
28709  var queue = [], i, len, start, end, list;
28710 
28711  for ( i = 0, len = holeIndices.length; i < len; i ++ ) {
28712 
28713  start = holeIndices[ i ] * dim;
28714  end = i < len - 1 ? holeIndices[ i + 1 ] * dim : data.length;
28715  list = linkedList( data, start, end, dim, false );
28716  if ( list === list.next ) list.steiner = true;
28717  queue.push( getLeftmost( list ) );
28718 
28719  }
28720 
28721  queue.sort( compareX );
28722 
28723  // process holes from left to right
28724 
28725  for ( i = 0; i < queue.length; i ++ ) {
28726 
28727  eliminateHole( queue[ i ], outerNode );
28728  outerNode = filterPoints( outerNode, outerNode.next );
28729 
28730  }
28731 
28732  return outerNode;
28733 
28734  }
28735 
28736  function compareX( a, b ) {
28737 
28738  return a.x - b.x;
28739 
28740  }
28741 
28742  // find a bridge between vertices that connects hole with an outer ring and and link it
28743 
28744  function eliminateHole( hole, outerNode ) {
28745 
28746  outerNode = findHoleBridge( hole, outerNode );
28747 
28748  if ( outerNode ) {
28749 
28750  var b = splitPolygon( outerNode, hole );
28751 
28752  filterPoints( b, b.next );
28753 
28754  }
28755 
28756  }
28757 
28758  // David Eberly's algorithm for finding a bridge between hole and outer polygon
28759 
28760  function findHoleBridge( hole, outerNode ) {
28761 
28762  var p = outerNode,
28763  hx = hole.x,
28764  hy = hole.y,
28765  qx = - Infinity,
28766  m;
28767 
28768  // find a segment intersected by a ray from the hole's leftmost point to the left;
28769  // segment's endpoint with lesser x will be potential connection point
28770 
28771  do {
28772 
28773  if ( hy <= p.y && hy >= p.next.y && p.next.y !== p.y ) {
28774 
28775  var x = p.x + ( hy - p.y ) * ( p.next.x - p.x ) / ( p.next.y - p.y );
28776 
28777  if ( x <= hx && x > qx ) {
28778 
28779  qx = x;
28780 
28781  if ( x === hx ) {
28782 
28783  if ( hy === p.y ) return p;
28784  if ( hy === p.next.y ) return p.next;
28785 
28786  }
28787 
28788  m = p.x < p.next.x ? p : p.next;
28789 
28790  }
28791 
28792  }
28793 
28794  p = p.next;
28795 
28796  } while ( p !== outerNode );
28797 
28798  if ( ! m ) return null;
28799 
28800  if ( hx === qx ) return m.prev; // hole touches outer segment; pick lower endpoint
28801 
28802  // look for points inside the triangle of hole point, segment intersection and endpoint;
28803  // if there are no points found, we have a valid connection;
28804  // otherwise choose the point of the minimum angle with the ray as connection point
28805 
28806  var stop = m,
28807  mx = m.x,
28808  my = m.y,
28809  tanMin = Infinity,
28810  tan;
28811 
28812  p = m.next;
28813 
28814  while ( p !== stop ) {
28815 
28816  if ( hx >= p.x && p.x >= mx && hx !== p.x &&
28817  pointInTriangle( hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y ) ) {
28818 
28819  tan = Math.abs( hy - p.y ) / ( hx - p.x ); // tangential
28820 
28821  if ( ( tan < tanMin || ( tan === tanMin && p.x > m.x ) ) && locallyInside( p, hole ) ) {
28822 
28823  m = p;
28824  tanMin = tan;
28825 
28826  }
28827 
28828  }
28829 
28830  p = p.next;
28831 
28832  }
28833 
28834  return m;
28835 
28836  }
28837 
28838  // interlink polygon nodes in z-order
28839 
28840  function indexCurve( start, minX, minY, invSize ) {
28841 
28842  var p = start;
28843 
28844  do {
28845 
28846  if ( p.z === null ) p.z = zOrder( p.x, p.y, minX, minY, invSize );
28847  p.prevZ = p.prev;
28848  p.nextZ = p.next;
28849  p = p.next;
28850 
28851  } while ( p !== start );
28852 
28853  p.prevZ.nextZ = null;
28854  p.prevZ = null;
28855 
28856  sortLinked( p );
28857 
28858  }
28859 
28860  // Simon Tatham's linked list merge sort algorithm
28861  // http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
28862 
28863  function sortLinked( list ) {
28864 
28865  var i, p, q, e, tail, numMerges, pSize, qSize, inSize = 1;
28866 
28867  do {
28868 
28869  p = list;
28870  list = null;
28871  tail = null;
28872  numMerges = 0;
28873 
28874  while ( p ) {
28875 
28876  numMerges ++;
28877  q = p;
28878  pSize = 0;
28879 
28880  for ( i = 0; i < inSize; i ++ ) {
28881 
28882  pSize ++;
28883  q = q.nextZ;
28884  if ( ! q ) break;
28885 
28886  }
28887 
28888  qSize = inSize;
28889 
28890  while ( pSize > 0 || ( qSize > 0 && q ) ) {
28891 
28892  if ( pSize !== 0 && ( qSize === 0 || ! q || p.z <= q.z ) ) {
28893 
28894  e = p;
28895  p = p.nextZ;
28896  pSize --;
28897 
28898  } else {
28899 
28900  e = q;
28901  q = q.nextZ;
28902  qSize --;
28903 
28904  }
28905 
28906  if ( tail ) tail.nextZ = e;
28907  else list = e;
28908 
28909  e.prevZ = tail;
28910  tail = e;
28911 
28912  }
28913 
28914  p = q;
28915 
28916  }
28917 
28918  tail.nextZ = null;
28919  inSize *= 2;
28920 
28921  } while ( numMerges > 1 );
28922 
28923  return list;
28924 
28925  }
28926 
28927  // z-order of a point given coords and inverse of the longer side of data bbox
28928 
28929  function zOrder( x, y, minX, minY, invSize ) {
28930 
28931  // coords are transformed into non-negative 15-bit integer range
28932 
28933  x = 32767 * ( x - minX ) * invSize;
28934  y = 32767 * ( y - minY ) * invSize;
28935 
28936  x = ( x | ( x << 8 ) ) & 0x00FF00FF;
28937  x = ( x | ( x << 4 ) ) & 0x0F0F0F0F;
28938  x = ( x | ( x << 2 ) ) & 0x33333333;
28939  x = ( x | ( x << 1 ) ) & 0x55555555;
28940 
28941  y = ( y | ( y << 8 ) ) & 0x00FF00FF;
28942  y = ( y | ( y << 4 ) ) & 0x0F0F0F0F;
28943  y = ( y | ( y << 2 ) ) & 0x33333333;
28944  y = ( y | ( y << 1 ) ) & 0x55555555;
28945 
28946  return x | ( y << 1 );
28947 
28948  }
28949 
28950  // find the leftmost node of a polygon ring
28951 
28952  function getLeftmost( start ) {
28953 
28954  var p = start, leftmost = start;
28955 
28956  do {
28957 
28958  if ( p.x < leftmost.x ) leftmost = p;
28959  p = p.next;
28960 
28961  } while ( p !== start );
28962 
28963  return leftmost;
28964 
28965  }
28966 
28967  // check if a point lies within a convex triangle
28968 
28969  function pointInTriangle( ax, ay, bx, by, cx, cy, px, py ) {
28970 
28971  return ( cx - px ) * ( ay - py ) - ( ax - px ) * ( cy - py ) >= 0 &&
28972  ( ax - px ) * ( by - py ) - ( bx - px ) * ( ay - py ) >= 0 &&
28973  ( bx - px ) * ( cy - py ) - ( cx - px ) * ( by - py ) >= 0;
28974 
28975  }
28976 
28977  // check if a diagonal between two polygon nodes is valid (lies in polygon interior)
28978 
28979  function isValidDiagonal( a, b ) {
28980 
28981  return a.next.i !== b.i && a.prev.i !== b.i && ! intersectsPolygon( a, b ) &&
28982  locallyInside( a, b ) && locallyInside( b, a ) && middleInside( a, b );
28983 
28984  }
28985 
28986  // signed area of a triangle
28987 
28988  function area( p, q, r ) {
28989 
28990  return ( q.y - p.y ) * ( r.x - q.x ) - ( q.x - p.x ) * ( r.y - q.y );
28991 
28992  }
28993 
28994  // check if two points are equal
28995 
28996  function equals( p1, p2 ) {
28997 
28998  return p1.x === p2.x && p1.y === p2.y;
28999 
29000  }
29001 
29002  // check if two segments intersect
29003 
29004  function intersects( p1, q1, p2, q2 ) {
29005 
29006  if ( ( equals( p1, q1 ) && equals( p2, q2 ) ) ||
29007  ( equals( p1, q2 ) && equals( p2, q1 ) ) ) return true;
29008 
29009  return area( p1, q1, p2 ) > 0 !== area( p1, q1, q2 ) > 0 &&
29010  area( p2, q2, p1 ) > 0 !== area( p2, q2, q1 ) > 0;
29011 
29012  }
29013 
29014  // check if a polygon diagonal intersects any polygon segments
29015 
29016  function intersectsPolygon( a, b ) {
29017 
29018  var p = a;
29019 
29020  do {
29021 
29022  if ( p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i &&
29023  intersects( p, p.next, a, b ) ) {
29024 
29025  return true;
29026 
29027  }
29028 
29029  p = p.next;
29030 
29031  } while ( p !== a );
29032 
29033  return false;
29034 
29035  }
29036 
29037  // check if a polygon diagonal is locally inside the polygon
29038 
29039  function locallyInside( a, b ) {
29040 
29041  return area( a.prev, a, a.next ) < 0 ?
29042  area( a, b, a.next ) >= 0 && area( a, a.prev, b ) >= 0 :
29043  area( a, b, a.prev ) < 0 || area( a, a.next, b ) < 0;
29044 
29045  }
29046 
29047  // check if the middle point of a polygon diagonal is inside the polygon
29048 
29049  function middleInside( a, b ) {
29050 
29051  var p = a,
29052  inside = false,
29053  px = ( a.x + b.x ) / 2,
29054  py = ( a.y + b.y ) / 2;
29055 
29056  do {
29057 
29058  if ( ( ( p.y > py ) !== ( p.next.y > py ) ) && p.next.y !== p.y &&
29059  ( px < ( p.next.x - p.x ) * ( py - p.y ) / ( p.next.y - p.y ) + p.x ) ) {
29060 
29061  inside = ! inside;
29062 
29063  }
29064 
29065  p = p.next;
29066 
29067  } while ( p !== a );
29068 
29069  return inside;
29070 
29071  }
29072 
29073  // link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two;
29074  // if one belongs to the outer ring and another to a hole, it merges it into a single ring
29075 
29076  function splitPolygon( a, b ) {
29077 
29078  var a2 = new Node( a.i, a.x, a.y ),
29079  b2 = new Node( b.i, b.x, b.y ),
29080  an = a.next,
29081  bp = b.prev;
29082 
29083  a.next = b;
29084  b.prev = a;
29085 
29086  a2.next = an;
29087  an.prev = a2;
29088 
29089  b2.next = a2;
29090  a2.prev = b2;
29091 
29092  bp.next = b2;
29093  b2.prev = bp;
29094 
29095  return b2;
29096 
29097  }
29098 
29099  // create a node and optionally link it with previous one (in a circular doubly linked list)
29100 
29101  function insertNode( i, x, y, last ) {
29102 
29103  var p = new Node( i, x, y );
29104 
29105  if ( ! last ) {
29106 
29107  p.prev = p;
29108  p.next = p;
29109 
29110  } else {
29111 
29112  p.next = last.next;
29113  p.prev = last;
29114  last.next.prev = p;
29115  last.next = p;
29116 
29117  }
29118 
29119  return p;
29120 
29121  }
29122 
29123  function removeNode( p ) {
29124 
29125  p.next.prev = p.prev;
29126  p.prev.next = p.next;
29127 
29128  if ( p.prevZ ) p.prevZ.nextZ = p.nextZ;
29129  if ( p.nextZ ) p.nextZ.prevZ = p.prevZ;
29130 
29131  }
29132 
29133  function Node( i, x, y ) {
29134 
29135  // vertice index in coordinates array
29136  this.i = i;
29137 
29138  // vertex coordinates
29139  this.x = x;
29140  this.y = y;
29141 
29142  // previous and next vertice nodes in a polygon ring
29143  this.prev = null;
29144  this.next = null;
29145 
29146  // z-order curve value
29147  this.z = null;
29148 
29149  // previous and next nodes in z-order
29150  this.prevZ = null;
29151  this.nextZ = null;
29152 
29153  // indicates whether this is a steiner point
29154  this.steiner = false;
29155 
29156  }
29157 
29158  function signedArea( data, start, end, dim ) {
29159 
29160  var sum = 0;
29161 
29162  for ( var i = start, j = end - dim; i < end; i += dim ) {
29163 
29164  sum += ( data[ j ] - data[ i ] ) * ( data[ i + 1 ] + data[ j + 1 ] );
29165  j = i;
29166 
29167  }
29168 
29169  return sum;
29170 
29171  }
29172 
29177  var ShapeUtils = {
29178 
29179  // calculate area of the contour polygon
29180 
29181  area: function ( contour ) {
29182 
29183  var n = contour.length;
29184  var a = 0.0;
29185 
29186  for ( var p = n - 1, q = 0; q < n; p = q ++ ) {
29187 
29188  a += contour[ p ].x * contour[ q ].y - contour[ q ].x * contour[ p ].y;
29189 
29190  }
29191 
29192  return a * 0.5;
29193 
29194  },
29195 
29196  isClockWise: function ( pts ) {
29197 
29198  return ShapeUtils.area( pts ) < 0;
29199 
29200  },
29201 
29202  triangulateShape: function ( contour, holes ) {
29203 
29204  var vertices = []; // flat array of vertices like [ x0,y0, x1,y1, x2,y2, ... ]
29205  var holeIndices = []; // array of hole indices
29206  var faces = []; // final array of vertex indices like [ [ a,b,d ], [ b,c,d ] ]
29207 
29208  removeDupEndPts( contour );
29209  addContour( vertices, contour );
29210 
29211  //
29212 
29213  var holeIndex = contour.length;
29214 
29215  holes.forEach( removeDupEndPts );
29216 
29217  for ( var i = 0; i < holes.length; i ++ ) {
29218 
29219  holeIndices.push( holeIndex );
29220  holeIndex += holes[ i ].length;
29221  addContour( vertices, holes[ i ] );
29222 
29223  }
29224 
29225  //
29226 
29227  var triangles = Earcut.triangulate( vertices, holeIndices );
29228 
29229  //
29230 
29231  for ( var i = 0; i < triangles.length; i += 3 ) {
29232 
29233  faces.push( triangles.slice( i, i + 3 ) );
29234 
29235  }
29236 
29237  return faces;
29238 
29239  }
29240 
29241  };
29242 
29243  function removeDupEndPts( points ) {
29244 
29245  var l = points.length;
29246 
29247  if ( l > 2 && points[ l - 1 ].equals( points[ 0 ] ) ) {
29248 
29249  points.pop();
29250 
29251  }
29252 
29253  }
29254 
29255  function addContour( vertices, contour ) {
29256 
29257  for ( var i = 0; i < contour.length; i ++ ) {
29258 
29259  vertices.push( contour[ i ].x );
29260  vertices.push( contour[ i ].y );
29261 
29262  }
29263 
29264  }
29265 
29289  // ExtrudeGeometry
29290 
29291  function ExtrudeGeometry( shapes, options ) {
29292 
29293  Geometry.call( this );
29294 
29295  this.type = 'ExtrudeGeometry';
29296 
29297  this.parameters = {
29298  shapes: shapes,
29299  options: options
29300  };
29301 
29302  this.fromBufferGeometry( new ExtrudeBufferGeometry( shapes, options ) );
29303  this.mergeVertices();
29304 
29305  }
29306 
29307  ExtrudeGeometry.prototype = Object.create( Geometry.prototype );
29308  ExtrudeGeometry.prototype.constructor = ExtrudeGeometry;
29309 
29310  ExtrudeGeometry.prototype.toJSON = function () {
29311 
29312  var data = Geometry.prototype.toJSON.call( this );
29313 
29314  var shapes = this.parameters.shapes;
29315  var options = this.parameters.options;
29316 
29317  return toJSON( shapes, options, data );
29318 
29319  };
29320 
29321  // ExtrudeBufferGeometry
29322 
29323  function ExtrudeBufferGeometry( shapes, options ) {
29324 
29325  BufferGeometry.call( this );
29326 
29327  this.type = 'ExtrudeBufferGeometry';
29328 
29329  this.parameters = {
29330  shapes: shapes,
29331  options: options
29332  };
29333 
29334  shapes = Array.isArray( shapes ) ? shapes : [ shapes ];
29335 
29336  var scope = this;
29337 
29338  var verticesArray = [];
29339  var uvArray = [];
29340 
29341  for ( var i = 0, l = shapes.length; i < l; i ++ ) {
29342 
29343  var shape = shapes[ i ];
29344  addShape( shape );
29345 
29346  }
29347 
29348  // build geometry
29349 
29350  this.addAttribute( 'position', new Float32BufferAttribute( verticesArray, 3 ) );
29351  this.addAttribute( 'uv', new Float32BufferAttribute( uvArray, 2 ) );
29352 
29353  this.computeVertexNormals();
29354 
29355  // functions
29356 
29357  function addShape( shape ) {
29358 
29359  var placeholder = [];
29360 
29361  // options
29362 
29363  var curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12;
29364  var steps = options.steps !== undefined ? options.steps : 1;
29365  var depth = options.depth !== undefined ? options.depth : 100;
29366 
29367  var bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true;
29368  var bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 6;
29369  var bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 2;
29370  var bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3;
29371 
29372  var extrudePath = options.extrudePath;
29373 
29374  var uvgen = options.UVGenerator !== undefined ? options.UVGenerator : WorldUVGenerator;
29375 
29376  // deprecated options
29377 
29378  if ( options.amount !== undefined ) {
29379 
29380  console.warn( 'THREE.ExtrudeBufferGeometry: amount has been renamed to depth.' );
29381  depth = options.amount;
29382 
29383  }
29384 
29385  //
29386 
29387  var extrudePts, extrudeByPath = false;
29388  var splineTube, binormal, normal, position2;
29389 
29390  if ( extrudePath ) {
29391 
29392  extrudePts = extrudePath.getSpacedPoints( steps );
29393 
29394  extrudeByPath = true;
29395  bevelEnabled = false; // bevels not supported for path extrusion
29396 
29397  // SETUP TNB variables
29398 
29399  // TODO1 - have a .isClosed in spline?
29400 
29401  splineTube = extrudePath.computeFrenetFrames( steps, false );
29402 
29403  // console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length);
29404 
29405  binormal = new Vector3();
29406  normal = new Vector3();
29407  position2 = new Vector3();
29408 
29409  }
29410 
29411  // Safeguards if bevels are not enabled
29412 
29413  if ( ! bevelEnabled ) {
29414 
29415  bevelSegments = 0;
29416  bevelThickness = 0;
29417  bevelSize = 0;
29418 
29419  }
29420 
29421  // Variables initialization
29422 
29423  var ahole, h, hl; // looping of holes
29424 
29425  var shapePoints = shape.extractPoints( curveSegments );
29426 
29427  var vertices = shapePoints.shape;
29428  var holes = shapePoints.holes;
29429 
29430  var reverse = ! ShapeUtils.isClockWise( vertices );
29431 
29432  if ( reverse ) {
29433 
29434  vertices = vertices.reverse();
29435 
29436  // Maybe we should also check if holes are in the opposite direction, just to be safe ...
29437 
29438  for ( h = 0, hl = holes.length; h < hl; h ++ ) {
29439 
29440  ahole = holes[ h ];
29441 
29442  if ( ShapeUtils.isClockWise( ahole ) ) {
29443 
29444  holes[ h ] = ahole.reverse();
29445 
29446  }
29447 
29448  }
29449 
29450  }
29451 
29452 
29453  var faces = ShapeUtils.triangulateShape( vertices, holes );
29454 
29455  /* Vertices */
29456 
29457  var contour = vertices; // vertices has all points but contour has only points of circumference
29458 
29459  for ( h = 0, hl = holes.length; h < hl; h ++ ) {
29460 
29461  ahole = holes[ h ];
29462 
29463  vertices = vertices.concat( ahole );
29464 
29465  }
29466 
29467 
29468  function scalePt2( pt, vec, size ) {
29469 
29470  if ( ! vec ) console.error( "THREE.ExtrudeGeometry: vec does not exist" );
29471 
29472  return vec.clone().multiplyScalar( size ).add( pt );
29473 
29474  }
29475 
29476  var b, bs, t, z,
29477  vert, vlen = vertices.length,
29478  face, flen = faces.length;
29479 
29480 
29481  // Find directions for point movement
29482 
29483 
29484  function getBevelVec( inPt, inPrev, inNext ) {
29485 
29486  // computes for inPt the corresponding point inPt' on a new contour
29487  // shifted by 1 unit (length of normalized vector) to the left
29488  // if we walk along contour clockwise, this new contour is outside the old one
29489  //
29490  // inPt' is the intersection of the two lines parallel to the two
29491  // adjacent edges of inPt at a distance of 1 unit on the left side.
29492 
29493  var v_trans_x, v_trans_y, shrink_by; // resulting translation vector for inPt
29494 
29495  // good reading for geometry algorithms (here: line-line intersection)
29496  // http://geomalgorithms.com/a05-_intersect-1.html
29497 
29498  var v_prev_x = inPt.x - inPrev.x,
29499  v_prev_y = inPt.y - inPrev.y;
29500  var v_next_x = inNext.x - inPt.x,
29501  v_next_y = inNext.y - inPt.y;
29502 
29503  var v_prev_lensq = ( v_prev_x * v_prev_x + v_prev_y * v_prev_y );
29504 
29505  // check for collinear edges
29506  var collinear0 = ( v_prev_x * v_next_y - v_prev_y * v_next_x );
29507 
29508  if ( Math.abs( collinear0 ) > Number.EPSILON ) {
29509 
29510  // not collinear
29511 
29512  // length of vectors for normalizing
29513 
29514  var v_prev_len = Math.sqrt( v_prev_lensq );
29515  var v_next_len = Math.sqrt( v_next_x * v_next_x + v_next_y * v_next_y );
29516 
29517  // shift adjacent points by unit vectors to the left
29518 
29519  var ptPrevShift_x = ( inPrev.x - v_prev_y / v_prev_len );
29520  var ptPrevShift_y = ( inPrev.y + v_prev_x / v_prev_len );
29521 
29522  var ptNextShift_x = ( inNext.x - v_next_y / v_next_len );
29523  var ptNextShift_y = ( inNext.y + v_next_x / v_next_len );
29524 
29525  // scaling factor for v_prev to intersection point
29526 
29527  var sf = ( ( ptNextShift_x - ptPrevShift_x ) * v_next_y -
29528  ( ptNextShift_y - ptPrevShift_y ) * v_next_x ) /
29529  ( v_prev_x * v_next_y - v_prev_y * v_next_x );
29530 
29531  // vector from inPt to intersection point
29532 
29533  v_trans_x = ( ptPrevShift_x + v_prev_x * sf - inPt.x );
29534  v_trans_y = ( ptPrevShift_y + v_prev_y * sf - inPt.y );
29535 
29536  // Don't normalize!, otherwise sharp corners become ugly
29537  // but prevent crazy spikes
29538  var v_trans_lensq = ( v_trans_x * v_trans_x + v_trans_y * v_trans_y );
29539  if ( v_trans_lensq <= 2 ) {
29540 
29541  return new Vector2( v_trans_x, v_trans_y );
29542 
29543  } else {
29544 
29545  shrink_by = Math.sqrt( v_trans_lensq / 2 );
29546 
29547  }
29548 
29549  } else {
29550 
29551  // handle special case of collinear edges
29552 
29553  var direction_eq = false; // assumes: opposite
29554  if ( v_prev_x > Number.EPSILON ) {
29555 
29556  if ( v_next_x > Number.EPSILON ) {
29557 
29558  direction_eq = true;
29559 
29560  }
29561 
29562  } else {
29563 
29564  if ( v_prev_x < - Number.EPSILON ) {
29565 
29566  if ( v_next_x < - Number.EPSILON ) {
29567 
29568  direction_eq = true;
29569 
29570  }
29571 
29572  } else {
29573 
29574  if ( Math.sign( v_prev_y ) === Math.sign( v_next_y ) ) {
29575 
29576  direction_eq = true;
29577 
29578  }
29579 
29580  }
29581 
29582  }
29583 
29584  if ( direction_eq ) {
29585 
29586  // console.log("Warning: lines are a straight sequence");
29587  v_trans_x = - v_prev_y;
29588  v_trans_y = v_prev_x;
29589  shrink_by = Math.sqrt( v_prev_lensq );
29590 
29591  } else {
29592 
29593  // console.log("Warning: lines are a straight spike");
29594  v_trans_x = v_prev_x;
29595  v_trans_y = v_prev_y;
29596  shrink_by = Math.sqrt( v_prev_lensq / 2 );
29597 
29598  }
29599 
29600  }
29601 
29602  return new Vector2( v_trans_x / shrink_by, v_trans_y / shrink_by );
29603 
29604  }
29605 
29606 
29607  var contourMovements = [];
29608 
29609  for ( var i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
29610 
29611  if ( j === il ) j = 0;
29612  if ( k === il ) k = 0;
29613 
29614  // (j)---(i)---(k)
29615  // console.log('i,j,k', i, j , k)
29616 
29617  contourMovements[ i ] = getBevelVec( contour[ i ], contour[ j ], contour[ k ] );
29618 
29619  }
29620 
29621  var holesMovements = [],
29622  oneHoleMovements, verticesMovements = contourMovements.concat();
29623 
29624  for ( h = 0, hl = holes.length; h < hl; h ++ ) {
29625 
29626  ahole = holes[ h ];
29627 
29628  oneHoleMovements = [];
29629 
29630  for ( i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
29631 
29632  if ( j === il ) j = 0;
29633  if ( k === il ) k = 0;
29634 
29635  // (j)---(i)---(k)
29636  oneHoleMovements[ i ] = getBevelVec( ahole[ i ], ahole[ j ], ahole[ k ] );
29637 
29638  }
29639 
29640  holesMovements.push( oneHoleMovements );
29641  verticesMovements = verticesMovements.concat( oneHoleMovements );
29642 
29643  }
29644 
29645 
29646  // Loop bevelSegments, 1 for the front, 1 for the back
29647 
29648  for ( b = 0; b < bevelSegments; b ++ ) {
29649 
29650  //for ( b = bevelSegments; b > 0; b -- ) {
29651 
29652  t = b / bevelSegments;
29653  z = bevelThickness * Math.cos( t * Math.PI / 2 );
29654  bs = bevelSize * Math.sin( t * Math.PI / 2 );
29655 
29656  // contract shape
29657 
29658  for ( i = 0, il = contour.length; i < il; i ++ ) {
29659 
29660  vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
29661 
29662  v( vert.x, vert.y, - z );
29663 
29664  }
29665 
29666  // expand holes
29667 
29668  for ( h = 0, hl = holes.length; h < hl; h ++ ) {
29669 
29670  ahole = holes[ h ];
29671  oneHoleMovements = holesMovements[ h ];
29672 
29673  for ( i = 0, il = ahole.length; i < il; i ++ ) {
29674 
29675  vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
29676 
29677  v( vert.x, vert.y, - z );
29678 
29679  }
29680 
29681  }
29682 
29683  }
29684 
29685  bs = bevelSize;
29686 
29687  // Back facing vertices
29688 
29689  for ( i = 0; i < vlen; i ++ ) {
29690 
29691  vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
29692 
29693  if ( ! extrudeByPath ) {
29694 
29695  v( vert.x, vert.y, 0 );
29696 
29697  } else {
29698 
29699  // v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x );
29700 
29701  normal.copy( splineTube.normals[ 0 ] ).multiplyScalar( vert.x );
29702  binormal.copy( splineTube.binormals[ 0 ] ).multiplyScalar( vert.y );
29703 
29704  position2.copy( extrudePts[ 0 ] ).add( normal ).add( binormal );
29705 
29706  v( position2.x, position2.y, position2.z );
29707 
29708  }
29709 
29710  }
29711 
29712  // Add stepped vertices...
29713  // Including front facing vertices
29714 
29715  var s;
29716 
29717  for ( s = 1; s <= steps; s ++ ) {
29718 
29719  for ( i = 0; i < vlen; i ++ ) {
29720 
29721  vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
29722 
29723  if ( ! extrudeByPath ) {
29724 
29725  v( vert.x, vert.y, depth / steps * s );
29726 
29727  } else {
29728 
29729  // v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x );
29730 
29731  normal.copy( splineTube.normals[ s ] ).multiplyScalar( vert.x );
29732  binormal.copy( splineTube.binormals[ s ] ).multiplyScalar( vert.y );
29733 
29734  position2.copy( extrudePts[ s ] ).add( normal ).add( binormal );
29735 
29736  v( position2.x, position2.y, position2.z );
29737 
29738  }
29739 
29740  }
29741 
29742  }
29743 
29744 
29745  // Add bevel segments planes
29746 
29747  //for ( b = 1; b <= bevelSegments; b ++ ) {
29748  for ( b = bevelSegments - 1; b >= 0; b -- ) {
29749 
29750  t = b / bevelSegments;
29751  z = bevelThickness * Math.cos( t * Math.PI / 2 );
29752  bs = bevelSize * Math.sin( t * Math.PI / 2 );
29753 
29754  // contract shape
29755 
29756  for ( i = 0, il = contour.length; i < il; i ++ ) {
29757 
29758  vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
29759  v( vert.x, vert.y, depth + z );
29760 
29761  }
29762 
29763  // expand holes
29764 
29765  for ( h = 0, hl = holes.length; h < hl; h ++ ) {
29766 
29767  ahole = holes[ h ];
29768  oneHoleMovements = holesMovements[ h ];
29769 
29770  for ( i = 0, il = ahole.length; i < il; i ++ ) {
29771 
29772  vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
29773 
29774  if ( ! extrudeByPath ) {
29775 
29776  v( vert.x, vert.y, depth + z );
29777 
29778  } else {
29779 
29780  v( vert.x, vert.y + extrudePts[ steps - 1 ].y, extrudePts[ steps - 1 ].x + z );
29781 
29782  }
29783 
29784  }
29785 
29786  }
29787 
29788  }
29789 
29790  /* Faces */
29791 
29792  // Top and bottom faces
29793 
29794  buildLidFaces();
29795 
29796  // Sides faces
29797 
29798  buildSideFaces();
29799 
29800 
29802 
29803  function buildLidFaces() {
29804 
29805  var start = verticesArray.length / 3;
29806 
29807  if ( bevelEnabled ) {
29808 
29809  var layer = 0; // steps + 1
29810  var offset = vlen * layer;
29811 
29812  // Bottom faces
29813 
29814  for ( i = 0; i < flen; i ++ ) {
29815 
29816  face = faces[ i ];
29817  f3( face[ 2 ] + offset, face[ 1 ] + offset, face[ 0 ] + offset );
29818 
29819  }
29820 
29821  layer = steps + bevelSegments * 2;
29822  offset = vlen * layer;
29823 
29824  // Top faces
29825 
29826  for ( i = 0; i < flen; i ++ ) {
29827 
29828  face = faces[ i ];
29829  f3( face[ 0 ] + offset, face[ 1 ] + offset, face[ 2 ] + offset );
29830 
29831  }
29832 
29833  } else {
29834 
29835  // Bottom faces
29836 
29837  for ( i = 0; i < flen; i ++ ) {
29838 
29839  face = faces[ i ];
29840  f3( face[ 2 ], face[ 1 ], face[ 0 ] );
29841 
29842  }
29843 
29844  // Top faces
29845 
29846  for ( i = 0; i < flen; i ++ ) {
29847 
29848  face = faces[ i ];
29849  f3( face[ 0 ] + vlen * steps, face[ 1 ] + vlen * steps, face[ 2 ] + vlen * steps );
29850 
29851  }
29852 
29853  }
29854 
29855  scope.addGroup( start, verticesArray.length / 3 - start, 0 );
29856 
29857  }
29858 
29859  // Create faces for the z-sides of the shape
29860 
29861  function buildSideFaces() {
29862 
29863  var start = verticesArray.length / 3;
29864  var layeroffset = 0;
29865  sidewalls( contour, layeroffset );
29866  layeroffset += contour.length;
29867 
29868  for ( h = 0, hl = holes.length; h < hl; h ++ ) {
29869 
29870  ahole = holes[ h ];
29871  sidewalls( ahole, layeroffset );
29872 
29873  //, true
29874  layeroffset += ahole.length;
29875 
29876  }
29877 
29878 
29879  scope.addGroup( start, verticesArray.length / 3 - start, 1 );
29880 
29881 
29882  }
29883 
29884  function sidewalls( contour, layeroffset ) {
29885 
29886  var j, k;
29887  i = contour.length;
29888 
29889  while ( -- i >= 0 ) {
29890 
29891  j = i;
29892  k = i - 1;
29893  if ( k < 0 ) k = contour.length - 1;
29894 
29895  //console.log('b', i,j, i-1, k,vertices.length);
29896 
29897  var s = 0,
29898  sl = steps + bevelSegments * 2;
29899 
29900  for ( s = 0; s < sl; s ++ ) {
29901 
29902  var slen1 = vlen * s;
29903  var slen2 = vlen * ( s + 1 );
29904 
29905  var a = layeroffset + j + slen1,
29906  b = layeroffset + k + slen1,
29907  c = layeroffset + k + slen2,
29908  d = layeroffset + j + slen2;
29909 
29910  f4( a, b, c, d );
29911 
29912  }
29913 
29914  }
29915 
29916  }
29917 
29918  function v( x, y, z ) {
29919 
29920  placeholder.push( x );
29921  placeholder.push( y );
29922  placeholder.push( z );
29923 
29924  }
29925 
29926 
29927  function f3( a, b, c ) {
29928 
29929  addVertex( a );
29930  addVertex( b );
29931  addVertex( c );
29932 
29933  var nextIndex = verticesArray.length / 3;
29934  var uvs = uvgen.generateTopUV( scope, verticesArray, nextIndex - 3, nextIndex - 2, nextIndex - 1 );
29935 
29936  addUV( uvs[ 0 ] );
29937  addUV( uvs[ 1 ] );
29938  addUV( uvs[ 2 ] );
29939 
29940  }
29941 
29942  function f4( a, b, c, d ) {
29943 
29944  addVertex( a );
29945  addVertex( b );
29946  addVertex( d );
29947 
29948  addVertex( b );
29949  addVertex( c );
29950  addVertex( d );
29951 
29952 
29953  var nextIndex = verticesArray.length / 3;
29954  var uvs = uvgen.generateSideWallUV( scope, verticesArray, nextIndex - 6, nextIndex - 3, nextIndex - 2, nextIndex - 1 );
29955 
29956  addUV( uvs[ 0 ] );
29957  addUV( uvs[ 1 ] );
29958  addUV( uvs[ 3 ] );
29959 
29960  addUV( uvs[ 1 ] );
29961  addUV( uvs[ 2 ] );
29962  addUV( uvs[ 3 ] );
29963 
29964  }
29965 
29966  function addVertex( index ) {
29967 
29968  verticesArray.push( placeholder[ index * 3 + 0 ] );
29969  verticesArray.push( placeholder[ index * 3 + 1 ] );
29970  verticesArray.push( placeholder[ index * 3 + 2 ] );
29971 
29972  }
29973 
29974 
29975  function addUV( vector2 ) {
29976 
29977  uvArray.push( vector2.x );
29978  uvArray.push( vector2.y );
29979 
29980  }
29981 
29982  }
29983 
29984  }
29985 
29986  ExtrudeBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
29987  ExtrudeBufferGeometry.prototype.constructor = ExtrudeBufferGeometry;
29988 
29989  ExtrudeBufferGeometry.prototype.toJSON = function () {
29990 
29991  var data = BufferGeometry.prototype.toJSON.call( this );
29992 
29993  var shapes = this.parameters.shapes;
29994  var options = this.parameters.options;
29995 
29996  return toJSON( shapes, options, data );
29997 
29998  };
29999 
30000  //
30001 
30002  var WorldUVGenerator = {
30003 
30004  generateTopUV: function ( geometry, vertices, indexA, indexB, indexC ) {
30005 
30006  var a_x = vertices[ indexA * 3 ];
30007  var a_y = vertices[ indexA * 3 + 1 ];
30008  var b_x = vertices[ indexB * 3 ];
30009  var b_y = vertices[ indexB * 3 + 1 ];
30010  var c_x = vertices[ indexC * 3 ];
30011  var c_y = vertices[ indexC * 3 + 1 ];
30012 
30013  return [
30014  new Vector2( a_x, a_y ),
30015  new Vector2( b_x, b_y ),
30016  new Vector2( c_x, c_y )
30017  ];
30018 
30019  },
30020 
30021  generateSideWallUV: function ( geometry, vertices, indexA, indexB, indexC, indexD ) {
30022 
30023  var a_x = vertices[ indexA * 3 ];
30024  var a_y = vertices[ indexA * 3 + 1 ];
30025  var a_z = vertices[ indexA * 3 + 2 ];
30026  var b_x = vertices[ indexB * 3 ];
30027  var b_y = vertices[ indexB * 3 + 1 ];
30028  var b_z = vertices[ indexB * 3 + 2 ];
30029  var c_x = vertices[ indexC * 3 ];
30030  var c_y = vertices[ indexC * 3 + 1 ];
30031  var c_z = vertices[ indexC * 3 + 2 ];
30032  var d_x = vertices[ indexD * 3 ];
30033  var d_y = vertices[ indexD * 3 + 1 ];
30034  var d_z = vertices[ indexD * 3 + 2 ];
30035 
30036  if ( Math.abs( a_y - b_y ) < 0.01 ) {
30037 
30038  return [
30039  new Vector2( a_x, 1 - a_z ),
30040  new Vector2( b_x, 1 - b_z ),
30041  new Vector2( c_x, 1 - c_z ),
30042  new Vector2( d_x, 1 - d_z )
30043  ];
30044 
30045  } else {
30046 
30047  return [
30048  new Vector2( a_y, 1 - a_z ),
30049  new Vector2( b_y, 1 - b_z ),
30050  new Vector2( c_y, 1 - c_z ),
30051  new Vector2( d_y, 1 - d_z )
30052  ];
30053 
30054  }
30055 
30056  }
30057  };
30058 
30059  function toJSON( shapes, options, data ) {
30060 
30061  //
30062 
30063  data.shapes = [];
30064 
30065  if ( Array.isArray( shapes ) ) {
30066 
30067  for ( var i = 0, l = shapes.length; i < l; i ++ ) {
30068 
30069  var shape = shapes[ i ];
30070 
30071  data.shapes.push( shape.uuid );
30072 
30073  }
30074 
30075  } else {
30076 
30077  data.shapes.push( shapes.uuid );
30078 
30079  }
30080 
30081  //
30082 
30083  if ( options.extrudePath !== undefined ) data.options.extrudePath = options.extrudePath.toJSON();
30084 
30085  return data;
30086 
30087  }
30088 
30108  // TextGeometry
30109 
30110  function TextGeometry( text, parameters ) {
30111 
30112  Geometry.call( this );
30113 
30114  this.type = 'TextGeometry';
30115 
30116  this.parameters = {
30117  text: text,
30118  parameters: parameters
30119  };
30120 
30121  this.fromBufferGeometry( new TextBufferGeometry( text, parameters ) );
30122  this.mergeVertices();
30123 
30124  }
30125 
30126  TextGeometry.prototype = Object.create( Geometry.prototype );
30127  TextGeometry.prototype.constructor = TextGeometry;
30128 
30129  // TextBufferGeometry
30130 
30131  function TextBufferGeometry( text, parameters ) {
30132 
30133  parameters = parameters || {};
30134 
30135  var font = parameters.font;
30136 
30137  if ( ! ( font && font.isFont ) ) {
30138 
30139  console.error( 'THREE.TextGeometry: font parameter is not an instance of THREE.Font.' );
30140  return new Geometry();
30141 
30142  }
30143 
30144  var shapes = font.generateShapes( text, parameters.size );
30145 
30146  // translate parameters to ExtrudeGeometry API
30147 
30148  parameters.depth = parameters.height !== undefined ? parameters.height : 50;
30149 
30150  // defaults
30151 
30152  if ( parameters.bevelThickness === undefined ) parameters.bevelThickness = 10;
30153  if ( parameters.bevelSize === undefined ) parameters.bevelSize = 8;
30154  if ( parameters.bevelEnabled === undefined ) parameters.bevelEnabled = false;
30155 
30156  ExtrudeBufferGeometry.call( this, shapes, parameters );
30157 
30158  this.type = 'TextBufferGeometry';
30159 
30160  }
30161 
30162  TextBufferGeometry.prototype = Object.create( ExtrudeBufferGeometry.prototype );
30163  TextBufferGeometry.prototype.constructor = TextBufferGeometry;
30164 
30171  // SphereGeometry
30172 
30173  function SphereGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) {
30174 
30175  Geometry.call( this );
30176 
30177  this.type = 'SphereGeometry';
30178 
30179  this.parameters = {
30180  radius: radius,
30181  widthSegments: widthSegments,
30182  heightSegments: heightSegments,
30183  phiStart: phiStart,
30184  phiLength: phiLength,
30185  thetaStart: thetaStart,
30186  thetaLength: thetaLength
30187  };
30188 
30189  this.fromBufferGeometry( new SphereBufferGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) );
30190  this.mergeVertices();
30191 
30192  }
30193 
30194  SphereGeometry.prototype = Object.create( Geometry.prototype );
30195  SphereGeometry.prototype.constructor = SphereGeometry;
30196 
30197  // SphereBufferGeometry
30198 
30199  function SphereBufferGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) {
30200 
30201  BufferGeometry.call( this );
30202 
30203  this.type = 'SphereBufferGeometry';
30204 
30205  this.parameters = {
30206  radius: radius,
30207  widthSegments: widthSegments,
30208  heightSegments: heightSegments,
30209  phiStart: phiStart,
30210  phiLength: phiLength,
30211  thetaStart: thetaStart,
30212  thetaLength: thetaLength
30213  };
30214 
30215  radius = radius || 1;
30216 
30217  widthSegments = Math.max( 3, Math.floor( widthSegments ) || 8 );
30218  heightSegments = Math.max( 2, Math.floor( heightSegments ) || 6 );
30219 
30220  phiStart = phiStart !== undefined ? phiStart : 0;
30221  phiLength = phiLength !== undefined ? phiLength : Math.PI * 2;
30222 
30223  thetaStart = thetaStart !== undefined ? thetaStart : 0;
30224  thetaLength = thetaLength !== undefined ? thetaLength : Math.PI;
30225 
30226  var thetaEnd = thetaStart + thetaLength;
30227 
30228  var ix, iy;
30229 
30230  var index = 0;
30231  var grid = [];
30232 
30233  var vertex = new Vector3();
30234  var normal = new Vector3();
30235 
30236  // buffers
30237 
30238  var indices = [];
30239  var vertices = [];
30240  var normals = [];
30241  var uvs = [];
30242 
30243  // generate vertices, normals and uvs
30244 
30245  for ( iy = 0; iy <= heightSegments; iy ++ ) {
30246 
30247  var verticesRow = [];
30248 
30249  var v = iy / heightSegments;
30250 
30251  for ( ix = 0; ix <= widthSegments; ix ++ ) {
30252 
30253  var u = ix / widthSegments;
30254 
30255  // vertex
30256 
30257  vertex.x = - radius * Math.cos( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
30258  vertex.y = radius * Math.cos( thetaStart + v * thetaLength );
30259  vertex.z = radius * Math.sin( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
30260 
30261  vertices.push( vertex.x, vertex.y, vertex.z );
30262 
30263  // normal
30264 
30265  normal.set( vertex.x, vertex.y, vertex.z ).normalize();
30266  normals.push( normal.x, normal.y, normal.z );
30267 
30268  // uv
30269 
30270  uvs.push( u, 1 - v );
30271 
30272  verticesRow.push( index ++ );
30273 
30274  }
30275 
30276  grid.push( verticesRow );
30277 
30278  }
30279 
30280  // indices
30281 
30282  for ( iy = 0; iy < heightSegments; iy ++ ) {
30283 
30284  for ( ix = 0; ix < widthSegments; ix ++ ) {
30285 
30286  var a = grid[ iy ][ ix + 1 ];
30287  var b = grid[ iy ][ ix ];
30288  var c = grid[ iy + 1 ][ ix ];
30289  var d = grid[ iy + 1 ][ ix + 1 ];
30290 
30291  if ( iy !== 0 || thetaStart > 0 ) indices.push( a, b, d );
30292  if ( iy !== heightSegments - 1 || thetaEnd < Math.PI ) indices.push( b, c, d );
30293 
30294  }
30295 
30296  }
30297 
30298  // build geometry
30299 
30300  this.setIndex( indices );
30301  this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
30302  this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
30303  this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
30304 
30305  }
30306 
30307  SphereBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
30308  SphereBufferGeometry.prototype.constructor = SphereBufferGeometry;
30309 
30315  // RingGeometry
30316 
30317  function RingGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) {
30318 
30319  Geometry.call( this );
30320 
30321  this.type = 'RingGeometry';
30322 
30323  this.parameters = {
30324  innerRadius: innerRadius,
30325  outerRadius: outerRadius,
30326  thetaSegments: thetaSegments,
30327  phiSegments: phiSegments,
30328  thetaStart: thetaStart,
30329  thetaLength: thetaLength
30330  };
30331 
30332  this.fromBufferGeometry( new RingBufferGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) );
30333  this.mergeVertices();
30334 
30335  }
30336 
30337  RingGeometry.prototype = Object.create( Geometry.prototype );
30338  RingGeometry.prototype.constructor = RingGeometry;
30339 
30340  // RingBufferGeometry
30341 
30342  function RingBufferGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) {
30343 
30344  BufferGeometry.call( this );
30345 
30346  this.type = 'RingBufferGeometry';
30347 
30348  this.parameters = {
30349  innerRadius: innerRadius,
30350  outerRadius: outerRadius,
30351  thetaSegments: thetaSegments,
30352  phiSegments: phiSegments,
30353  thetaStart: thetaStart,
30354  thetaLength: thetaLength
30355  };
30356 
30357  innerRadius = innerRadius || 0.5;
30358  outerRadius = outerRadius || 1;
30359 
30360  thetaStart = thetaStart !== undefined ? thetaStart : 0;
30361  thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2;
30362 
30363  thetaSegments = thetaSegments !== undefined ? Math.max( 3, thetaSegments ) : 8;
30364  phiSegments = phiSegments !== undefined ? Math.max( 1, phiSegments ) : 1;
30365 
30366  // buffers
30367 
30368  var indices = [];
30369  var vertices = [];
30370  var normals = [];
30371  var uvs = [];
30372 
30373  // some helper variables
30374 
30375  var segment;
30376  var radius = innerRadius;
30377  var radiusStep = ( ( outerRadius - innerRadius ) / phiSegments );
30378  var vertex = new Vector3();
30379  var uv = new Vector2();
30380  var j, i;
30381 
30382  // generate vertices, normals and uvs
30383 
30384  for ( j = 0; j <= phiSegments; j ++ ) {
30385 
30386  for ( i = 0; i <= thetaSegments; i ++ ) {
30387 
30388  // values are generate from the inside of the ring to the outside
30389 
30390  segment = thetaStart + i / thetaSegments * thetaLength;
30391 
30392  // vertex
30393 
30394  vertex.x = radius * Math.cos( segment );
30395  vertex.y = radius * Math.sin( segment );
30396 
30397  vertices.push( vertex.x, vertex.y, vertex.z );
30398 
30399  // normal
30400 
30401  normals.push( 0, 0, 1 );
30402 
30403  // uv
30404 
30405  uv.x = ( vertex.x / outerRadius + 1 ) / 2;
30406  uv.y = ( vertex.y / outerRadius + 1 ) / 2;
30407 
30408  uvs.push( uv.x, uv.y );
30409 
30410  }
30411 
30412  // increase the radius for next row of vertices
30413 
30414  radius += radiusStep;
30415 
30416  }
30417 
30418  // indices
30419 
30420  for ( j = 0; j < phiSegments; j ++ ) {
30421 
30422  var thetaSegmentLevel = j * ( thetaSegments + 1 );
30423 
30424  for ( i = 0; i < thetaSegments; i ++ ) {
30425 
30426  segment = i + thetaSegmentLevel;
30427 
30428  var a = segment;
30429  var b = segment + thetaSegments + 1;
30430  var c = segment + thetaSegments + 2;
30431  var d = segment + 1;
30432 
30433  // faces
30434 
30435  indices.push( a, b, d );
30436  indices.push( b, c, d );
30437 
30438  }
30439 
30440  }
30441 
30442  // build geometry
30443 
30444  this.setIndex( indices );
30445  this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
30446  this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
30447  this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
30448 
30449  }
30450 
30451  RingBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
30452  RingBufferGeometry.prototype.constructor = RingBufferGeometry;
30453 
30460  // LatheGeometry
30461 
30462  function LatheGeometry( points, segments, phiStart, phiLength ) {
30463 
30464  Geometry.call( this );
30465 
30466  this.type = 'LatheGeometry';
30467 
30468  this.parameters = {
30469  points: points,
30470  segments: segments,
30471  phiStart: phiStart,
30472  phiLength: phiLength
30473  };
30474 
30475  this.fromBufferGeometry( new LatheBufferGeometry( points, segments, phiStart, phiLength ) );
30476  this.mergeVertices();
30477 
30478  }
30479 
30480  LatheGeometry.prototype = Object.create( Geometry.prototype );
30481  LatheGeometry.prototype.constructor = LatheGeometry;
30482 
30483  // LatheBufferGeometry
30484 
30485  function LatheBufferGeometry( points, segments, phiStart, phiLength ) {
30486 
30487  BufferGeometry.call( this );
30488 
30489  this.type = 'LatheBufferGeometry';
30490 
30491  this.parameters = {
30492  points: points,
30493  segments: segments,
30494  phiStart: phiStart,
30495  phiLength: phiLength
30496  };
30497 
30498  segments = Math.floor( segments ) || 12;
30499  phiStart = phiStart || 0;
30500  phiLength = phiLength || Math.PI * 2;
30501 
30502  // clamp phiLength so it's in range of [ 0, 2PI ]
30503 
30504  phiLength = _Math.clamp( phiLength, 0, Math.PI * 2 );
30505 
30506 
30507  // buffers
30508 
30509  var indices = [];
30510  var vertices = [];
30511  var uvs = [];
30512 
30513  // helper variables
30514 
30515  var base;
30516  var inverseSegments = 1.0 / segments;
30517  var vertex = new Vector3();
30518  var uv = new Vector2();
30519  var i, j;
30520 
30521  // generate vertices and uvs
30522 
30523  for ( i = 0; i <= segments; i ++ ) {
30524 
30525  var phi = phiStart + i * inverseSegments * phiLength;
30526 
30527  var sin = Math.sin( phi );
30528  var cos = Math.cos( phi );
30529 
30530  for ( j = 0; j <= ( points.length - 1 ); j ++ ) {
30531 
30532  // vertex
30533 
30534  vertex.x = points[ j ].x * sin;
30535  vertex.y = points[ j ].y;
30536  vertex.z = points[ j ].x * cos;
30537 
30538  vertices.push( vertex.x, vertex.y, vertex.z );
30539 
30540  // uv
30541 
30542  uv.x = i / segments;
30543  uv.y = j / ( points.length - 1 );
30544 
30545  uvs.push( uv.x, uv.y );
30546 
30547 
30548  }
30549 
30550  }
30551 
30552  // indices
30553 
30554  for ( i = 0; i < segments; i ++ ) {
30555 
30556  for ( j = 0; j < ( points.length - 1 ); j ++ ) {
30557 
30558  base = j + i * points.length;
30559 
30560  var a = base;
30561  var b = base + points.length;
30562  var c = base + points.length + 1;
30563  var d = base + 1;
30564 
30565  // faces
30566 
30567  indices.push( a, b, d );
30568  indices.push( b, c, d );
30569 
30570  }
30571 
30572  }
30573 
30574  // build geometry
30575 
30576  this.setIndex( indices );
30577  this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
30578  this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
30579 
30580  // generate normals
30581 
30582  this.computeVertexNormals();
30583 
30584  // if the geometry is closed, we need to average the normals along the seam.
30585  // because the corresponding vertices are identical (but still have different UVs).
30586 
30587  if ( phiLength === Math.PI * 2 ) {
30588 
30589  var normals = this.attributes.normal.array;
30590  var n1 = new Vector3();
30591  var n2 = new Vector3();
30592  var n = new Vector3();
30593 
30594  // this is the buffer offset for the last line of vertices
30595 
30596  base = segments * points.length * 3;
30597 
30598  for ( i = 0, j = 0; i < points.length; i ++, j += 3 ) {
30599 
30600  // select the normal of the vertex in the first line
30601 
30602  n1.x = normals[ j + 0 ];
30603  n1.y = normals[ j + 1 ];
30604  n1.z = normals[ j + 2 ];
30605 
30606  // select the normal of the vertex in the last line
30607 
30608  n2.x = normals[ base + j + 0 ];
30609  n2.y = normals[ base + j + 1 ];
30610  n2.z = normals[ base + j + 2 ];
30611 
30612  // average normals
30613 
30614  n.addVectors( n1, n2 ).normalize();
30615 
30616  // assign the new values to both normals
30617 
30618  normals[ j + 0 ] = normals[ base + j + 0 ] = n.x;
30619  normals[ j + 1 ] = normals[ base + j + 1 ] = n.y;
30620  normals[ j + 2 ] = normals[ base + j + 2 ] = n.z;
30621 
30622  }
30623 
30624  }
30625 
30626  }
30627 
30628  LatheBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
30629  LatheBufferGeometry.prototype.constructor = LatheBufferGeometry;
30630 
30636  // ShapeGeometry
30637 
30638  function ShapeGeometry( shapes, curveSegments ) {
30639 
30640  Geometry.call( this );
30641 
30642  this.type = 'ShapeGeometry';
30643 
30644  if ( typeof curveSegments === 'object' ) {
30645 
30646  console.warn( 'THREE.ShapeGeometry: Options parameter has been removed.' );
30647 
30648  curveSegments = curveSegments.curveSegments;
30649 
30650  }
30651 
30652  this.parameters = {
30653  shapes: shapes,
30654  curveSegments: curveSegments
30655  };
30656 
30657  this.fromBufferGeometry( new ShapeBufferGeometry( shapes, curveSegments ) );
30658  this.mergeVertices();
30659 
30660  }
30661 
30662  ShapeGeometry.prototype = Object.create( Geometry.prototype );
30663  ShapeGeometry.prototype.constructor = ShapeGeometry;
30664 
30665  ShapeGeometry.prototype.toJSON = function () {
30666 
30667  var data = Geometry.prototype.toJSON.call( this );
30668 
30669  var shapes = this.parameters.shapes;
30670 
30671  return toJSON$1( shapes, data );
30672 
30673  };
30674 
30675  // ShapeBufferGeometry
30676 
30677  function ShapeBufferGeometry( shapes, curveSegments ) {
30678 
30679  BufferGeometry.call( this );
30680 
30681  this.type = 'ShapeBufferGeometry';
30682 
30683  this.parameters = {
30684  shapes: shapes,
30685  curveSegments: curveSegments
30686  };
30687 
30688  curveSegments = curveSegments || 12;
30689 
30690  // buffers
30691 
30692  var indices = [];
30693  var vertices = [];
30694  var normals = [];
30695  var uvs = [];
30696 
30697  // helper variables
30698 
30699  var groupStart = 0;
30700  var groupCount = 0;
30701 
30702  // allow single and array values for "shapes" parameter
30703 
30704  if ( Array.isArray( shapes ) === false ) {
30705 
30706  addShape( shapes );
30707 
30708  } else {
30709 
30710  for ( var i = 0; i < shapes.length; i ++ ) {
30711 
30712  addShape( shapes[ i ] );
30713 
30714  this.addGroup( groupStart, groupCount, i ); // enables MultiMaterial support
30715 
30716  groupStart += groupCount;
30717  groupCount = 0;
30718 
30719  }
30720 
30721  }
30722 
30723  // build geometry
30724 
30725  this.setIndex( indices );
30726  this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
30727  this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
30728  this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
30729 
30730 
30731  // helper functions
30732 
30733  function addShape( shape ) {
30734 
30735  var i, l, shapeHole;
30736 
30737  var indexOffset = vertices.length / 3;
30738  var points = shape.extractPoints( curveSegments );
30739 
30740  var shapeVertices = points.shape;
30741  var shapeHoles = points.holes;
30742 
30743  // check direction of vertices
30744 
30745  if ( ShapeUtils.isClockWise( shapeVertices ) === false ) {
30746 
30747  shapeVertices = shapeVertices.reverse();
30748 
30749  }
30750 
30751  for ( i = 0, l = shapeHoles.length; i < l; i ++ ) {
30752 
30753  shapeHole = shapeHoles[ i ];
30754 
30755  if ( ShapeUtils.isClockWise( shapeHole ) === true ) {
30756 
30757  shapeHoles[ i ] = shapeHole.reverse();
30758 
30759  }
30760 
30761  }
30762 
30763  var faces = ShapeUtils.triangulateShape( shapeVertices, shapeHoles );
30764 
30765  // join vertices of inner and outer paths to a single array
30766 
30767  for ( i = 0, l = shapeHoles.length; i < l; i ++ ) {
30768 
30769  shapeHole = shapeHoles[ i ];
30770  shapeVertices = shapeVertices.concat( shapeHole );
30771 
30772  }
30773 
30774  // vertices, normals, uvs
30775 
30776  for ( i = 0, l = shapeVertices.length; i < l; i ++ ) {
30777 
30778  var vertex = shapeVertices[ i ];
30779 
30780  vertices.push( vertex.x, vertex.y, 0 );
30781  normals.push( 0, 0, 1 );
30782  uvs.push( vertex.x, vertex.y ); // world uvs
30783 
30784  }
30785 
30786  // incides
30787 
30788  for ( i = 0, l = faces.length; i < l; i ++ ) {
30789 
30790  var face = faces[ i ];
30791 
30792  var a = face[ 0 ] + indexOffset;
30793  var b = face[ 1 ] + indexOffset;
30794  var c = face[ 2 ] + indexOffset;
30795 
30796  indices.push( a, b, c );
30797  groupCount += 3;
30798 
30799  }
30800 
30801  }
30802 
30803  }
30804 
30805  ShapeBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
30806  ShapeBufferGeometry.prototype.constructor = ShapeBufferGeometry;
30807 
30808  ShapeBufferGeometry.prototype.toJSON = function () {
30809 
30810  var data = BufferGeometry.prototype.toJSON.call( this );
30811 
30812  var shapes = this.parameters.shapes;
30813 
30814  return toJSON$1( shapes, data );
30815 
30816  };
30817 
30818  //
30819 
30820  function toJSON$1( shapes, data ) {
30821 
30822  data.shapes = [];
30823 
30824  if ( Array.isArray( shapes ) ) {
30825 
30826  for ( var i = 0, l = shapes.length; i < l; i ++ ) {
30827 
30828  var shape = shapes[ i ];
30829 
30830  data.shapes.push( shape.uuid );
30831 
30832  }
30833 
30834  } else {
30835 
30836  data.shapes.push( shapes.uuid );
30837 
30838  }
30839 
30840  return data;
30841 
30842  }
30843 
30849  function EdgesGeometry( geometry, thresholdAngle ) {
30850 
30851  BufferGeometry.call( this );
30852 
30853  this.type = 'EdgesGeometry';
30854 
30855  this.parameters = {
30856  thresholdAngle: thresholdAngle
30857  };
30858 
30859  thresholdAngle = ( thresholdAngle !== undefined ) ? thresholdAngle : 1;
30860 
30861  // buffer
30862 
30863  var vertices = [];
30864 
30865  // helper variables
30866 
30867  var thresholdDot = Math.cos( _Math.DEG2RAD * thresholdAngle );
30868  var edge = [ 0, 0 ], edges = {}, edge1, edge2;
30869  var key, keys = [ 'a', 'b', 'c' ];
30870 
30871  // prepare source geometry
30872 
30873  var geometry2;
30874 
30875  if ( geometry.isBufferGeometry ) {
30876 
30877  geometry2 = new Geometry();
30878  geometry2.fromBufferGeometry( geometry );
30879 
30880  } else {
30881 
30882  geometry2 = geometry.clone();
30883 
30884  }
30885 
30886  geometry2.mergeVertices();
30887  geometry2.computeFaceNormals();
30888 
30889  var sourceVertices = geometry2.vertices;
30890  var faces = geometry2.faces;
30891 
30892  // now create a data structure where each entry represents an edge with its adjoining faces
30893 
30894  for ( var i = 0, l = faces.length; i < l; i ++ ) {
30895 
30896  var face = faces[ i ];
30897 
30898  for ( var j = 0; j < 3; j ++ ) {
30899 
30900  edge1 = face[ keys[ j ] ];
30901  edge2 = face[ keys[ ( j + 1 ) % 3 ] ];
30902  edge[ 0 ] = Math.min( edge1, edge2 );
30903  edge[ 1 ] = Math.max( edge1, edge2 );
30904 
30905  key = edge[ 0 ] + ',' + edge[ 1 ];
30906 
30907  if ( edges[ key ] === undefined ) {
30908 
30909  edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ], face1: i, face2: undefined };
30910 
30911  } else {
30912 
30913  edges[ key ].face2 = i;
30914 
30915  }
30916 
30917  }
30918 
30919  }
30920 
30921  // generate vertices
30922 
30923  for ( key in edges ) {
30924 
30925  var e = edges[ key ];
30926 
30927  // an edge is only rendered if the angle (in degrees) between the face normals of the adjoining faces exceeds this value. default = 1 degree.
30928 
30929  if ( e.face2 === undefined || faces[ e.face1 ].normal.dot( faces[ e.face2 ].normal ) <= thresholdDot ) {
30930 
30931  var vertex = sourceVertices[ e.index1 ];
30932  vertices.push( vertex.x, vertex.y, vertex.z );
30933 
30934  vertex = sourceVertices[ e.index2 ];
30935  vertices.push( vertex.x, vertex.y, vertex.z );
30936 
30937  }
30938 
30939  }
30940 
30941  // build geometry
30942 
30943  this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
30944 
30945  }
30946 
30947  EdgesGeometry.prototype = Object.create( BufferGeometry.prototype );
30948  EdgesGeometry.prototype.constructor = EdgesGeometry;
30949 
30955  // CylinderGeometry
30956 
30957  function CylinderGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {
30958 
30959  Geometry.call( this );
30960 
30961  this.type = 'CylinderGeometry';
30962 
30963  this.parameters = {
30964  radiusTop: radiusTop,
30965  radiusBottom: radiusBottom,
30966  height: height,
30967  radialSegments: radialSegments,
30968  heightSegments: heightSegments,
30969  openEnded: openEnded,
30970  thetaStart: thetaStart,
30971  thetaLength: thetaLength
30972  };
30973 
30974  this.fromBufferGeometry( new CylinderBufferGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) );
30975  this.mergeVertices();
30976 
30977  }
30978 
30979  CylinderGeometry.prototype = Object.create( Geometry.prototype );
30980  CylinderGeometry.prototype.constructor = CylinderGeometry;
30981 
30982  // CylinderBufferGeometry
30983 
30984  function CylinderBufferGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {
30985 
30986  BufferGeometry.call( this );
30987 
30988  this.type = 'CylinderBufferGeometry';
30989 
30990  this.parameters = {
30991  radiusTop: radiusTop,
30992  radiusBottom: radiusBottom,
30993  height: height,
30994  radialSegments: radialSegments,
30995  heightSegments: heightSegments,
30996  openEnded: openEnded,
30997  thetaStart: thetaStart,
30998  thetaLength: thetaLength
30999  };
31000 
31001  var scope = this;
31002 
31003  radiusTop = radiusTop !== undefined ? radiusTop : 1;
31004  radiusBottom = radiusBottom !== undefined ? radiusBottom : 1;
31005  height = height || 1;
31006 
31007  radialSegments = Math.floor( radialSegments ) || 8;
31008  heightSegments = Math.floor( heightSegments ) || 1;
31009 
31010  openEnded = openEnded !== undefined ? openEnded : false;
31011  thetaStart = thetaStart !== undefined ? thetaStart : 0.0;
31012  thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2;
31013 
31014  // buffers
31015 
31016  var indices = [];
31017  var vertices = [];
31018  var normals = [];
31019  var uvs = [];
31020 
31021  // helper variables
31022 
31023  var index = 0;
31024  var indexArray = [];
31025  var halfHeight = height / 2;
31026  var groupStart = 0;
31027 
31028  // generate geometry
31029 
31030  generateTorso();
31031 
31032  if ( openEnded === false ) {
31033 
31034  if ( radiusTop > 0 ) generateCap( true );
31035  if ( radiusBottom > 0 ) generateCap( false );
31036 
31037  }
31038 
31039  // build geometry
31040 
31041  this.setIndex( indices );
31042  this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
31043  this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
31044  this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
31045 
31046  function generateTorso() {
31047 
31048  var x, y;
31049  var normal = new Vector3();
31050  var vertex = new Vector3();
31051 
31052  var groupCount = 0;
31053 
31054  // this will be used to calculate the normal
31055  var slope = ( radiusBottom - radiusTop ) / height;
31056 
31057  // generate vertices, normals and uvs
31058 
31059  for ( y = 0; y <= heightSegments; y ++ ) {
31060 
31061  var indexRow = [];
31062 
31063  var v = y / heightSegments;
31064 
31065  // calculate the radius of the current row
31066 
31067  var radius = v * ( radiusBottom - radiusTop ) + radiusTop;
31068 
31069  for ( x = 0; x <= radialSegments; x ++ ) {
31070 
31071  var u = x / radialSegments;
31072 
31073  var theta = u * thetaLength + thetaStart;
31074 
31075  var sinTheta = Math.sin( theta );
31076  var cosTheta = Math.cos( theta );
31077 
31078  // vertex
31079 
31080  vertex.x = radius * sinTheta;
31081  vertex.y = - v * height + halfHeight;
31082  vertex.z = radius * cosTheta;
31083  vertices.push( vertex.x, vertex.y, vertex.z );
31084 
31085  // normal
31086 
31087  normal.set( sinTheta, slope, cosTheta ).normalize();
31088  normals.push( normal.x, normal.y, normal.z );
31089 
31090  // uv
31091 
31092  uvs.push( u, 1 - v );
31093 
31094  // save index of vertex in respective row
31095 
31096  indexRow.push( index ++ );
31097 
31098  }
31099 
31100  // now save vertices of the row in our index array
31101 
31102  indexArray.push( indexRow );
31103 
31104  }
31105 
31106  // generate indices
31107 
31108  for ( x = 0; x < radialSegments; x ++ ) {
31109 
31110  for ( y = 0; y < heightSegments; y ++ ) {
31111 
31112  // we use the index array to access the correct indices
31113 
31114  var a = indexArray[ y ][ x ];
31115  var b = indexArray[ y + 1 ][ x ];
31116  var c = indexArray[ y + 1 ][ x + 1 ];
31117  var d = indexArray[ y ][ x + 1 ];
31118 
31119  // faces
31120 
31121  indices.push( a, b, d );
31122  indices.push( b, c, d );
31123 
31124  // update group counter
31125 
31126  groupCount += 6;
31127 
31128  }
31129 
31130  }
31131 
31132  // add a group to the geometry. this will ensure multi material support
31133 
31134  scope.addGroup( groupStart, groupCount, 0 );
31135 
31136  // calculate new start value for groups
31137 
31138  groupStart += groupCount;
31139 
31140  }
31141 
31142  function generateCap( top ) {
31143 
31144  var x, centerIndexStart, centerIndexEnd;
31145 
31146  var uv = new Vector2();
31147  var vertex = new Vector3();
31148 
31149  var groupCount = 0;
31150 
31151  var radius = ( top === true ) ? radiusTop : radiusBottom;
31152  var sign = ( top === true ) ? 1 : - 1;
31153 
31154  // save the index of the first center vertex
31155  centerIndexStart = index;
31156 
31157  // first we generate the center vertex data of the cap.
31158  // because the geometry needs one set of uvs per face,
31159  // we must generate a center vertex per face/segment
31160 
31161  for ( x = 1; x <= radialSegments; x ++ ) {
31162 
31163  // vertex
31164 
31165  vertices.push( 0, halfHeight * sign, 0 );
31166 
31167  // normal
31168 
31169  normals.push( 0, sign, 0 );
31170 
31171  // uv
31172 
31173  uvs.push( 0.5, 0.5 );
31174 
31175  // increase index
31176 
31177  index ++;
31178 
31179  }
31180 
31181  // save the index of the last center vertex
31182 
31183  centerIndexEnd = index;
31184 
31185  // now we generate the surrounding vertices, normals and uvs
31186 
31187  for ( x = 0; x <= radialSegments; x ++ ) {
31188 
31189  var u = x / radialSegments;
31190  var theta = u * thetaLength + thetaStart;
31191 
31192  var cosTheta = Math.cos( theta );
31193  var sinTheta = Math.sin( theta );
31194 
31195  // vertex
31196 
31197  vertex.x = radius * sinTheta;
31198  vertex.y = halfHeight * sign;
31199  vertex.z = radius * cosTheta;
31200  vertices.push( vertex.x, vertex.y, vertex.z );
31201 
31202  // normal
31203 
31204  normals.push( 0, sign, 0 );
31205 
31206  // uv
31207 
31208  uv.x = ( cosTheta * 0.5 ) + 0.5;
31209  uv.y = ( sinTheta * 0.5 * sign ) + 0.5;
31210  uvs.push( uv.x, uv.y );
31211 
31212  // increase index
31213 
31214  index ++;
31215 
31216  }
31217 
31218  // generate indices
31219 
31220  for ( x = 0; x < radialSegments; x ++ ) {
31221 
31222  var c = centerIndexStart + x;
31223  var i = centerIndexEnd + x;
31224 
31225  if ( top === true ) {
31226 
31227  // face top
31228 
31229  indices.push( i, i + 1, c );
31230 
31231  } else {
31232 
31233  // face bottom
31234 
31235  indices.push( i + 1, i, c );
31236 
31237  }
31238 
31239  groupCount += 3;
31240 
31241  }
31242 
31243  // add a group to the geometry. this will ensure multi material support
31244 
31245  scope.addGroup( groupStart, groupCount, top === true ? 1 : 2 );
31246 
31247  // calculate new start value for groups
31248 
31249  groupStart += groupCount;
31250 
31251  }
31252 
31253  }
31254 
31255  CylinderBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
31256  CylinderBufferGeometry.prototype.constructor = CylinderBufferGeometry;
31257 
31262  // ConeGeometry
31263 
31264  function ConeGeometry( radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {
31265 
31266  CylinderGeometry.call( this, 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength );
31267 
31268  this.type = 'ConeGeometry';
31269 
31270  this.parameters = {
31271  radius: radius,
31272  height: height,
31273  radialSegments: radialSegments,
31274  heightSegments: heightSegments,
31275  openEnded: openEnded,
31276  thetaStart: thetaStart,
31277  thetaLength: thetaLength
31278  };
31279 
31280  }
31281 
31282  ConeGeometry.prototype = Object.create( CylinderGeometry.prototype );
31283  ConeGeometry.prototype.constructor = ConeGeometry;
31284 
31285  // ConeBufferGeometry
31286 
31287  function ConeBufferGeometry( radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {
31288 
31289  CylinderBufferGeometry.call( this, 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength );
31290 
31291  this.type = 'ConeBufferGeometry';
31292 
31293  this.parameters = {
31294  radius: radius,
31295  height: height,
31296  radialSegments: radialSegments,
31297  heightSegments: heightSegments,
31298  openEnded: openEnded,
31299  thetaStart: thetaStart,
31300  thetaLength: thetaLength
31301  };
31302 
31303  }
31304 
31305  ConeBufferGeometry.prototype = Object.create( CylinderBufferGeometry.prototype );
31306  ConeBufferGeometry.prototype.constructor = ConeBufferGeometry;
31307 
31314  // CircleGeometry
31315 
31316  function CircleGeometry( radius, segments, thetaStart, thetaLength ) {
31317 
31318  Geometry.call( this );
31319 
31320  this.type = 'CircleGeometry';
31321 
31322  this.parameters = {
31323  radius: radius,
31324  segments: segments,
31325  thetaStart: thetaStart,
31326  thetaLength: thetaLength
31327  };
31328 
31329  this.fromBufferGeometry( new CircleBufferGeometry( radius, segments, thetaStart, thetaLength ) );
31330  this.mergeVertices();
31331 
31332  }
31333 
31334  CircleGeometry.prototype = Object.create( Geometry.prototype );
31335  CircleGeometry.prototype.constructor = CircleGeometry;
31336 
31337  // CircleBufferGeometry
31338 
31339  function CircleBufferGeometry( radius, segments, thetaStart, thetaLength ) {
31340 
31341  BufferGeometry.call( this );
31342 
31343  this.type = 'CircleBufferGeometry';
31344 
31345  this.parameters = {
31346  radius: radius,
31347  segments: segments,
31348  thetaStart: thetaStart,
31349  thetaLength: thetaLength
31350  };
31351 
31352  radius = radius || 1;
31353  segments = segments !== undefined ? Math.max( 3, segments ) : 8;
31354 
31355  thetaStart = thetaStart !== undefined ? thetaStart : 0;
31356  thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2;
31357 
31358  // buffers
31359 
31360  var indices = [];
31361  var vertices = [];
31362  var normals = [];
31363  var uvs = [];
31364 
31365  // helper variables
31366 
31367  var i, s;
31368  var vertex = new Vector3();
31369  var uv = new Vector2();
31370 
31371  // center point
31372 
31373  vertices.push( 0, 0, 0 );
31374  normals.push( 0, 0, 1 );
31375  uvs.push( 0.5, 0.5 );
31376 
31377  for ( s = 0, i = 3; s <= segments; s ++, i += 3 ) {
31378 
31379  var segment = thetaStart + s / segments * thetaLength;
31380 
31381  // vertex
31382 
31383  vertex.x = radius * Math.cos( segment );
31384  vertex.y = radius * Math.sin( segment );
31385 
31386  vertices.push( vertex.x, vertex.y, vertex.z );
31387 
31388  // normal
31389 
31390  normals.push( 0, 0, 1 );
31391 
31392  // uvs
31393 
31394  uv.x = ( vertices[ i ] / radius + 1 ) / 2;
31395  uv.y = ( vertices[ i + 1 ] / radius + 1 ) / 2;
31396 
31397  uvs.push( uv.x, uv.y );
31398 
31399  }
31400 
31401  // indices
31402 
31403  for ( i = 1; i <= segments; i ++ ) {
31404 
31405  indices.push( i, i + 1, 0 );
31406 
31407  }
31408 
31409  // build geometry
31410 
31411  this.setIndex( indices );
31412  this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
31413  this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
31414  this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
31415 
31416  }
31417 
31418  CircleBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
31419  CircleBufferGeometry.prototype.constructor = CircleBufferGeometry;
31420 
31421 
31422 
31423  var Geometries = /*#__PURE__*/Object.freeze({
31424  WireframeGeometry: WireframeGeometry,
31425  ParametricGeometry: ParametricGeometry,
31426  ParametricBufferGeometry: ParametricBufferGeometry,
31427  TetrahedronGeometry: TetrahedronGeometry,
31428  TetrahedronBufferGeometry: TetrahedronBufferGeometry,
31429  OctahedronGeometry: OctahedronGeometry,
31430  OctahedronBufferGeometry: OctahedronBufferGeometry,
31431  IcosahedronGeometry: IcosahedronGeometry,
31432  IcosahedronBufferGeometry: IcosahedronBufferGeometry,
31433  DodecahedronGeometry: DodecahedronGeometry,
31434  DodecahedronBufferGeometry: DodecahedronBufferGeometry,
31435  PolyhedronGeometry: PolyhedronGeometry,
31436  PolyhedronBufferGeometry: PolyhedronBufferGeometry,
31437  TubeGeometry: TubeGeometry,
31438  TubeBufferGeometry: TubeBufferGeometry,
31439  TorusKnotGeometry: TorusKnotGeometry,
31440  TorusKnotBufferGeometry: TorusKnotBufferGeometry,
31441  TorusGeometry: TorusGeometry,
31442  TorusBufferGeometry: TorusBufferGeometry,
31443  TextGeometry: TextGeometry,
31444  TextBufferGeometry: TextBufferGeometry,
31445  SphereGeometry: SphereGeometry,
31446  SphereBufferGeometry: SphereBufferGeometry,
31447  RingGeometry: RingGeometry,
31448  RingBufferGeometry: RingBufferGeometry,
31449  PlaneGeometry: PlaneGeometry,
31450  PlaneBufferGeometry: PlaneBufferGeometry,
31451  LatheGeometry: LatheGeometry,
31452  LatheBufferGeometry: LatheBufferGeometry,
31453  ShapeGeometry: ShapeGeometry,
31454  ShapeBufferGeometry: ShapeBufferGeometry,
31455  ExtrudeGeometry: ExtrudeGeometry,
31456  ExtrudeBufferGeometry: ExtrudeBufferGeometry,
31457  EdgesGeometry: EdgesGeometry,
31458  ConeGeometry: ConeGeometry,
31459  ConeBufferGeometry: ConeBufferGeometry,
31460  CylinderGeometry: CylinderGeometry,
31461  CylinderBufferGeometry: CylinderBufferGeometry,
31462  CircleGeometry: CircleGeometry,
31463  CircleBufferGeometry: CircleBufferGeometry,
31464  BoxGeometry: BoxGeometry,
31465  BoxBufferGeometry: BoxBufferGeometry
31466  });
31467 
31476  function ShadowMaterial( parameters ) {
31477 
31478  Material.call( this );
31479 
31480  this.type = 'ShadowMaterial';
31481 
31482  this.color = new Color( 0x000000 );
31483  this.transparent = true;
31484 
31485  this.setValues( parameters );
31486 
31487  }
31488 
31489  ShadowMaterial.prototype = Object.create( Material.prototype );
31490  ShadowMaterial.prototype.constructor = ShadowMaterial;
31491 
31492  ShadowMaterial.prototype.isShadowMaterial = true;
31493 
31494  ShadowMaterial.prototype.copy = function ( source ) {
31495 
31496  Material.prototype.copy.call( this, source );
31497 
31498  this.color.copy( source.color );
31499 
31500  return this;
31501 
31502  };
31503 
31508  function RawShaderMaterial( parameters ) {
31509 
31510  ShaderMaterial.call( this, parameters );
31511 
31512  this.type = 'RawShaderMaterial';
31513 
31514  }
31515 
31516  RawShaderMaterial.prototype = Object.create( ShaderMaterial.prototype );
31517  RawShaderMaterial.prototype.constructor = RawShaderMaterial;
31518 
31519  RawShaderMaterial.prototype.isRawShaderMaterial = true;
31520 
31573  function MeshStandardMaterial( parameters ) {
31574 
31575  Material.call( this );
31576 
31577  this.defines = { 'STANDARD': '' };
31578 
31579  this.type = 'MeshStandardMaterial';
31580 
31581  this.color = new Color( 0xffffff ); // diffuse
31582  this.roughness = 0.5;
31583  this.metalness = 0.5;
31584 
31585  this.map = null;
31586 
31587  this.lightMap = null;
31588  this.lightMapIntensity = 1.0;
31589 
31590  this.aoMap = null;
31591  this.aoMapIntensity = 1.0;
31592 
31593  this.emissive = new Color( 0x000000 );
31594  this.emissiveIntensity = 1.0;
31595  this.emissiveMap = null;
31596 
31597  this.bumpMap = null;
31598  this.bumpScale = 1;
31599 
31600  this.normalMap = null;
31601  this.normalMapType = TangentSpaceNormalMap;
31602  this.normalScale = new Vector2( 1, 1 );
31603 
31604  this.displacementMap = null;
31605  this.displacementScale = 1;
31606  this.displacementBias = 0;
31607 
31608  this.roughnessMap = null;
31609 
31610  this.metalnessMap = null;
31611 
31612  this.alphaMap = null;
31613 
31614  this.envMap = null;
31615  this.envMapIntensity = 1.0;
31616 
31617  this.refractionRatio = 0.98;
31618 
31619  this.wireframe = false;
31620  this.wireframeLinewidth = 1;
31621  this.wireframeLinecap = 'round';
31622  this.wireframeLinejoin = 'round';
31623 
31624  this.skinning = false;
31625  this.morphTargets = false;
31626  this.morphNormals = false;
31627 
31628  this.setValues( parameters );
31629 
31630  }
31631 
31632  MeshStandardMaterial.prototype = Object.create( Material.prototype );
31633  MeshStandardMaterial.prototype.constructor = MeshStandardMaterial;
31634 
31635  MeshStandardMaterial.prototype.isMeshStandardMaterial = true;
31636 
31637  MeshStandardMaterial.prototype.copy = function ( source ) {
31638 
31639  Material.prototype.copy.call( this, source );
31640 
31641  this.defines = { 'STANDARD': '' };
31642 
31643  this.color.copy( source.color );
31644  this.roughness = source.roughness;
31645  this.metalness = source.metalness;
31646 
31647  this.map = source.map;
31648 
31649  this.lightMap = source.lightMap;
31650  this.lightMapIntensity = source.lightMapIntensity;
31651 
31652  this.aoMap = source.aoMap;
31653  this.aoMapIntensity = source.aoMapIntensity;
31654 
31655  this.emissive.copy( source.emissive );
31656  this.emissiveMap = source.emissiveMap;
31657  this.emissiveIntensity = source.emissiveIntensity;
31658 
31659  this.bumpMap = source.bumpMap;
31660  this.bumpScale = source.bumpScale;
31661 
31662  this.normalMap = source.normalMap;
31663  this.normalMapType = source.normalMapType;
31664  this.normalScale.copy( source.normalScale );
31665 
31666  this.displacementMap = source.displacementMap;
31667  this.displacementScale = source.displacementScale;
31668  this.displacementBias = source.displacementBias;
31669 
31670  this.roughnessMap = source.roughnessMap;
31671 
31672  this.metalnessMap = source.metalnessMap;
31673 
31674  this.alphaMap = source.alphaMap;
31675 
31676  this.envMap = source.envMap;
31677  this.envMapIntensity = source.envMapIntensity;
31678 
31679  this.refractionRatio = source.refractionRatio;
31680 
31681  this.wireframe = source.wireframe;
31682  this.wireframeLinewidth = source.wireframeLinewidth;
31683  this.wireframeLinecap = source.wireframeLinecap;
31684  this.wireframeLinejoin = source.wireframeLinejoin;
31685 
31686  this.skinning = source.skinning;
31687  this.morphTargets = source.morphTargets;
31688  this.morphNormals = source.morphNormals;
31689 
31690  return this;
31691 
31692  };
31693 
31704  function MeshPhysicalMaterial( parameters ) {
31705 
31706  MeshStandardMaterial.call( this );
31707 
31708  this.defines = { 'PHYSICAL': '' };
31709 
31710  this.type = 'MeshPhysicalMaterial';
31711 
31712  this.reflectivity = 0.5; // maps to F0 = 0.04
31713 
31714  this.clearCoat = 0.0;
31715  this.clearCoatRoughness = 0.0;
31716 
31717  this.setValues( parameters );
31718 
31719  }
31720 
31721  MeshPhysicalMaterial.prototype = Object.create( MeshStandardMaterial.prototype );
31722  MeshPhysicalMaterial.prototype.constructor = MeshPhysicalMaterial;
31723 
31724  MeshPhysicalMaterial.prototype.isMeshPhysicalMaterial = true;
31725 
31726  MeshPhysicalMaterial.prototype.copy = function ( source ) {
31727 
31728  MeshStandardMaterial.prototype.copy.call( this, source );
31729 
31730  this.defines = { 'PHYSICAL': '' };
31731 
31732  this.reflectivity = source.reflectivity;
31733 
31734  this.clearCoat = source.clearCoat;
31735  this.clearCoatRoughness = source.clearCoatRoughness;
31736 
31737  return this;
31738 
31739  };
31740 
31792  function MeshPhongMaterial( parameters ) {
31793 
31794  Material.call( this );
31795 
31796  this.type = 'MeshPhongMaterial';
31797 
31798  this.color = new Color( 0xffffff ); // diffuse
31799  this.specular = new Color( 0x111111 );
31800  this.shininess = 30;
31801 
31802  this.map = null;
31803 
31804  this.lightMap = null;
31805  this.lightMapIntensity = 1.0;
31806 
31807  this.aoMap = null;
31808  this.aoMapIntensity = 1.0;
31809 
31810  this.emissive = new Color( 0x000000 );
31811  this.emissiveIntensity = 1.0;
31812  this.emissiveMap = null;
31813 
31814  this.bumpMap = null;
31815  this.bumpScale = 1;
31816 
31817  this.normalMap = null;
31818  this.normalMapType = TangentSpaceNormalMap;
31819  this.normalScale = new Vector2( 1, 1 );
31820 
31821  this.displacementMap = null;
31822  this.displacementScale = 1;
31823  this.displacementBias = 0;
31824 
31825  this.specularMap = null;
31826 
31827  this.alphaMap = null;
31828 
31829  this.envMap = null;
31830  this.combine = MultiplyOperation;
31831  this.reflectivity = 1;
31832  this.refractionRatio = 0.98;
31833 
31834  this.wireframe = false;
31835  this.wireframeLinewidth = 1;
31836  this.wireframeLinecap = 'round';
31837  this.wireframeLinejoin = 'round';
31838 
31839  this.skinning = false;
31840  this.morphTargets = false;
31841  this.morphNormals = false;
31842 
31843  this.setValues( parameters );
31844 
31845  }
31846 
31847  MeshPhongMaterial.prototype = Object.create( Material.prototype );
31848  MeshPhongMaterial.prototype.constructor = MeshPhongMaterial;
31849 
31850  MeshPhongMaterial.prototype.isMeshPhongMaterial = true;
31851 
31852  MeshPhongMaterial.prototype.copy = function ( source ) {
31853 
31854  Material.prototype.copy.call( this, source );
31855 
31856  this.color.copy( source.color );
31857  this.specular.copy( source.specular );
31858  this.shininess = source.shininess;
31859 
31860  this.map = source.map;
31861 
31862  this.lightMap = source.lightMap;
31863  this.lightMapIntensity = source.lightMapIntensity;
31864 
31865  this.aoMap = source.aoMap;
31866  this.aoMapIntensity = source.aoMapIntensity;
31867 
31868  this.emissive.copy( source.emissive );
31869  this.emissiveMap = source.emissiveMap;
31870  this.emissiveIntensity = source.emissiveIntensity;
31871 
31872  this.bumpMap = source.bumpMap;
31873  this.bumpScale = source.bumpScale;
31874 
31875  this.normalMap = source.normalMap;
31876  this.normalMapType = source.normalMapType;
31877  this.normalScale.copy( source.normalScale );
31878 
31879  this.displacementMap = source.displacementMap;
31880  this.displacementScale = source.displacementScale;
31881  this.displacementBias = source.displacementBias;
31882 
31883  this.specularMap = source.specularMap;
31884 
31885  this.alphaMap = source.alphaMap;
31886 
31887  this.envMap = source.envMap;
31888  this.combine = source.combine;
31889  this.reflectivity = source.reflectivity;
31890  this.refractionRatio = source.refractionRatio;
31891 
31892  this.wireframe = source.wireframe;
31893  this.wireframeLinewidth = source.wireframeLinewidth;
31894  this.wireframeLinecap = source.wireframeLinecap;
31895  this.wireframeLinejoin = source.wireframeLinejoin;
31896 
31897  this.skinning = source.skinning;
31898  this.morphTargets = source.morphTargets;
31899  this.morphNormals = source.morphNormals;
31900 
31901  return this;
31902 
31903  };
31904 
31913  function MeshToonMaterial( parameters ) {
31914 
31915  MeshPhongMaterial.call( this );
31916 
31917  this.defines = { 'TOON': '' };
31918 
31919  this.type = 'MeshToonMaterial';
31920 
31921  this.gradientMap = null;
31922 
31923  this.setValues( parameters );
31924 
31925  }
31926 
31927  MeshToonMaterial.prototype = Object.create( MeshPhongMaterial.prototype );
31928  MeshToonMaterial.prototype.constructor = MeshToonMaterial;
31929 
31930  MeshToonMaterial.prototype.isMeshToonMaterial = true;
31931 
31932  MeshToonMaterial.prototype.copy = function ( source ) {
31933 
31934  MeshPhongMaterial.prototype.copy.call( this, source );
31935 
31936  this.gradientMap = source.gradientMap;
31937 
31938  return this;
31939 
31940  };
31941 
31969  function MeshNormalMaterial( parameters ) {
31970 
31971  Material.call( this );
31972 
31973  this.type = 'MeshNormalMaterial';
31974 
31975  this.bumpMap = null;
31976  this.bumpScale = 1;
31977 
31978  this.normalMap = null;
31979  this.normalMapType = TangentSpaceNormalMap;
31980  this.normalScale = new Vector2( 1, 1 );
31981 
31982  this.displacementMap = null;
31983  this.displacementScale = 1;
31984  this.displacementBias = 0;
31985 
31986  this.wireframe = false;
31987  this.wireframeLinewidth = 1;
31988 
31989  this.fog = false;
31990  this.lights = false;
31991 
31992  this.skinning = false;
31993  this.morphTargets = false;
31994  this.morphNormals = false;
31995 
31996  this.setValues( parameters );
31997 
31998  }
31999 
32000  MeshNormalMaterial.prototype = Object.create( Material.prototype );
32001  MeshNormalMaterial.prototype.constructor = MeshNormalMaterial;
32002 
32003  MeshNormalMaterial.prototype.isMeshNormalMaterial = true;
32004 
32005  MeshNormalMaterial.prototype.copy = function ( source ) {
32006 
32007  Material.prototype.copy.call( this, source );
32008 
32009  this.bumpMap = source.bumpMap;
32010  this.bumpScale = source.bumpScale;
32011 
32012  this.normalMap = source.normalMap;
32013  this.normalMapType = source.normalMapType;
32014  this.normalScale.copy( source.normalScale );
32015 
32016  this.displacementMap = source.displacementMap;
32017  this.displacementScale = source.displacementScale;
32018  this.displacementBias = source.displacementBias;
32019 
32020  this.wireframe = source.wireframe;
32021  this.wireframeLinewidth = source.wireframeLinewidth;
32022 
32023  this.skinning = source.skinning;
32024  this.morphTargets = source.morphTargets;
32025  this.morphNormals = source.morphNormals;
32026 
32027  return this;
32028 
32029  };
32030 
32069  function MeshLambertMaterial( parameters ) {
32070 
32071  Material.call( this );
32072 
32073  this.type = 'MeshLambertMaterial';
32074 
32075  this.color = new Color( 0xffffff ); // diffuse
32076 
32077  this.map = null;
32078 
32079  this.lightMap = null;
32080  this.lightMapIntensity = 1.0;
32081 
32082  this.aoMap = null;
32083  this.aoMapIntensity = 1.0;
32084 
32085  this.emissive = new Color( 0x000000 );
32086  this.emissiveIntensity = 1.0;
32087  this.emissiveMap = null;
32088 
32089  this.specularMap = null;
32090 
32091  this.alphaMap = null;
32092 
32093  this.envMap = null;
32094  this.combine = MultiplyOperation;
32095  this.reflectivity = 1;
32096  this.refractionRatio = 0.98;
32097 
32098  this.wireframe = false;
32099  this.wireframeLinewidth = 1;
32100  this.wireframeLinecap = 'round';
32101  this.wireframeLinejoin = 'round';
32102 
32103  this.skinning = false;
32104  this.morphTargets = false;
32105  this.morphNormals = false;
32106 
32107  this.setValues( parameters );
32108 
32109  }
32110 
32111  MeshLambertMaterial.prototype = Object.create( Material.prototype );
32112  MeshLambertMaterial.prototype.constructor = MeshLambertMaterial;
32113 
32114  MeshLambertMaterial.prototype.isMeshLambertMaterial = true;
32115 
32116  MeshLambertMaterial.prototype.copy = function ( source ) {
32117 
32118  Material.prototype.copy.call( this, source );
32119 
32120  this.color.copy( source.color );
32121 
32122  this.map = source.map;
32123 
32124  this.lightMap = source.lightMap;
32125  this.lightMapIntensity = source.lightMapIntensity;
32126 
32127  this.aoMap = source.aoMap;
32128  this.aoMapIntensity = source.aoMapIntensity;
32129 
32130  this.emissive.copy( source.emissive );
32131  this.emissiveMap = source.emissiveMap;
32132  this.emissiveIntensity = source.emissiveIntensity;
32133 
32134  this.specularMap = source.specularMap;
32135 
32136  this.alphaMap = source.alphaMap;
32137 
32138  this.envMap = source.envMap;
32139  this.combine = source.combine;
32140  this.reflectivity = source.reflectivity;
32141  this.refractionRatio = source.refractionRatio;
32142 
32143  this.wireframe = source.wireframe;
32144  this.wireframeLinewidth = source.wireframeLinewidth;
32145  this.wireframeLinecap = source.wireframeLinecap;
32146  this.wireframeLinejoin = source.wireframeLinejoin;
32147 
32148  this.skinning = source.skinning;
32149  this.morphTargets = source.morphTargets;
32150  this.morphNormals = source.morphNormals;
32151 
32152  return this;
32153 
32154  };
32155 
32186  function MeshMatcapMaterial( parameters ) {
32187 
32188  Material.call( this );
32189 
32190  this.defines = { 'MATCAP': '' };
32191 
32192  this.type = 'MeshMatcapMaterial';
32193 
32194  this.color = new Color( 0xffffff ); // diffuse
32195 
32196  this.matcap = null;
32197 
32198  this.map = null;
32199 
32200  this.bumpMap = null;
32201  this.bumpScale = 1;
32202 
32203  this.normalMap = null;
32204  this.normalMapType = TangentSpaceNormalMap;
32205  this.normalScale = new Vector2( 1, 1 );
32206 
32207  this.displacementMap = null;
32208  this.displacementScale = 1;
32209  this.displacementBias = 0;
32210 
32211  this.alphaMap = null;
32212 
32213  this.skinning = false;
32214  this.morphTargets = false;
32215  this.morphNormals = false;
32216 
32217  this.lights = false;
32218 
32219  this.setValues( parameters );
32220 
32221  }
32222 
32223  MeshMatcapMaterial.prototype = Object.create( Material.prototype );
32224  MeshMatcapMaterial.prototype.constructor = MeshMatcapMaterial;
32225 
32226  MeshMatcapMaterial.prototype.isMeshMatcapMaterial = true;
32227 
32228  MeshMatcapMaterial.prototype.copy = function ( source ) {
32229 
32230  Material.prototype.copy.call( this, source );
32231 
32232  this.defines = { 'MATCAP': '' };
32233 
32234  this.color.copy( source.color );
32235 
32236  this.matcap = source.matcap;
32237 
32238  this.map = source.map;
32239 
32240  this.bumpMap = source.bumpMap;
32241  this.bumpScale = source.bumpScale;
32242 
32243  this.normalMap = source.normalMap;
32244  this.normalMapType = source.normalMapType;
32245  this.normalScale.copy( source.normalScale );
32246 
32247  this.displacementMap = source.displacementMap;
32248  this.displacementScale = source.displacementScale;
32249  this.displacementBias = source.displacementBias;
32250 
32251  this.alphaMap = source.alphaMap;
32252 
32253  this.skinning = source.skinning;
32254  this.morphTargets = source.morphTargets;
32255  this.morphNormals = source.morphNormals;
32256 
32257  return this;
32258 
32259  };
32260 
32276  function LineDashedMaterial( parameters ) {
32277 
32278  LineBasicMaterial.call( this );
32279 
32280  this.type = 'LineDashedMaterial';
32281 
32282  this.scale = 1;
32283  this.dashSize = 3;
32284  this.gapSize = 1;
32285 
32286  this.setValues( parameters );
32287 
32288  }
32289 
32290  LineDashedMaterial.prototype = Object.create( LineBasicMaterial.prototype );
32291  LineDashedMaterial.prototype.constructor = LineDashedMaterial;
32292 
32293  LineDashedMaterial.prototype.isLineDashedMaterial = true;
32294 
32295  LineDashedMaterial.prototype.copy = function ( source ) {
32296 
32297  LineBasicMaterial.prototype.copy.call( this, source );
32298 
32299  this.scale = source.scale;
32300  this.dashSize = source.dashSize;
32301  this.gapSize = source.gapSize;
32302 
32303  return this;
32304 
32305  };
32306 
32307 
32308 
32309  var Materials = /*#__PURE__*/Object.freeze({
32310  ShadowMaterial: ShadowMaterial,
32311  SpriteMaterial: SpriteMaterial,
32312  RawShaderMaterial: RawShaderMaterial,
32313  ShaderMaterial: ShaderMaterial,
32314  PointsMaterial: PointsMaterial,
32315  MeshPhysicalMaterial: MeshPhysicalMaterial,
32316  MeshStandardMaterial: MeshStandardMaterial,
32317  MeshPhongMaterial: MeshPhongMaterial,
32318  MeshToonMaterial: MeshToonMaterial,
32319  MeshNormalMaterial: MeshNormalMaterial,
32320  MeshLambertMaterial: MeshLambertMaterial,
32321  MeshDepthMaterial: MeshDepthMaterial,
32322  MeshDistanceMaterial: MeshDistanceMaterial,
32323  MeshBasicMaterial: MeshBasicMaterial,
32324  MeshMatcapMaterial: MeshMatcapMaterial,
32325  LineDashedMaterial: LineDashedMaterial,
32326  LineBasicMaterial: LineBasicMaterial,
32327  Material: Material
32328  });
32329 
32336  var AnimationUtils = {
32337 
32338  // same as Array.prototype.slice, but also works on typed arrays
32339  arraySlice: function ( array, from, to ) {
32340 
32341  if ( AnimationUtils.isTypedArray( array ) ) {
32342 
32343  // in ios9 array.subarray(from, undefined) will return empty array
32344  // but array.subarray(from) or array.subarray(from, len) is correct
32345  return new array.constructor( array.subarray( from, to !== undefined ? to : array.length ) );
32346 
32347  }
32348 
32349  return array.slice( from, to );
32350 
32351  },
32352 
32353  // converts an array to a specific type
32354  convertArray: function ( array, type, forceClone ) {
32355 
32356  if ( ! array || // let 'undefined' and 'null' pass
32357  ! forceClone && array.constructor === type ) return array;
32358 
32359  if ( typeof type.BYTES_PER_ELEMENT === 'number' ) {
32360 
32361  return new type( array ); // create typed array
32362 
32363  }
32364 
32365  return Array.prototype.slice.call( array ); // create Array
32366 
32367  },
32368 
32369  isTypedArray: function ( object ) {
32370 
32371  return ArrayBuffer.isView( object ) &&
32372  ! ( object instanceof DataView );
32373 
32374  },
32375 
32376  // returns an array by which times and values can be sorted
32377  getKeyframeOrder: function ( times ) {
32378 
32379  function compareTime( i, j ) {
32380 
32381  return times[ i ] - times[ j ];
32382 
32383  }
32384 
32385  var n = times.length;
32386  var result = new Array( n );
32387  for ( var i = 0; i !== n; ++ i ) result[ i ] = i;
32388 
32389  result.sort( compareTime );
32390 
32391  return result;
32392 
32393  },
32394 
32395  // uses the array previously returned by 'getKeyframeOrder' to sort data
32396  sortedArray: function ( values, stride, order ) {
32397 
32398  var nValues = values.length;
32399  var result = new values.constructor( nValues );
32400 
32401  for ( var i = 0, dstOffset = 0; dstOffset !== nValues; ++ i ) {
32402 
32403  var srcOffset = order[ i ] * stride;
32404 
32405  for ( var j = 0; j !== stride; ++ j ) {
32406 
32407  result[ dstOffset ++ ] = values[ srcOffset + j ];
32408 
32409  }
32410 
32411  }
32412 
32413  return result;
32414 
32415  },
32416 
32417  // function for parsing AOS keyframe formats
32418  flattenJSON: function ( jsonKeys, times, values, valuePropertyName ) {
32419 
32420  var i = 1, key = jsonKeys[ 0 ];
32421 
32422  while ( key !== undefined && key[ valuePropertyName ] === undefined ) {
32423 
32424  key = jsonKeys[ i ++ ];
32425 
32426  }
32427 
32428  if ( key === undefined ) return; // no data
32429 
32430  var value = key[ valuePropertyName ];
32431  if ( value === undefined ) return; // no data
32432 
32433  if ( Array.isArray( value ) ) {
32434 
32435  do {
32436 
32437  value = key[ valuePropertyName ];
32438 
32439  if ( value !== undefined ) {
32440 
32441  times.push( key.time );
32442  values.push.apply( values, value ); // push all elements
32443 
32444  }
32445 
32446  key = jsonKeys[ i ++ ];
32447 
32448  } while ( key !== undefined );
32449 
32450  } else if ( value.toArray !== undefined ) {
32451 
32452  // ...assume THREE.Math-ish
32453 
32454  do {
32455 
32456  value = key[ valuePropertyName ];
32457 
32458  if ( value !== undefined ) {
32459 
32460  times.push( key.time );
32461  value.toArray( values, values.length );
32462 
32463  }
32464 
32465  key = jsonKeys[ i ++ ];
32466 
32467  } while ( key !== undefined );
32468 
32469  } else {
32470 
32471  // otherwise push as-is
32472 
32473  do {
32474 
32475  value = key[ valuePropertyName ];
32476 
32477  if ( value !== undefined ) {
32478 
32479  times.push( key.time );
32480  values.push( value );
32481 
32482  }
32483 
32484  key = jsonKeys[ i ++ ];
32485 
32486  } while ( key !== undefined );
32487 
32488  }
32489 
32490  }
32491 
32492  };
32493 
32516  function Interpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
32517 
32518  this.parameterPositions = parameterPositions;
32519  this._cachedIndex = 0;
32520 
32521  this.resultBuffer = resultBuffer !== undefined ?
32522  resultBuffer : new sampleValues.constructor( sampleSize );
32523  this.sampleValues = sampleValues;
32524  this.valueSize = sampleSize;
32525 
32526  }
32527 
32528  Object.assign( Interpolant.prototype, {
32529 
32530  evaluate: function ( t ) {
32531 
32532  var pp = this.parameterPositions,
32533  i1 = this._cachedIndex,
32534 
32535  t1 = pp[ i1 ],
32536  t0 = pp[ i1 - 1 ];
32537 
32538  validate_interval: {
32539 
32540  seek: {
32541 
32542  var right;
32543 
32544  linear_scan: {
32545 
32546  //- See http://jsperf.com/comparison-to-undefined/3
32547  //- slower code:
32548  //-
32549  //- if ( t >= t1 || t1 === undefined ) {
32550  forward_scan: if ( ! ( t < t1 ) ) {
32551 
32552  for ( var giveUpAt = i1 + 2; ; ) {
32553 
32554  if ( t1 === undefined ) {
32555 
32556  if ( t < t0 ) break forward_scan;
32557 
32558  // after end
32559 
32560  i1 = pp.length;
32561  this._cachedIndex = i1;
32562  return this.afterEnd_( i1 - 1, t, t0 );
32563 
32564  }
32565 
32566  if ( i1 === giveUpAt ) break; // this loop
32567 
32568  t0 = t1;
32569  t1 = pp[ ++ i1 ];
32570 
32571  if ( t < t1 ) {
32572 
32573  // we have arrived at the sought interval
32574  break seek;
32575 
32576  }
32577 
32578  }
32579 
32580  // prepare binary search on the right side of the index
32581  right = pp.length;
32582  break linear_scan;
32583 
32584  }
32585 
32586  //- slower code:
32587  //- if ( t < t0 || t0 === undefined ) {
32588  if ( ! ( t >= t0 ) ) {
32589 
32590  // looping?
32591 
32592  var t1global = pp[ 1 ];
32593 
32594  if ( t < t1global ) {
32595 
32596  i1 = 2; // + 1, using the scan for the details
32597  t0 = t1global;
32598 
32599  }
32600 
32601  // linear reverse scan
32602 
32603  for ( var giveUpAt = i1 - 2; ; ) {
32604 
32605  if ( t0 === undefined ) {
32606 
32607  // before start
32608 
32609  this._cachedIndex = 0;
32610  return this.beforeStart_( 0, t, t1 );
32611 
32612  }
32613 
32614  if ( i1 === giveUpAt ) break; // this loop
32615 
32616  t1 = t0;
32617  t0 = pp[ -- i1 - 1 ];
32618 
32619  if ( t >= t0 ) {
32620 
32621  // we have arrived at the sought interval
32622  break seek;
32623 
32624  }
32625 
32626  }
32627 
32628  // prepare binary search on the left side of the index
32629  right = i1;
32630  i1 = 0;
32631  break linear_scan;
32632 
32633  }
32634 
32635  // the interval is valid
32636 
32637  break validate_interval;
32638 
32639  } // linear scan
32640 
32641  // binary search
32642 
32643  while ( i1 < right ) {
32644 
32645  var mid = ( i1 + right ) >>> 1;
32646 
32647  if ( t < pp[ mid ] ) {
32648 
32649  right = mid;
32650 
32651  } else {
32652 
32653  i1 = mid + 1;
32654 
32655  }
32656 
32657  }
32658 
32659  t1 = pp[ i1 ];
32660  t0 = pp[ i1 - 1 ];
32661 
32662  // check boundary cases, again
32663 
32664  if ( t0 === undefined ) {
32665 
32666  this._cachedIndex = 0;
32667  return this.beforeStart_( 0, t, t1 );
32668 
32669  }
32670 
32671  if ( t1 === undefined ) {
32672 
32673  i1 = pp.length;
32674  this._cachedIndex = i1;
32675  return this.afterEnd_( i1 - 1, t0, t );
32676 
32677  }
32678 
32679  } // seek
32680 
32681  this._cachedIndex = i1;
32682 
32683  this.intervalChanged_( i1, t0, t1 );
32684 
32685  } // validate_interval
32686 
32687  return this.interpolate_( i1, t0, t, t1 );
32688 
32689  },
32690 
32691  settings: null, // optional, subclass-specific settings structure
32692  // Note: The indirection allows central control of many interpolants.
32693 
32694  // --- Protected interface
32695 
32696  DefaultSettings_: {},
32697 
32698  getSettings_: function () {
32699 
32700  return this.settings || this.DefaultSettings_;
32701 
32702  },
32703 
32704  copySampleValue_: function ( index ) {
32705 
32706  // copies a sample value to the result buffer
32707 
32708  var result = this.resultBuffer,
32709  values = this.sampleValues,
32710  stride = this.valueSize,
32711  offset = index * stride;
32712 
32713  for ( var i = 0; i !== stride; ++ i ) {
32714 
32715  result[ i ] = values[ offset + i ];
32716 
32717  }
32718 
32719  return result;
32720 
32721  },
32722 
32723  // Template methods for derived classes:
32724 
32725  interpolate_: function ( /* i1, t0, t, t1 */ ) {
32726 
32727  throw new Error( 'call to abstract method' );
32728  // implementations shall return this.resultBuffer
32729 
32730  },
32731 
32732  intervalChanged_: function ( /* i1, t0, t1 */ ) {
32733 
32734  // empty
32735 
32736  }
32737 
32738  } );
32739 
32741  Object.assign( Interpolant.prototype, {
32742 
32743  //( 0, t, t0 ), returns this.resultBuffer
32744  beforeStart_: Interpolant.prototype.copySampleValue_,
32745 
32746  //( N-1, tN-1, t ), returns this.resultBuffer
32747  afterEnd_: Interpolant.prototype.copySampleValue_,
32748 
32749  } );
32750 
32761  function CubicInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
32762 
32763  Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );
32764 
32765  this._weightPrev = - 0;
32766  this._offsetPrev = - 0;
32767  this._weightNext = - 0;
32768  this._offsetNext = - 0;
32769 
32770  }
32771 
32772  CubicInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {
32773 
32774  constructor: CubicInterpolant,
32775 
32776  DefaultSettings_: {
32777 
32778  endingStart: ZeroCurvatureEnding,
32779  endingEnd: ZeroCurvatureEnding
32780 
32781  },
32782 
32783  intervalChanged_: function ( i1, t0, t1 ) {
32784 
32785  var pp = this.parameterPositions,
32786  iPrev = i1 - 2,
32787  iNext = i1 + 1,
32788 
32789  tPrev = pp[ iPrev ],
32790  tNext = pp[ iNext ];
32791 
32792  if ( tPrev === undefined ) {
32793 
32794  switch ( this.getSettings_().endingStart ) {
32795 
32796  case ZeroSlopeEnding:
32797 
32798  // f'(t0) = 0
32799  iPrev = i1;
32800  tPrev = 2 * t0 - t1;
32801 
32802  break;
32803 
32804  case WrapAroundEnding:
32805 
32806  // use the other end of the curve
32807  iPrev = pp.length - 2;
32808  tPrev = t0 + pp[ iPrev ] - pp[ iPrev + 1 ];
32809 
32810  break;
32811 
32812  default: // ZeroCurvatureEnding
32813 
32814  // f''(t0) = 0 a.k.a. Natural Spline
32815  iPrev = i1;
32816  tPrev = t1;
32817 
32818  }
32819 
32820  }
32821 
32822  if ( tNext === undefined ) {
32823 
32824  switch ( this.getSettings_().endingEnd ) {
32825 
32826  case ZeroSlopeEnding:
32827 
32828  // f'(tN) = 0
32829  iNext = i1;
32830  tNext = 2 * t1 - t0;
32831 
32832  break;
32833 
32834  case WrapAroundEnding:
32835 
32836  // use the other end of the curve
32837  iNext = 1;
32838  tNext = t1 + pp[ 1 ] - pp[ 0 ];
32839 
32840  break;
32841 
32842  default: // ZeroCurvatureEnding
32843 
32844  // f''(tN) = 0, a.k.a. Natural Spline
32845  iNext = i1 - 1;
32846  tNext = t0;
32847 
32848  }
32849 
32850  }
32851 
32852  var halfDt = ( t1 - t0 ) * 0.5,
32853  stride = this.valueSize;
32854 
32855  this._weightPrev = halfDt / ( t0 - tPrev );
32856  this._weightNext = halfDt / ( tNext - t1 );
32857  this._offsetPrev = iPrev * stride;
32858  this._offsetNext = iNext * stride;
32859 
32860  },
32861 
32862  interpolate_: function ( i1, t0, t, t1 ) {
32863 
32864  var result = this.resultBuffer,
32865  values = this.sampleValues,
32866  stride = this.valueSize,
32867 
32868  o1 = i1 * stride, o0 = o1 - stride,
32869  oP = this._offsetPrev, oN = this._offsetNext,
32870  wP = this._weightPrev, wN = this._weightNext,
32871 
32872  p = ( t - t0 ) / ( t1 - t0 ),
32873  pp = p * p,
32874  ppp = pp * p;
32875 
32876  // evaluate polynomials
32877 
32878  var sP = - wP * ppp + 2 * wP * pp - wP * p;
32879  var s0 = ( 1 + wP ) * ppp + ( - 1.5 - 2 * wP ) * pp + ( - 0.5 + wP ) * p + 1;
32880  var s1 = ( - 1 - wN ) * ppp + ( 1.5 + wN ) * pp + 0.5 * p;
32881  var sN = wN * ppp - wN * pp;
32882 
32883  // combine data linearly
32884 
32885  for ( var i = 0; i !== stride; ++ i ) {
32886 
32887  result[ i ] =
32888  sP * values[ oP + i ] +
32889  s0 * values[ o0 + i ] +
32890  s1 * values[ o1 + i ] +
32891  sN * values[ oN + i ];
32892 
32893  }
32894 
32895  return result;
32896 
32897  }
32898 
32899  } );
32900 
32905  function LinearInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
32906 
32907  Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );
32908 
32909  }
32910 
32911  LinearInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {
32912 
32913  constructor: LinearInterpolant,
32914 
32915  interpolate_: function ( i1, t0, t, t1 ) {
32916 
32917  var result = this.resultBuffer,
32918  values = this.sampleValues,
32919  stride = this.valueSize,
32920 
32921  offset1 = i1 * stride,
32922  offset0 = offset1 - stride,
32923 
32924  weight1 = ( t - t0 ) / ( t1 - t0 ),
32925  weight0 = 1 - weight1;
32926 
32927  for ( var i = 0; i !== stride; ++ i ) {
32928 
32929  result[ i ] =
32930  values[ offset0 + i ] * weight0 +
32931  values[ offset1 + i ] * weight1;
32932 
32933  }
32934 
32935  return result;
32936 
32937  }
32938 
32939  } );
32940 
32949  function DiscreteInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
32950 
32951  Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );
32952 
32953  }
32954 
32955  DiscreteInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {
32956 
32957  constructor: DiscreteInterpolant,
32958 
32959  interpolate_: function ( i1 /*, t0, t, t1 */ ) {
32960 
32961  return this.copySampleValue_( i1 - 1 );
32962 
32963  }
32964 
32965  } );
32966 
32977  function KeyframeTrack( name, times, values, interpolation ) {
32978 
32979  if ( name === undefined ) throw new Error( 'THREE.KeyframeTrack: track name is undefined' );
32980  if ( times === undefined || times.length === 0 ) throw new Error( 'THREE.KeyframeTrack: no keyframes in track named ' + name );
32981 
32982  this.name = name;
32983 
32984  this.times = AnimationUtils.convertArray( times, this.TimeBufferType );
32985  this.values = AnimationUtils.convertArray( values, this.ValueBufferType );
32986 
32987  this.setInterpolation( interpolation || this.DefaultInterpolation );
32988 
32989  }
32990 
32991  // Static methods
32992 
32993  Object.assign( KeyframeTrack, {
32994 
32995  // Serialization (in static context, because of constructor invocation
32996  // and automatic invocation of .toJSON):
32997 
32998  toJSON: function ( track ) {
32999 
33000  var trackType = track.constructor;
33001 
33002  var json;
33003 
33004  // derived classes can define a static toJSON method
33005  if ( trackType.toJSON !== undefined ) {
33006 
33007  json = trackType.toJSON( track );
33008 
33009  } else {
33010 
33011  // by default, we assume the data can be serialized as-is
33012  json = {
33013 
33014  'name': track.name,
33015  'times': AnimationUtils.convertArray( track.times, Array ),
33016  'values': AnimationUtils.convertArray( track.values, Array )
33017 
33018  };
33019 
33020  var interpolation = track.getInterpolation();
33021 
33022  if ( interpolation !== track.DefaultInterpolation ) {
33023 
33024  json.interpolation = interpolation;
33025 
33026  }
33027 
33028  }
33029 
33030  json.type = track.ValueTypeName; // mandatory
33031 
33032  return json;
33033 
33034  }
33035 
33036  } );
33037 
33038  Object.assign( KeyframeTrack.prototype, {
33039 
33040  constructor: KeyframeTrack,
33041 
33042  TimeBufferType: Float32Array,
33043 
33044  ValueBufferType: Float32Array,
33045 
33046  DefaultInterpolation: InterpolateLinear,
33047 
33048  InterpolantFactoryMethodDiscrete: function ( result ) {
33049 
33050  return new DiscreteInterpolant( this.times, this.values, this.getValueSize(), result );
33051 
33052  },
33053 
33054  InterpolantFactoryMethodLinear: function ( result ) {
33055 
33056  return new LinearInterpolant( this.times, this.values, this.getValueSize(), result );
33057 
33058  },
33059 
33060  InterpolantFactoryMethodSmooth: function ( result ) {
33061 
33062  return new CubicInterpolant( this.times, this.values, this.getValueSize(), result );
33063 
33064  },
33065 
33066  setInterpolation: function ( interpolation ) {
33067 
33068  var factoryMethod;
33069 
33070  switch ( interpolation ) {
33071 
33072  case InterpolateDiscrete:
33073 
33074  factoryMethod = this.InterpolantFactoryMethodDiscrete;
33075 
33076  break;
33077 
33078  case InterpolateLinear:
33079 
33080  factoryMethod = this.InterpolantFactoryMethodLinear;
33081 
33082  break;
33083 
33084  case InterpolateSmooth:
33085 
33086  factoryMethod = this.InterpolantFactoryMethodSmooth;
33087 
33088  break;
33089 
33090  }
33091 
33092  if ( factoryMethod === undefined ) {
33093 
33094  var message = "unsupported interpolation for " +
33095  this.ValueTypeName + " keyframe track named " + this.name;
33096 
33097  if ( this.createInterpolant === undefined ) {
33098 
33099  // fall back to default, unless the default itself is messed up
33100  if ( interpolation !== this.DefaultInterpolation ) {
33101 
33102  this.setInterpolation( this.DefaultInterpolation );
33103 
33104  } else {
33105 
33106  throw new Error( message ); // fatal, in this case
33107 
33108  }
33109 
33110  }
33111 
33112  console.warn( 'THREE.KeyframeTrack:', message );
33113  return this;
33114 
33115  }
33116 
33117  this.createInterpolant = factoryMethod;
33118 
33119  return this;
33120 
33121  },
33122 
33123  getInterpolation: function () {
33124 
33125  switch ( this.createInterpolant ) {
33126 
33127  case this.InterpolantFactoryMethodDiscrete:
33128 
33129  return InterpolateDiscrete;
33130 
33131  case this.InterpolantFactoryMethodLinear:
33132 
33133  return InterpolateLinear;
33134 
33135  case this.InterpolantFactoryMethodSmooth:
33136 
33137  return InterpolateSmooth;
33138 
33139  }
33140 
33141  },
33142 
33143  getValueSize: function () {
33144 
33145  return this.values.length / this.times.length;
33146 
33147  },
33148 
33149  // move all keyframes either forwards or backwards in time
33150  shift: function ( timeOffset ) {
33151 
33152  if ( timeOffset !== 0.0 ) {
33153 
33154  var times = this.times;
33155 
33156  for ( var i = 0, n = times.length; i !== n; ++ i ) {
33157 
33158  times[ i ] += timeOffset;
33159 
33160  }
33161 
33162  }
33163 
33164  return this;
33165 
33166  },
33167 
33168  // scale all keyframe times by a factor (useful for frame <-> seconds conversions)
33169  scale: function ( timeScale ) {
33170 
33171  if ( timeScale !== 1.0 ) {
33172 
33173  var times = this.times;
33174 
33175  for ( var i = 0, n = times.length; i !== n; ++ i ) {
33176 
33177  times[ i ] *= timeScale;
33178 
33179  }
33180 
33181  }
33182 
33183  return this;
33184 
33185  },
33186 
33187  // removes keyframes before and after animation without changing any values within the range [startTime, endTime].
33188  // IMPORTANT: We do not shift around keys to the start of the track time, because for interpolated keys this will change their values
33189  trim: function ( startTime, endTime ) {
33190 
33191  var times = this.times,
33192  nKeys = times.length,
33193  from = 0,
33194  to = nKeys - 1;
33195 
33196  while ( from !== nKeys && times[ from ] < startTime ) {
33197 
33198  ++ from;
33199 
33200  }
33201 
33202  while ( to !== - 1 && times[ to ] > endTime ) {
33203 
33204  -- to;
33205 
33206  }
33207 
33208  ++ to; // inclusive -> exclusive bound
33209 
33210  if ( from !== 0 || to !== nKeys ) {
33211 
33212  // empty tracks are forbidden, so keep at least one keyframe
33213  if ( from >= to ) to = Math.max( to, 1 ), from = to - 1;
33214 
33215  var stride = this.getValueSize();
33216  this.times = AnimationUtils.arraySlice( times, from, to );
33217  this.values = AnimationUtils.arraySlice( this.values, from * stride, to * stride );
33218 
33219  }
33220 
33221  return this;
33222 
33223  },
33224 
33225  // ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable
33226  validate: function () {
33227 
33228  var valid = true;
33229 
33230  var valueSize = this.getValueSize();
33231  if ( valueSize - Math.floor( valueSize ) !== 0 ) {
33232 
33233  console.error( 'THREE.KeyframeTrack: Invalid value size in track.', this );
33234  valid = false;
33235 
33236  }
33237 
33238  var times = this.times,
33239  values = this.values,
33240 
33241  nKeys = times.length;
33242 
33243  if ( nKeys === 0 ) {
33244 
33245  console.error( 'THREE.KeyframeTrack: Track is empty.', this );
33246  valid = false;
33247 
33248  }
33249 
33250  var prevTime = null;
33251 
33252  for ( var i = 0; i !== nKeys; i ++ ) {
33253 
33254  var currTime = times[ i ];
33255 
33256  if ( typeof currTime === 'number' && isNaN( currTime ) ) {
33257 
33258  console.error( 'THREE.KeyframeTrack: Time is not a valid number.', this, i, currTime );
33259  valid = false;
33260  break;
33261 
33262  }
33263 
33264  if ( prevTime !== null && prevTime > currTime ) {
33265 
33266  console.error( 'THREE.KeyframeTrack: Out of order keys.', this, i, currTime, prevTime );
33267  valid = false;
33268  break;
33269 
33270  }
33271 
33272  prevTime = currTime;
33273 
33274  }
33275 
33276  if ( values !== undefined ) {
33277 
33278  if ( AnimationUtils.isTypedArray( values ) ) {
33279 
33280  for ( var i = 0, n = values.length; i !== n; ++ i ) {
33281 
33282  var value = values[ i ];
33283 
33284  if ( isNaN( value ) ) {
33285 
33286  console.error( 'THREE.KeyframeTrack: Value is not a valid number.', this, i, value );
33287  valid = false;
33288  break;
33289 
33290  }
33291 
33292  }
33293 
33294  }
33295 
33296  }
33297 
33298  return valid;
33299 
33300  },
33301 
33302  // removes equivalent sequential keys as common in morph target sequences
33303  // (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0)
33304  optimize: function () {
33305 
33306  var times = this.times,
33307  values = this.values,
33308  stride = this.getValueSize(),
33309 
33310  smoothInterpolation = this.getInterpolation() === InterpolateSmooth,
33311 
33312  writeIndex = 1,
33313  lastIndex = times.length - 1;
33314 
33315  for ( var i = 1; i < lastIndex; ++ i ) {
33316 
33317  var keep = false;
33318 
33319  var time = times[ i ];
33320  var timeNext = times[ i + 1 ];
33321 
33322  // remove adjacent keyframes scheduled at the same time
33323 
33324  if ( time !== timeNext && ( i !== 1 || time !== time[ 0 ] ) ) {
33325 
33326  if ( ! smoothInterpolation ) {
33327 
33328  // remove unnecessary keyframes same as their neighbors
33329 
33330  var offset = i * stride,
33331  offsetP = offset - stride,
33332  offsetN = offset + stride;
33333 
33334  for ( var j = 0; j !== stride; ++ j ) {
33335 
33336  var value = values[ offset + j ];
33337 
33338  if ( value !== values[ offsetP + j ] ||
33339  value !== values[ offsetN + j ] ) {
33340 
33341  keep = true;
33342  break;
33343 
33344  }
33345 
33346  }
33347 
33348  } else {
33349 
33350  keep = true;
33351 
33352  }
33353 
33354  }
33355 
33356  // in-place compaction
33357 
33358  if ( keep ) {
33359 
33360  if ( i !== writeIndex ) {
33361 
33362  times[ writeIndex ] = times[ i ];
33363 
33364  var readOffset = i * stride,
33365  writeOffset = writeIndex * stride;
33366 
33367  for ( var j = 0; j !== stride; ++ j ) {
33368 
33369  values[ writeOffset + j ] = values[ readOffset + j ];
33370 
33371  }
33372 
33373  }
33374 
33375  ++ writeIndex;
33376 
33377  }
33378 
33379  }
33380 
33381  // flush last keyframe (compaction looks ahead)
33382 
33383  if ( lastIndex > 0 ) {
33384 
33385  times[ writeIndex ] = times[ lastIndex ];
33386 
33387  for ( var readOffset = lastIndex * stride, writeOffset = writeIndex * stride, j = 0; j !== stride; ++ j ) {
33388 
33389  values[ writeOffset + j ] = values[ readOffset + j ];
33390 
33391  }
33392 
33393  ++ writeIndex;
33394 
33395  }
33396 
33397  if ( writeIndex !== times.length ) {
33398 
33399  this.times = AnimationUtils.arraySlice( times, 0, writeIndex );
33400  this.values = AnimationUtils.arraySlice( values, 0, writeIndex * stride );
33401 
33402  }
33403 
33404  return this;
33405 
33406  },
33407 
33408  clone: function () {
33409 
33410  var times = AnimationUtils.arraySlice( this.times, 0 );
33411  var values = AnimationUtils.arraySlice( this.values, 0 );
33412 
33413  var TypedKeyframeTrack = this.constructor;
33414  var track = new TypedKeyframeTrack( this.name, times, values );
33415 
33416  // Interpolant argument to constructor is not saved, so copy the factory method directly.
33417  track.createInterpolant = this.createInterpolant;
33418 
33419  return track;
33420 
33421  }
33422 
33423  } );
33424 
33435  function BooleanKeyframeTrack( name, times, values ) {
33436 
33437  KeyframeTrack.call( this, name, times, values );
33438 
33439  }
33440 
33441  BooleanKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
33442 
33443  constructor: BooleanKeyframeTrack,
33444 
33445  ValueTypeName: 'bool',
33446  ValueBufferType: Array,
33447 
33448  DefaultInterpolation: InterpolateDiscrete,
33449 
33450  InterpolantFactoryMethodLinear: undefined,
33451  InterpolantFactoryMethodSmooth: undefined
33452 
33453  // Note: Actually this track could have a optimized / compressed
33454  // representation of a single value and a custom interpolant that
33455  // computes "firstValue ^ isOdd( index )".
33456 
33457  } );
33458 
33469  function ColorKeyframeTrack( name, times, values, interpolation ) {
33470 
33471  KeyframeTrack.call( this, name, times, values, interpolation );
33472 
33473  }
33474 
33475  ColorKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
33476 
33477  constructor: ColorKeyframeTrack,
33478 
33479  ValueTypeName: 'color'
33480 
33481  // ValueBufferType is inherited
33482 
33483  // DefaultInterpolation is inherited
33484 
33485  // Note: Very basic implementation and nothing special yet.
33486  // However, this is the place for color space parameterization.
33487 
33488  } );
33489 
33499  function NumberKeyframeTrack( name, times, values, interpolation ) {
33500 
33501  KeyframeTrack.call( this, name, times, values, interpolation );
33502 
33503  }
33504 
33505  NumberKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
33506 
33507  constructor: NumberKeyframeTrack,
33508 
33509  ValueTypeName: 'number'
33510 
33511  // ValueBufferType is inherited
33512 
33513  // DefaultInterpolation is inherited
33514 
33515  } );
33516 
33523  function QuaternionLinearInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
33524 
33525  Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );
33526 
33527  }
33528 
33529  QuaternionLinearInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {
33530 
33531  constructor: QuaternionLinearInterpolant,
33532 
33533  interpolate_: function ( i1, t0, t, t1 ) {
33534 
33535  var result = this.resultBuffer,
33536  values = this.sampleValues,
33537  stride = this.valueSize,
33538 
33539  offset = i1 * stride,
33540 
33541  alpha = ( t - t0 ) / ( t1 - t0 );
33542 
33543  for ( var end = offset + stride; offset !== end; offset += 4 ) {
33544 
33545  Quaternion.slerpFlat( result, 0, values, offset - stride, values, offset, alpha );
33546 
33547  }
33548 
33549  return result;
33550 
33551  }
33552 
33553  } );
33554 
33564  function QuaternionKeyframeTrack( name, times, values, interpolation ) {
33565 
33566  KeyframeTrack.call( this, name, times, values, interpolation );
33567 
33568  }
33569 
33570  QuaternionKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
33571 
33572  constructor: QuaternionKeyframeTrack,
33573 
33574  ValueTypeName: 'quaternion',
33575 
33576  // ValueBufferType is inherited
33577 
33578  DefaultInterpolation: InterpolateLinear,
33579 
33580  InterpolantFactoryMethodLinear: function ( result ) {
33581 
33582  return new QuaternionLinearInterpolant( this.times, this.values, this.getValueSize(), result );
33583 
33584  },
33585 
33586  InterpolantFactoryMethodSmooth: undefined // not yet implemented
33587 
33588  } );
33589 
33600  function StringKeyframeTrack( name, times, values, interpolation ) {
33601 
33602  KeyframeTrack.call( this, name, times, values, interpolation );
33603 
33604  }
33605 
33606  StringKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
33607 
33608  constructor: StringKeyframeTrack,
33609 
33610  ValueTypeName: 'string',
33611  ValueBufferType: Array,
33612 
33613  DefaultInterpolation: InterpolateDiscrete,
33614 
33615  InterpolantFactoryMethodLinear: undefined,
33616 
33617  InterpolantFactoryMethodSmooth: undefined
33618 
33619  } );
33620 
33631  function VectorKeyframeTrack( name, times, values, interpolation ) {
33632 
33633  KeyframeTrack.call( this, name, times, values, interpolation );
33634 
33635  }
33636 
33637  VectorKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
33638 
33639  constructor: VectorKeyframeTrack,
33640 
33641  ValueTypeName: 'vector'
33642 
33643  // ValueBufferType is inherited
33644 
33645  // DefaultInterpolation is inherited
33646 
33647  } );
33648 
33657  function AnimationClip( name, duration, tracks ) {
33658 
33659  this.name = name;
33660  this.tracks = tracks;
33661  this.duration = ( duration !== undefined ) ? duration : - 1;
33662 
33663  this.uuid = _Math.generateUUID();
33664 
33665  // this means it should figure out its duration by scanning the tracks
33666  if ( this.duration < 0 ) {
33667 
33668  this.resetDuration();
33669 
33670  }
33671 
33672  }
33673 
33674  function getTrackTypeForValueTypeName( typeName ) {
33675 
33676  switch ( typeName.toLowerCase() ) {
33677 
33678  case 'scalar':
33679  case 'double':
33680  case 'float':
33681  case 'number':
33682  case 'integer':
33683 
33684  return NumberKeyframeTrack;
33685 
33686  case 'vector':
33687  case 'vector2':
33688  case 'vector3':
33689  case 'vector4':
33690 
33691  return VectorKeyframeTrack;
33692 
33693  case 'color':
33694 
33695  return ColorKeyframeTrack;
33696 
33697  case 'quaternion':
33698 
33699  return QuaternionKeyframeTrack;
33700 
33701  case 'bool':
33702  case 'boolean':
33703 
33704  return BooleanKeyframeTrack;
33705 
33706  case 'string':
33707 
33708  return StringKeyframeTrack;
33709 
33710  }
33711 
33712  throw new Error( 'THREE.KeyframeTrack: Unsupported typeName: ' + typeName );
33713 
33714  }
33715 
33716  function parseKeyframeTrack( json ) {
33717 
33718  if ( json.type === undefined ) {
33719 
33720  throw new Error( 'THREE.KeyframeTrack: track type undefined, can not parse' );
33721 
33722  }
33723 
33724  var trackType = getTrackTypeForValueTypeName( json.type );
33725 
33726  if ( json.times === undefined ) {
33727 
33728  var times = [], values = [];
33729 
33730  AnimationUtils.flattenJSON( json.keys, times, values, 'value' );
33731 
33732  json.times = times;
33733  json.values = values;
33734 
33735  }
33736 
33737  // derived classes can define a static parse method
33738  if ( trackType.parse !== undefined ) {
33739 
33740  return trackType.parse( json );
33741 
33742  } else {
33743 
33744  // by default, we assume a constructor compatible with the base
33745  return new trackType( json.name, json.times, json.values, json.interpolation );
33746 
33747  }
33748 
33749  }
33750 
33751  Object.assign( AnimationClip, {
33752 
33753  parse: function ( json ) {
33754 
33755  var tracks = [],
33756  jsonTracks = json.tracks,
33757  frameTime = 1.0 / ( json.fps || 1.0 );
33758 
33759  for ( var i = 0, n = jsonTracks.length; i !== n; ++ i ) {
33760 
33761  tracks.push( parseKeyframeTrack( jsonTracks[ i ] ).scale( frameTime ) );
33762 
33763  }
33764 
33765  return new AnimationClip( json.name, json.duration, tracks );
33766 
33767  },
33768 
33769  toJSON: function ( clip ) {
33770 
33771  var tracks = [],
33772  clipTracks = clip.tracks;
33773 
33774  var json = {
33775 
33776  'name': clip.name,
33777  'duration': clip.duration,
33778  'tracks': tracks,
33779  'uuid': clip.uuid
33780 
33781  };
33782 
33783  for ( var i = 0, n = clipTracks.length; i !== n; ++ i ) {
33784 
33785  tracks.push( KeyframeTrack.toJSON( clipTracks[ i ] ) );
33786 
33787  }
33788 
33789  return json;
33790 
33791  },
33792 
33793  CreateFromMorphTargetSequence: function ( name, morphTargetSequence, fps, noLoop ) {
33794 
33795  var numMorphTargets = morphTargetSequence.length;
33796  var tracks = [];
33797 
33798  for ( var i = 0; i < numMorphTargets; i ++ ) {
33799 
33800  var times = [];
33801  var values = [];
33802 
33803  times.push(
33804  ( i + numMorphTargets - 1 ) % numMorphTargets,
33805  i,
33806  ( i + 1 ) % numMorphTargets );
33807 
33808  values.push( 0, 1, 0 );
33809 
33810  var order = AnimationUtils.getKeyframeOrder( times );
33811  times = AnimationUtils.sortedArray( times, 1, order );
33812  values = AnimationUtils.sortedArray( values, 1, order );
33813 
33814  // if there is a key at the first frame, duplicate it as the
33815  // last frame as well for perfect loop.
33816  if ( ! noLoop && times[ 0 ] === 0 ) {
33817 
33818  times.push( numMorphTargets );
33819  values.push( values[ 0 ] );
33820 
33821  }
33822 
33823  tracks.push(
33824  new NumberKeyframeTrack(
33825  '.morphTargetInfluences[' + morphTargetSequence[ i ].name + ']',
33826  times, values
33827  ).scale( 1.0 / fps ) );
33828 
33829  }
33830 
33831  return new AnimationClip( name, - 1, tracks );
33832 
33833  },
33834 
33835  findByName: function ( objectOrClipArray, name ) {
33836 
33837  var clipArray = objectOrClipArray;
33838 
33839  if ( ! Array.isArray( objectOrClipArray ) ) {
33840 
33841  var o = objectOrClipArray;
33842  clipArray = o.geometry && o.geometry.animations || o.animations;
33843 
33844  }
33845 
33846  for ( var i = 0; i < clipArray.length; i ++ ) {
33847 
33848  if ( clipArray[ i ].name === name ) {
33849 
33850  return clipArray[ i ];
33851 
33852  }
33853 
33854  }
33855 
33856  return null;
33857 
33858  },
33859 
33860  CreateClipsFromMorphTargetSequences: function ( morphTargets, fps, noLoop ) {
33861 
33862  var animationToMorphTargets = {};
33863 
33864  // tested with https://regex101.com/ on trick sequences
33865  // such flamingo_flyA_003, flamingo_run1_003, crdeath0059
33866  var pattern = /^([\w-]*?)([\d]+)$/;
33867 
33868  // sort morph target names into animation groups based
33869  // patterns like Walk_001, Walk_002, Run_001, Run_002
33870  for ( var i = 0, il = morphTargets.length; i < il; i ++ ) {
33871 
33872  var morphTarget = morphTargets[ i ];
33873  var parts = morphTarget.name.match( pattern );
33874 
33875  if ( parts && parts.length > 1 ) {
33876 
33877  var name = parts[ 1 ];
33878 
33879  var animationMorphTargets = animationToMorphTargets[ name ];
33880  if ( ! animationMorphTargets ) {
33881 
33882  animationToMorphTargets[ name ] = animationMorphTargets = [];
33883 
33884  }
33885 
33886  animationMorphTargets.push( morphTarget );
33887 
33888  }
33889 
33890  }
33891 
33892  var clips = [];
33893 
33894  for ( var name in animationToMorphTargets ) {
33895 
33896  clips.push( AnimationClip.CreateFromMorphTargetSequence( name, animationToMorphTargets[ name ], fps, noLoop ) );
33897 
33898  }
33899 
33900  return clips;
33901 
33902  },
33903 
33904  // parse the animation.hierarchy format
33905  parseAnimation: function ( animation, bones ) {
33906 
33907  if ( ! animation ) {
33908 
33909  console.error( 'THREE.AnimationClip: No animation in JSONLoader data.' );
33910  return null;
33911 
33912  }
33913 
33914  var addNonemptyTrack = function ( trackType, trackName, animationKeys, propertyName, destTracks ) {
33915 
33916  // only return track if there are actually keys.
33917  if ( animationKeys.length !== 0 ) {
33918 
33919  var times = [];
33920  var values = [];
33921 
33922  AnimationUtils.flattenJSON( animationKeys, times, values, propertyName );
33923 
33924  // empty keys are filtered out, so check again
33925  if ( times.length !== 0 ) {
33926 
33927  destTracks.push( new trackType( trackName, times, values ) );
33928 
33929  }
33930 
33931  }
33932 
33933  };
33934 
33935  var tracks = [];
33936 
33937  var clipName = animation.name || 'default';
33938  // automatic length determination in AnimationClip.
33939  var duration = animation.length || - 1;
33940  var fps = animation.fps || 30;
33941 
33942  var hierarchyTracks = animation.hierarchy || [];
33943 
33944  for ( var h = 0; h < hierarchyTracks.length; h ++ ) {
33945 
33946  var animationKeys = hierarchyTracks[ h ].keys;
33947 
33948  // skip empty tracks
33949  if ( ! animationKeys || animationKeys.length === 0 ) continue;
33950 
33951  // process morph targets
33952  if ( animationKeys[ 0 ].morphTargets ) {
33953 
33954  // figure out all morph targets used in this track
33955  var morphTargetNames = {};
33956 
33957  for ( var k = 0; k < animationKeys.length; k ++ ) {
33958 
33959  if ( animationKeys[ k ].morphTargets ) {
33960 
33961  for ( var m = 0; m < animationKeys[ k ].morphTargets.length; m ++ ) {
33962 
33963  morphTargetNames[ animationKeys[ k ].morphTargets[ m ] ] = - 1;
33964 
33965  }
33966 
33967  }
33968 
33969  }
33970 
33971  // create a track for each morph target with all zero
33972  // morphTargetInfluences except for the keys in which
33973  // the morphTarget is named.
33974  for ( var morphTargetName in morphTargetNames ) {
33975 
33976  var times = [];
33977  var values = [];
33978 
33979  for ( var m = 0; m !== animationKeys[ k ].morphTargets.length; ++ m ) {
33980 
33981  var animationKey = animationKeys[ k ];
33982 
33983  times.push( animationKey.time );
33984  values.push( ( animationKey.morphTarget === morphTargetName ) ? 1 : 0 );
33985 
33986  }
33987 
33988  tracks.push( new NumberKeyframeTrack( '.morphTargetInfluence[' + morphTargetName + ']', times, values ) );
33989 
33990  }
33991 
33992  duration = morphTargetNames.length * ( fps || 1.0 );
33993 
33994  } else {
33995 
33996  // ...assume skeletal animation
33997 
33998  var boneName = '.bones[' + bones[ h ].name + ']';
33999 
34000  addNonemptyTrack(
34001  VectorKeyframeTrack, boneName + '.position',
34002  animationKeys, 'pos', tracks );
34003 
34004  addNonemptyTrack(
34005  QuaternionKeyframeTrack, boneName + '.quaternion',
34006  animationKeys, 'rot', tracks );
34007 
34008  addNonemptyTrack(
34009  VectorKeyframeTrack, boneName + '.scale',
34010  animationKeys, 'scl', tracks );
34011 
34012  }
34013 
34014  }
34015 
34016  if ( tracks.length === 0 ) {
34017 
34018  return null;
34019 
34020  }
34021 
34022  var clip = new AnimationClip( clipName, duration, tracks );
34023 
34024  return clip;
34025 
34026  }
34027 
34028  } );
34029 
34030  Object.assign( AnimationClip.prototype, {
34031 
34032  resetDuration: function () {
34033 
34034  var tracks = this.tracks, duration = 0;
34035 
34036  for ( var i = 0, n = tracks.length; i !== n; ++ i ) {
34037 
34038  var track = this.tracks[ i ];
34039 
34040  duration = Math.max( duration, track.times[ track.times.length - 1 ] );
34041 
34042  }
34043 
34044  this.duration = duration;
34045 
34046  return this;
34047 
34048  },
34049 
34050  trim: function () {
34051 
34052  for ( var i = 0; i < this.tracks.length; i ++ ) {
34053 
34054  this.tracks[ i ].trim( 0, this.duration );
34055 
34056  }
34057 
34058  return this;
34059 
34060  },
34061 
34062  validate: function () {
34063 
34064  var valid = true;
34065 
34066  for ( var i = 0; i < this.tracks.length; i ++ ) {
34067 
34068  valid = valid && this.tracks[ i ].validate();
34069 
34070  }
34071 
34072  return valid;
34073 
34074  },
34075 
34076  optimize: function () {
34077 
34078  for ( var i = 0; i < this.tracks.length; i ++ ) {
34079 
34080  this.tracks[ i ].optimize();
34081 
34082  }
34083 
34084  return this;
34085 
34086  },
34087 
34088 
34089  clone: function () {
34090 
34091  var tracks = [];
34092 
34093  for ( var i = 0; i < this.tracks.length; i ++ ) {
34094 
34095  tracks.push( this.tracks[ i ].clone() );
34096 
34097  }
34098 
34099  return new AnimationClip( this.name, this.duration, tracks );
34100 
34101  }
34102 
34103  } );
34104 
34109  var Cache = {
34110 
34111  enabled: false,
34112 
34113  files: {},
34114 
34115  add: function ( key, file ) {
34116 
34117  if ( this.enabled === false ) return;
34118 
34119  // console.log( 'THREE.Cache', 'Adding key:', key );
34120 
34121  this.files[ key ] = file;
34122 
34123  },
34124 
34125  get: function ( key ) {
34126 
34127  if ( this.enabled === false ) return;
34128 
34129  // console.log( 'THREE.Cache', 'Checking key:', key );
34130 
34131  return this.files[ key ];
34132 
34133  },
34134 
34135  remove: function ( key ) {
34136 
34137  delete this.files[ key ];
34138 
34139  },
34140 
34141  clear: function () {
34142 
34143  this.files = {};
34144 
34145  }
34146 
34147  };
34148 
34153  function LoadingManager( onLoad, onProgress, onError ) {
34154 
34155  var scope = this;
34156 
34157  var isLoading = false;
34158  var itemsLoaded = 0;
34159  var itemsTotal = 0;
34160  var urlModifier = undefined;
34161 
34162  // Refer to #5689 for the reason why we don't set .onStart
34163  // in the constructor
34164 
34165  this.onStart = undefined;
34166  this.onLoad = onLoad;
34167  this.onProgress = onProgress;
34168  this.onError = onError;
34169 
34170  this.itemStart = function ( url ) {
34171 
34172  itemsTotal ++;
34173 
34174  if ( isLoading === false ) {
34175 
34176  if ( scope.onStart !== undefined ) {
34177 
34178  scope.onStart( url, itemsLoaded, itemsTotal );
34179 
34180  }
34181 
34182  }
34183 
34184  isLoading = true;
34185 
34186  };
34187 
34188  this.itemEnd = function ( url ) {
34189 
34190  itemsLoaded ++;
34191 
34192  if ( scope.onProgress !== undefined ) {
34193 
34194  scope.onProgress( url, itemsLoaded, itemsTotal );
34195 
34196  }
34197 
34198  if ( itemsLoaded === itemsTotal ) {
34199 
34200  isLoading = false;
34201 
34202  if ( scope.onLoad !== undefined ) {
34203 
34204  scope.onLoad();
34205 
34206  }
34207 
34208  }
34209 
34210  };
34211 
34212  this.itemError = function ( url ) {
34213 
34214  if ( scope.onError !== undefined ) {
34215 
34216  scope.onError( url );
34217 
34218  }
34219 
34220  };
34221 
34222  this.resolveURL = function ( url ) {
34223 
34224  if ( urlModifier ) {
34225 
34226  return urlModifier( url );
34227 
34228  }
34229 
34230  return url;
34231 
34232  };
34233 
34234  this.setURLModifier = function ( transform ) {
34235 
34236  urlModifier = transform;
34237  return this;
34238 
34239  };
34240 
34241  }
34242 
34243  var DefaultLoadingManager = new LoadingManager();
34244 
34249  var loading = {};
34250 
34251  function FileLoader( manager ) {
34252 
34253  this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
34254 
34255  }
34256 
34257  Object.assign( FileLoader.prototype, {
34258 
34259  load: function ( url, onLoad, onProgress, onError ) {
34260 
34261  if ( url === undefined ) url = '';
34262 
34263  if ( this.path !== undefined ) url = this.path + url;
34264 
34265  url = this.manager.resolveURL( url );
34266 
34267  var scope = this;
34268 
34269  var cached = Cache.get( url );
34270 
34271  if ( cached !== undefined ) {
34272 
34273  scope.manager.itemStart( url );
34274 
34275  setTimeout( function () {
34276 
34277  if ( onLoad ) onLoad( cached );
34278 
34279  scope.manager.itemEnd( url );
34280 
34281  }, 0 );
34282 
34283  return cached;
34284 
34285  }
34286 
34287  // Check if request is duplicate
34288 
34289  if ( loading[ url ] !== undefined ) {
34290 
34291  loading[ url ].push( {
34292 
34293  onLoad: onLoad,
34294  onProgress: onProgress,
34295  onError: onError
34296 
34297  } );
34298 
34299  return;
34300 
34301  }
34302 
34303  // Check for data: URI
34304  var dataUriRegex = /^data:(.*?)(;base64)?,(.*)$/;
34305  var dataUriRegexResult = url.match( dataUriRegex );
34306 
34307  // Safari can not handle Data URIs through XMLHttpRequest so process manually
34308  if ( dataUriRegexResult ) {
34309 
34310  var mimeType = dataUriRegexResult[ 1 ];
34311  var isBase64 = !! dataUriRegexResult[ 2 ];
34312  var data = dataUriRegexResult[ 3 ];
34313 
34314  data = decodeURIComponent( data );
34315 
34316  if ( isBase64 ) data = atob( data );
34317 
34318  try {
34319 
34320  var response;
34321  var responseType = ( this.responseType || '' ).toLowerCase();
34322 
34323  switch ( responseType ) {
34324 
34325  case 'arraybuffer':
34326  case 'blob':
34327 
34328  var view = new Uint8Array( data.length );
34329 
34330  for ( var i = 0; i < data.length; i ++ ) {
34331 
34332  view[ i ] = data.charCodeAt( i );
34333 
34334  }
34335 
34336  if ( responseType === 'blob' ) {
34337 
34338  response = new Blob( [ view.buffer ], { type: mimeType } );
34339 
34340  } else {
34341 
34342  response = view.buffer;
34343 
34344  }
34345 
34346  break;
34347 
34348  case 'document':
34349 
34350  var parser = new DOMParser();
34351  response = parser.parseFromString( data, mimeType );
34352 
34353  break;
34354 
34355  case 'json':
34356 
34357  response = JSON.parse( data );
34358 
34359  break;
34360 
34361  default: // 'text' or other
34362 
34363  response = data;
34364 
34365  break;
34366 
34367  }
34368 
34369  // Wait for next browser tick like standard XMLHttpRequest event dispatching does
34370  setTimeout( function () {
34371 
34372  if ( onLoad ) onLoad( response );
34373 
34374  scope.manager.itemEnd( url );
34375 
34376  }, 0 );
34377 
34378  } catch ( error ) {
34379 
34380  // Wait for next browser tick like standard XMLHttpRequest event dispatching does
34381  setTimeout( function () {
34382 
34383  if ( onError ) onError( error );
34384 
34385  scope.manager.itemError( url );
34386  scope.manager.itemEnd( url );
34387 
34388  }, 0 );
34389 
34390  }
34391 
34392  } else {
34393 
34394  // Initialise array for duplicate requests
34395 
34396  loading[ url ] = [];
34397 
34398  loading[ url ].push( {
34399 
34400  onLoad: onLoad,
34401  onProgress: onProgress,
34402  onError: onError
34403 
34404  } );
34405 
34406  var request = new XMLHttpRequest();
34407 
34408  request.open( 'GET', url, true );
34409 
34410  request.addEventListener( 'load', function ( event ) {
34411 
34412  var response = this.response;
34413 
34414  Cache.add( url, response );
34415 
34416  var callbacks = loading[ url ];
34417 
34418  delete loading[ url ];
34419 
34420  if ( this.status === 200 || this.status === 0 ) {
34421 
34422  // Some browsers return HTTP Status 0 when using non-http protocol
34423  // e.g. 'file://' or 'data://'. Handle as success.
34424 
34425  if ( this.status === 0 ) console.warn( 'THREE.FileLoader: HTTP Status 0 received.' );
34426 
34427  for ( var i = 0, il = callbacks.length; i < il; i ++ ) {
34428 
34429  var callback = callbacks[ i ];
34430  if ( callback.onLoad ) callback.onLoad( response );
34431 
34432  }
34433 
34434  scope.manager.itemEnd( url );
34435 
34436  } else {
34437 
34438  for ( var i = 0, il = callbacks.length; i < il; i ++ ) {
34439 
34440  var callback = callbacks[ i ];
34441  if ( callback.onError ) callback.onError( event );
34442 
34443  }
34444 
34445  scope.manager.itemError( url );
34446  scope.manager.itemEnd( url );
34447 
34448  }
34449 
34450  }, false );
34451 
34452  request.addEventListener( 'progress', function ( event ) {
34453 
34454  var callbacks = loading[ url ];
34455 
34456  for ( var i = 0, il = callbacks.length; i < il; i ++ ) {
34457 
34458  var callback = callbacks[ i ];
34459  if ( callback.onProgress ) callback.onProgress( event );
34460 
34461  }
34462 
34463  }, false );
34464 
34465  request.addEventListener( 'error', function ( event ) {
34466 
34467  var callbacks = loading[ url ];
34468 
34469  delete loading[ url ];
34470 
34471  for ( var i = 0, il = callbacks.length; i < il; i ++ ) {
34472 
34473  var callback = callbacks[ i ];
34474  if ( callback.onError ) callback.onError( event );
34475 
34476  }
34477 
34478  scope.manager.itemError( url );
34479  scope.manager.itemEnd( url );
34480 
34481  }, false );
34482 
34483  request.addEventListener( 'abort', function ( event ) {
34484 
34485  var callbacks = loading[ url ];
34486 
34487  delete loading[ url ];
34488 
34489  for ( var i = 0, il = callbacks.length; i < il; i ++ ) {
34490 
34491  var callback = callbacks[ i ];
34492  if ( callback.onError ) callback.onError( event );
34493 
34494  }
34495 
34496  scope.manager.itemError( url );
34497  scope.manager.itemEnd( url );
34498 
34499  }, false );
34500 
34501  if ( this.responseType !== undefined ) request.responseType = this.responseType;
34502  if ( this.withCredentials !== undefined ) request.withCredentials = this.withCredentials;
34503 
34504  if ( request.overrideMimeType ) request.overrideMimeType( this.mimeType !== undefined ? this.mimeType : 'text/plain' );
34505 
34506  for ( var header in this.requestHeader ) {
34507 
34508  request.setRequestHeader( header, this.requestHeader[ header ] );
34509 
34510  }
34511 
34512  request.send( null );
34513 
34514  }
34515 
34516  scope.manager.itemStart( url );
34517 
34518  return request;
34519 
34520  },
34521 
34522  setPath: function ( value ) {
34523 
34524  this.path = value;
34525  return this;
34526 
34527  },
34528 
34529  setResponseType: function ( value ) {
34530 
34531  this.responseType = value;
34532  return this;
34533 
34534  },
34535 
34536  setWithCredentials: function ( value ) {
34537 
34538  this.withCredentials = value;
34539  return this;
34540 
34541  },
34542 
34543  setMimeType: function ( value ) {
34544 
34545  this.mimeType = value;
34546  return this;
34547 
34548  },
34549 
34550  setRequestHeader: function ( value ) {
34551 
34552  this.requestHeader = value;
34553  return this;
34554 
34555  }
34556 
34557  } );
34558 
34563  function AnimationLoader( manager ) {
34564 
34565  this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
34566 
34567  }
34568 
34569  Object.assign( AnimationLoader.prototype, {
34570 
34571  load: function ( url, onLoad, onProgress, onError ) {
34572 
34573  var scope = this;
34574 
34575  var loader = new FileLoader( scope.manager );
34576  loader.setPath( scope.path );
34577  loader.load( url, function ( text ) {
34578 
34579  onLoad( scope.parse( JSON.parse( text ) ) );
34580 
34581  }, onProgress, onError );
34582 
34583  },
34584 
34585  parse: function ( json, onLoad ) {
34586 
34587  var animations = [];
34588 
34589  for ( var i = 0; i < json.length; i ++ ) {
34590 
34591  var clip = AnimationClip.parse( json[ i ] );
34592 
34593  animations.push( clip );
34594 
34595  }
34596 
34597  onLoad( animations );
34598 
34599  },
34600 
34601  setPath: function ( value ) {
34602 
34603  this.path = value;
34604  return this;
34605 
34606  }
34607 
34608  } );
34609 
34616  function CompressedTextureLoader( manager ) {
34617 
34618  this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
34619 
34620  // override in sub classes
34621  this._parser = null;
34622 
34623  }
34624 
34625  Object.assign( CompressedTextureLoader.prototype, {
34626 
34627  load: function ( url, onLoad, onProgress, onError ) {
34628 
34629  var scope = this;
34630 
34631  var images = [];
34632 
34633  var texture = new CompressedTexture();
34634  texture.image = images;
34635 
34636  var loader = new FileLoader( this.manager );
34637  loader.setPath( this.path );
34638  loader.setResponseType( 'arraybuffer' );
34639 
34640  function loadTexture( i ) {
34641 
34642  loader.load( url[ i ], function ( buffer ) {
34643 
34644  var texDatas = scope._parser( buffer, true );
34645 
34646  images[ i ] = {
34647  width: texDatas.width,
34648  height: texDatas.height,
34649  format: texDatas.format,
34650  mipmaps: texDatas.mipmaps
34651  };
34652 
34653  loaded += 1;
34654 
34655  if ( loaded === 6 ) {
34656 
34657  if ( texDatas.mipmapCount === 1 )
34658  texture.minFilter = LinearFilter;
34659 
34660  texture.format = texDatas.format;
34661  texture.needsUpdate = true;
34662 
34663  if ( onLoad ) onLoad( texture );
34664 
34665  }
34666 
34667  }, onProgress, onError );
34668 
34669  }
34670 
34671  if ( Array.isArray( url ) ) {
34672 
34673  var loaded = 0;
34674 
34675  for ( var i = 0, il = url.length; i < il; ++ i ) {
34676 
34677  loadTexture( i );
34678 
34679  }
34680 
34681  } else {
34682 
34683  // compressed cubemap texture stored in a single DDS file
34684 
34685  loader.load( url, function ( buffer ) {
34686 
34687  var texDatas = scope._parser( buffer, true );
34688 
34689  if ( texDatas.isCubemap ) {
34690 
34691  var faces = texDatas.mipmaps.length / texDatas.mipmapCount;
34692 
34693  for ( var f = 0; f < faces; f ++ ) {
34694 
34695  images[ f ] = { mipmaps: [] };
34696 
34697  for ( var i = 0; i < texDatas.mipmapCount; i ++ ) {
34698 
34699  images[ f ].mipmaps.push( texDatas.mipmaps[ f * texDatas.mipmapCount + i ] );
34700  images[ f ].format = texDatas.format;
34701  images[ f ].width = texDatas.width;
34702  images[ f ].height = texDatas.height;
34703 
34704  }
34705 
34706  }
34707 
34708  } else {
34709 
34710  texture.image.width = texDatas.width;
34711  texture.image.height = texDatas.height;
34712  texture.mipmaps = texDatas.mipmaps;
34713 
34714  }
34715 
34716  if ( texDatas.mipmapCount === 1 ) {
34717 
34718  texture.minFilter = LinearFilter;
34719 
34720  }
34721 
34722  texture.format = texDatas.format;
34723  texture.needsUpdate = true;
34724 
34725  if ( onLoad ) onLoad( texture );
34726 
34727  }, onProgress, onError );
34728 
34729  }
34730 
34731  return texture;
34732 
34733  },
34734 
34735  setPath: function ( value ) {
34736 
34737  this.path = value;
34738  return this;
34739 
34740  }
34741 
34742  } );
34743 
34750  function DataTextureLoader( manager ) {
34751 
34752  this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
34753 
34754  // override in sub classes
34755  this._parser = null;
34756 
34757  }
34758 
34759  Object.assign( DataTextureLoader.prototype, {
34760 
34761  load: function ( url, onLoad, onProgress, onError ) {
34762 
34763  var scope = this;
34764 
34765  var texture = new DataTexture();
34766 
34767  var loader = new FileLoader( this.manager );
34768  loader.setResponseType( 'arraybuffer' );
34769  loader.setPath( this.path );
34770  loader.load( url, function ( buffer ) {
34771 
34772  var texData = scope._parser( buffer );
34773 
34774  if ( ! texData ) return;
34775 
34776  if ( texData.image !== undefined ) {
34777 
34778  texture.image = texData.image;
34779 
34780  } else if ( texData.data !== undefined ) {
34781 
34782  texture.image.width = texData.width;
34783  texture.image.height = texData.height;
34784  texture.image.data = texData.data;
34785 
34786  }
34787 
34788  texture.wrapS = texData.wrapS !== undefined ? texData.wrapS : ClampToEdgeWrapping;
34789  texture.wrapT = texData.wrapT !== undefined ? texData.wrapT : ClampToEdgeWrapping;
34790 
34791  texture.magFilter = texData.magFilter !== undefined ? texData.magFilter : LinearFilter;
34792  texture.minFilter = texData.minFilter !== undefined ? texData.minFilter : LinearMipMapLinearFilter;
34793 
34794  texture.anisotropy = texData.anisotropy !== undefined ? texData.anisotropy : 1;
34795 
34796  if ( texData.format !== undefined ) {
34797 
34798  texture.format = texData.format;
34799 
34800  }
34801  if ( texData.type !== undefined ) {
34802 
34803  texture.type = texData.type;
34804 
34805  }
34806 
34807  if ( texData.mipmaps !== undefined ) {
34808 
34809  texture.mipmaps = texData.mipmaps;
34810 
34811  }
34812 
34813  if ( texData.mipmapCount === 1 ) {
34814 
34815  texture.minFilter = LinearFilter;
34816 
34817  }
34818 
34819  texture.needsUpdate = true;
34820 
34821  if ( onLoad ) onLoad( texture, texData );
34822 
34823  }, onProgress, onError );
34824 
34825 
34826  return texture;
34827 
34828  },
34829 
34830  setPath: function ( value ) {
34831 
34832  this.path = value;
34833  return this;
34834 
34835  }
34836 
34837  } );
34838 
34844  function ImageLoader( manager ) {
34845 
34846  this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
34847 
34848  }
34849 
34850  Object.assign( ImageLoader.prototype, {
34851 
34852  crossOrigin: 'anonymous',
34853 
34854  load: function ( url, onLoad, onProgress, onError ) {
34855 
34856  if ( url === undefined ) url = '';
34857 
34858  if ( this.path !== undefined ) url = this.path + url;
34859 
34860  url = this.manager.resolveURL( url );
34861 
34862  var scope = this;
34863 
34864  var cached = Cache.get( url );
34865 
34866  if ( cached !== undefined ) {
34867 
34868  scope.manager.itemStart( url );
34869 
34870  setTimeout( function () {
34871 
34872  if ( onLoad ) onLoad( cached );
34873 
34874  scope.manager.itemEnd( url );
34875 
34876  }, 0 );
34877 
34878  return cached;
34879 
34880  }
34881 
34882  var image = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'img' );
34883 
34884  function onImageLoad() {
34885 
34886  image.removeEventListener( 'load', onImageLoad, false );
34887  image.removeEventListener( 'error', onImageError, false );
34888 
34889  Cache.add( url, this );
34890 
34891  if ( onLoad ) onLoad( this );
34892 
34893  scope.manager.itemEnd( url );
34894 
34895  }
34896 
34897  function onImageError( event ) {
34898 
34899  image.removeEventListener( 'load', onImageLoad, false );
34900  image.removeEventListener( 'error', onImageError, false );
34901 
34902  if ( onError ) onError( event );
34903 
34904  scope.manager.itemError( url );
34905  scope.manager.itemEnd( url );
34906 
34907  }
34908 
34909  image.addEventListener( 'load', onImageLoad, false );
34910  image.addEventListener( 'error', onImageError, false );
34911 
34912  if ( url.substr( 0, 5 ) !== 'data:' ) {
34913 
34914  if ( this.crossOrigin !== undefined ) image.crossOrigin = this.crossOrigin;
34915 
34916  }
34917 
34918  scope.manager.itemStart( url );
34919 
34920  image.src = url;
34921 
34922  return image;
34923 
34924  },
34925 
34926  setCrossOrigin: function ( value ) {
34927 
34928  this.crossOrigin = value;
34929  return this;
34930 
34931  },
34932 
34933  setPath: function ( value ) {
34934 
34935  this.path = value;
34936  return this;
34937 
34938  }
34939 
34940  } );
34941 
34947  function CubeTextureLoader( manager ) {
34948 
34949  this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
34950 
34951  }
34952 
34953  Object.assign( CubeTextureLoader.prototype, {
34954 
34955  crossOrigin: 'anonymous',
34956 
34957  load: function ( urls, onLoad, onProgress, onError ) {
34958 
34959  var texture = new CubeTexture();
34960 
34961  var loader = new ImageLoader( this.manager );
34962  loader.setCrossOrigin( this.crossOrigin );
34963  loader.setPath( this.path );
34964 
34965  var loaded = 0;
34966 
34967  function loadTexture( i ) {
34968 
34969  loader.load( urls[ i ], function ( image ) {
34970 
34971  texture.images[ i ] = image;
34972 
34973  loaded ++;
34974 
34975  if ( loaded === 6 ) {
34976 
34977  texture.needsUpdate = true;
34978 
34979  if ( onLoad ) onLoad( texture );
34980 
34981  }
34982 
34983  }, undefined, onError );
34984 
34985  }
34986 
34987  for ( var i = 0; i < urls.length; ++ i ) {
34988 
34989  loadTexture( i );
34990 
34991  }
34992 
34993  return texture;
34994 
34995  },
34996 
34997  setCrossOrigin: function ( value ) {
34998 
34999  this.crossOrigin = value;
35000  return this;
35001 
35002  },
35003 
35004  setPath: function ( value ) {
35005 
35006  this.path = value;
35007  return this;
35008 
35009  }
35010 
35011  } );
35012 
35018  function TextureLoader( manager ) {
35019 
35020  this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
35021 
35022  }
35023 
35024  Object.assign( TextureLoader.prototype, {
35025 
35026  crossOrigin: 'anonymous',
35027 
35028  load: function ( url, onLoad, onProgress, onError ) {
35029 
35030  var texture = new Texture();
35031 
35032  var loader = new ImageLoader( this.manager );
35033  loader.setCrossOrigin( this.crossOrigin );
35034  loader.setPath( this.path );
35035 
35036  loader.load( url, function ( image ) {
35037 
35038  texture.image = image;
35039 
35040  // JPEGs can't have an alpha channel, so memory can be saved by storing them as RGB.
35041  var isJPEG = url.search( /\.jpe?g($|\?)/i ) > 0 || url.search( /^data\:image\/jpeg/ ) === 0;
35042 
35043  texture.format = isJPEG ? RGBFormat : RGBAFormat;
35044  texture.needsUpdate = true;
35045 
35046  if ( onLoad !== undefined ) {
35047 
35048  onLoad( texture );
35049 
35050  }
35051 
35052  }, onProgress, onError );
35053 
35054  return texture;
35055 
35056  },
35057 
35058  setCrossOrigin: function ( value ) {
35059 
35060  this.crossOrigin = value;
35061  return this;
35062 
35063  },
35064 
35065  setPath: function ( value ) {
35066 
35067  this.path = value;
35068  return this;
35069 
35070  }
35071 
35072  } );
35073 
35105  /**************************************************************
35106  * Abstract Curve base class
35107  **************************************************************/
35108 
35109  function Curve() {
35110 
35111  this.type = 'Curve';
35112 
35113  this.arcLengthDivisions = 200;
35114 
35115  }
35116 
35117  Object.assign( Curve.prototype, {
35118 
35119  // Virtual base class method to overwrite and implement in subclasses
35120  // - t [0 .. 1]
35121 
35122  getPoint: function ( /* t, optionalTarget */ ) {
35123 
35124  console.warn( 'THREE.Curve: .getPoint() not implemented.' );
35125  return null;
35126 
35127  },
35128 
35129  // Get point at relative position in curve according to arc length
35130  // - u [0 .. 1]
35131 
35132  getPointAt: function ( u, optionalTarget ) {
35133 
35134  var t = this.getUtoTmapping( u );
35135  return this.getPoint( t, optionalTarget );
35136 
35137  },
35138 
35139  // Get sequence of points using getPoint( t )
35140 
35141  getPoints: function ( divisions ) {
35142 
35143  if ( divisions === undefined ) divisions = 5;
35144 
35145  var points = [];
35146 
35147  for ( var d = 0; d <= divisions; d ++ ) {
35148 
35149  points.push( this.getPoint( d / divisions ) );
35150 
35151  }
35152 
35153  return points;
35154 
35155  },
35156 
35157  // Get sequence of points using getPointAt( u )
35158 
35159  getSpacedPoints: function ( divisions ) {
35160 
35161  if ( divisions === undefined ) divisions = 5;
35162 
35163  var points = [];
35164 
35165  for ( var d = 0; d <= divisions; d ++ ) {
35166 
35167  points.push( this.getPointAt( d / divisions ) );
35168 
35169  }
35170 
35171  return points;
35172 
35173  },
35174 
35175  // Get total curve arc length
35176 
35177  getLength: function () {
35178 
35179  var lengths = this.getLengths();
35180  return lengths[ lengths.length - 1 ];
35181 
35182  },
35183 
35184  // Get list of cumulative segment lengths
35185 
35186  getLengths: function ( divisions ) {
35187 
35188  if ( divisions === undefined ) divisions = this.arcLengthDivisions;
35189 
35190  if ( this.cacheArcLengths &&
35191  ( this.cacheArcLengths.length === divisions + 1 ) &&
35192  ! this.needsUpdate ) {
35193 
35194  return this.cacheArcLengths;
35195 
35196  }
35197 
35198  this.needsUpdate = false;
35199 
35200  var cache = [];
35201  var current, last = this.getPoint( 0 );
35202  var p, sum = 0;
35203 
35204  cache.push( 0 );
35205 
35206  for ( p = 1; p <= divisions; p ++ ) {
35207 
35208  current = this.getPoint( p / divisions );
35209  sum += current.distanceTo( last );
35210  cache.push( sum );
35211  last = current;
35212 
35213  }
35214 
35215  this.cacheArcLengths = cache;
35216 
35217  return cache; // { sums: cache, sum: sum }; Sum is in the last element.
35218 
35219  },
35220 
35221  updateArcLengths: function () {
35222 
35223  this.needsUpdate = true;
35224  this.getLengths();
35225 
35226  },
35227 
35228  // Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equidistant
35229 
35230  getUtoTmapping: function ( u, distance ) {
35231 
35232  var arcLengths = this.getLengths();
35233 
35234  var i = 0, il = arcLengths.length;
35235 
35236  var targetArcLength; // The targeted u distance value to get
35237 
35238  if ( distance ) {
35239 
35240  targetArcLength = distance;
35241 
35242  } else {
35243 
35244  targetArcLength = u * arcLengths[ il - 1 ];
35245 
35246  }
35247 
35248  // binary search for the index with largest value smaller than target u distance
35249 
35250  var low = 0, high = il - 1, comparison;
35251 
35252  while ( low <= high ) {
35253 
35254  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
35255 
35256  comparison = arcLengths[ i ] - targetArcLength;
35257 
35258  if ( comparison < 0 ) {
35259 
35260  low = i + 1;
35261 
35262  } else if ( comparison > 0 ) {
35263 
35264  high = i - 1;
35265 
35266  } else {
35267 
35268  high = i;
35269  break;
35270 
35271  // DONE
35272 
35273  }
35274 
35275  }
35276 
35277  i = high;
35278 
35279  if ( arcLengths[ i ] === targetArcLength ) {
35280 
35281  return i / ( il - 1 );
35282 
35283  }
35284 
35285  // we could get finer grain at lengths, or use simple interpolation between two points
35286 
35287  var lengthBefore = arcLengths[ i ];
35288  var lengthAfter = arcLengths[ i + 1 ];
35289 
35290  var segmentLength = lengthAfter - lengthBefore;
35291 
35292  // determine where we are between the 'before' and 'after' points
35293 
35294  var segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength;
35295 
35296  // add that fractional amount to t
35297 
35298  var t = ( i + segmentFraction ) / ( il - 1 );
35299 
35300  return t;
35301 
35302  },
35303 
35304  // Returns a unit vector tangent at t
35305  // In case any sub curve does not implement its tangent derivation,
35306  // 2 points a small delta apart will be used to find its gradient
35307  // which seems to give a reasonable approximation
35308 
35309  getTangent: function ( t ) {
35310 
35311  var delta = 0.0001;
35312  var t1 = t - delta;
35313  var t2 = t + delta;
35314 
35315  // Capping in case of danger
35316 
35317  if ( t1 < 0 ) t1 = 0;
35318  if ( t2 > 1 ) t2 = 1;
35319 
35320  var pt1 = this.getPoint( t1 );
35321  var pt2 = this.getPoint( t2 );
35322 
35323  var vec = pt2.clone().sub( pt1 );
35324  return vec.normalize();
35325 
35326  },
35327 
35328  getTangentAt: function ( u ) {
35329 
35330  var t = this.getUtoTmapping( u );
35331  return this.getTangent( t );
35332 
35333  },
35334 
35335  computeFrenetFrames: function ( segments, closed ) {
35336 
35337  // see http://www.cs.indiana.edu/pub/techreports/TR425.pdf
35338 
35339  var normal = new Vector3();
35340 
35341  var tangents = [];
35342  var normals = [];
35343  var binormals = [];
35344 
35345  var vec = new Vector3();
35346  var mat = new Matrix4();
35347 
35348  var i, u, theta;
35349 
35350  // compute the tangent vectors for each segment on the curve
35351 
35352  for ( i = 0; i <= segments; i ++ ) {
35353 
35354  u = i / segments;
35355 
35356  tangents[ i ] = this.getTangentAt( u );
35357  tangents[ i ].normalize();
35358 
35359  }
35360 
35361  // select an initial normal vector perpendicular to the first tangent vector,
35362  // and in the direction of the minimum tangent xyz component
35363 
35364  normals[ 0 ] = new Vector3();
35365  binormals[ 0 ] = new Vector3();
35366  var min = Number.MAX_VALUE;
35367  var tx = Math.abs( tangents[ 0 ].x );
35368  var ty = Math.abs( tangents[ 0 ].y );
35369  var tz = Math.abs( tangents[ 0 ].z );
35370 
35371  if ( tx <= min ) {
35372 
35373  min = tx;
35374  normal.set( 1, 0, 0 );
35375 
35376  }
35377 
35378  if ( ty <= min ) {
35379 
35380  min = ty;
35381  normal.set( 0, 1, 0 );
35382 
35383  }
35384 
35385  if ( tz <= min ) {
35386 
35387  normal.set( 0, 0, 1 );
35388 
35389  }
35390 
35391  vec.crossVectors( tangents[ 0 ], normal ).normalize();
35392 
35393  normals[ 0 ].crossVectors( tangents[ 0 ], vec );
35394  binormals[ 0 ].crossVectors( tangents[ 0 ], normals[ 0 ] );
35395 
35396 
35397  // compute the slowly-varying normal and binormal vectors for each segment on the curve
35398 
35399  for ( i = 1; i <= segments; i ++ ) {
35400 
35401  normals[ i ] = normals[ i - 1 ].clone();
35402 
35403  binormals[ i ] = binormals[ i - 1 ].clone();
35404 
35405  vec.crossVectors( tangents[ i - 1 ], tangents[ i ] );
35406 
35407  if ( vec.length() > Number.EPSILON ) {
35408 
35409  vec.normalize();
35410 
35411  theta = Math.acos( _Math.clamp( tangents[ i - 1 ].dot( tangents[ i ] ), - 1, 1 ) ); // clamp for floating pt errors
35412 
35413  normals[ i ].applyMatrix4( mat.makeRotationAxis( vec, theta ) );
35414 
35415  }
35416 
35417  binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
35418 
35419  }
35420 
35421  // if the curve is closed, postprocess the vectors so the first and last normal vectors are the same
35422 
35423  if ( closed === true ) {
35424 
35425  theta = Math.acos( _Math.clamp( normals[ 0 ].dot( normals[ segments ] ), - 1, 1 ) );
35426  theta /= segments;
35427 
35428  if ( tangents[ 0 ].dot( vec.crossVectors( normals[ 0 ], normals[ segments ] ) ) > 0 ) {
35429 
35430  theta = - theta;
35431 
35432  }
35433 
35434  for ( i = 1; i <= segments; i ++ ) {
35435 
35436  // twist a little...
35437  normals[ i ].applyMatrix4( mat.makeRotationAxis( tangents[ i ], theta * i ) );
35438  binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
35439 
35440  }
35441 
35442  }
35443 
35444  return {
35445  tangents: tangents,
35446  normals: normals,
35447  binormals: binormals
35448  };
35449 
35450  },
35451 
35452  clone: function () {
35453 
35454  return new this.constructor().copy( this );
35455 
35456  },
35457 
35458  copy: function ( source ) {
35459 
35460  this.arcLengthDivisions = source.arcLengthDivisions;
35461 
35462  return this;
35463 
35464  },
35465 
35466  toJSON: function () {
35467 
35468  var data = {
35469  metadata: {
35470  version: 4.5,
35471  type: 'Curve',
35472  generator: 'Curve.toJSON'
35473  }
35474  };
35475 
35476  data.arcLengthDivisions = this.arcLengthDivisions;
35477  data.type = this.type;
35478 
35479  return data;
35480 
35481  },
35482 
35483  fromJSON: function ( json ) {
35484 
35485  this.arcLengthDivisions = json.arcLengthDivisions;
35486 
35487  return this;
35488 
35489  }
35490 
35491  } );
35492 
35493  function EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
35494 
35495  Curve.call( this );
35496 
35497  this.type = 'EllipseCurve';
35498 
35499  this.aX = aX || 0;
35500  this.aY = aY || 0;
35501 
35502  this.xRadius = xRadius || 1;
35503  this.yRadius = yRadius || 1;
35504 
35505  this.aStartAngle = aStartAngle || 0;
35506  this.aEndAngle = aEndAngle || 2 * Math.PI;
35507 
35508  this.aClockwise = aClockwise || false;
35509 
35510  this.aRotation = aRotation || 0;
35511 
35512  }
35513 
35514  EllipseCurve.prototype = Object.create( Curve.prototype );
35515  EllipseCurve.prototype.constructor = EllipseCurve;
35516 
35517  EllipseCurve.prototype.isEllipseCurve = true;
35518 
35519  EllipseCurve.prototype.getPoint = function ( t, optionalTarget ) {
35520 
35521  var point = optionalTarget || new Vector2();
35522 
35523  var twoPi = Math.PI * 2;
35524  var deltaAngle = this.aEndAngle - this.aStartAngle;
35525  var samePoints = Math.abs( deltaAngle ) < Number.EPSILON;
35526 
35527  // ensures that deltaAngle is 0 .. 2 PI
35528  while ( deltaAngle < 0 ) deltaAngle += twoPi;
35529  while ( deltaAngle > twoPi ) deltaAngle -= twoPi;
35530 
35531  if ( deltaAngle < Number.EPSILON ) {
35532 
35533  if ( samePoints ) {
35534 
35535  deltaAngle = 0;
35536 
35537  } else {
35538 
35539  deltaAngle = twoPi;
35540 
35541  }
35542 
35543  }
35544 
35545  if ( this.aClockwise === true && ! samePoints ) {
35546 
35547  if ( deltaAngle === twoPi ) {
35548 
35549  deltaAngle = - twoPi;
35550 
35551  } else {
35552 
35553  deltaAngle = deltaAngle - twoPi;
35554 
35555  }
35556 
35557  }
35558 
35559  var angle = this.aStartAngle + t * deltaAngle;
35560  var x = this.aX + this.xRadius * Math.cos( angle );
35561  var y = this.aY + this.yRadius * Math.sin( angle );
35562 
35563  if ( this.aRotation !== 0 ) {
35564 
35565  var cos = Math.cos( this.aRotation );
35566  var sin = Math.sin( this.aRotation );
35567 
35568  var tx = x - this.aX;
35569  var ty = y - this.aY;
35570 
35571  // Rotate the point about the center of the ellipse.
35572  x = tx * cos - ty * sin + this.aX;
35573  y = tx * sin + ty * cos + this.aY;
35574 
35575  }
35576 
35577  return point.set( x, y );
35578 
35579  };
35580 
35581  EllipseCurve.prototype.copy = function ( source ) {
35582 
35583  Curve.prototype.copy.call( this, source );
35584 
35585  this.aX = source.aX;
35586  this.aY = source.aY;
35587 
35588  this.xRadius = source.xRadius;
35589  this.yRadius = source.yRadius;
35590 
35591  this.aStartAngle = source.aStartAngle;
35592  this.aEndAngle = source.aEndAngle;
35593 
35594  this.aClockwise = source.aClockwise;
35595 
35596  this.aRotation = source.aRotation;
35597 
35598  return this;
35599 
35600  };
35601 
35602 
35603  EllipseCurve.prototype.toJSON = function () {
35604 
35605  var data = Curve.prototype.toJSON.call( this );
35606 
35607  data.aX = this.aX;
35608  data.aY = this.aY;
35609 
35610  data.xRadius = this.xRadius;
35611  data.yRadius = this.yRadius;
35612 
35613  data.aStartAngle = this.aStartAngle;
35614  data.aEndAngle = this.aEndAngle;
35615 
35616  data.aClockwise = this.aClockwise;
35617 
35618  data.aRotation = this.aRotation;
35619 
35620  return data;
35621 
35622  };
35623 
35624  EllipseCurve.prototype.fromJSON = function ( json ) {
35625 
35626  Curve.prototype.fromJSON.call( this, json );
35627 
35628  this.aX = json.aX;
35629  this.aY = json.aY;
35630 
35631  this.xRadius = json.xRadius;
35632  this.yRadius = json.yRadius;
35633 
35634  this.aStartAngle = json.aStartAngle;
35635  this.aEndAngle = json.aEndAngle;
35636 
35637  this.aClockwise = json.aClockwise;
35638 
35639  this.aRotation = json.aRotation;
35640 
35641  return this;
35642 
35643  };
35644 
35645  function ArcCurve( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
35646 
35647  EllipseCurve.call( this, aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
35648 
35649  this.type = 'ArcCurve';
35650 
35651  }
35652 
35653  ArcCurve.prototype = Object.create( EllipseCurve.prototype );
35654  ArcCurve.prototype.constructor = ArcCurve;
35655 
35656  ArcCurve.prototype.isArcCurve = true;
35657 
35670  /*
35671  Based on an optimized c++ solution in
35672  - http://stackoverflow.com/questions/9489736/catmull-rom-curve-with-no-cusps-and-no-self-intersections/
35673  - http://ideone.com/NoEbVM
35674 
35675  This CubicPoly class could be used for reusing some variables and calculations,
35676  but for three.js curve use, it could be possible inlined and flatten into a single function call
35677  which can be placed in CurveUtils.
35678  */
35679 
35680  function CubicPoly() {
35681 
35682  var c0 = 0, c1 = 0, c2 = 0, c3 = 0;
35683 
35684  /*
35685  * Compute coefficients for a cubic polynomial
35686  * p(s) = c0 + c1*s + c2*s^2 + c3*s^3
35687  * such that
35688  * p(0) = x0, p(1) = x1
35689  * and
35690  * p'(0) = t0, p'(1) = t1.
35691  */
35692  function init( x0, x1, t0, t1 ) {
35693 
35694  c0 = x0;
35695  c1 = t0;
35696  c2 = - 3 * x0 + 3 * x1 - 2 * t0 - t1;
35697  c3 = 2 * x0 - 2 * x1 + t0 + t1;
35698 
35699  }
35700 
35701  return {
35702 
35703  initCatmullRom: function ( x0, x1, x2, x3, tension ) {
35704 
35705  init( x1, x2, tension * ( x2 - x0 ), tension * ( x3 - x1 ) );
35706 
35707  },
35708 
35709  initNonuniformCatmullRom: function ( x0, x1, x2, x3, dt0, dt1, dt2 ) {
35710 
35711  // compute tangents when parameterized in [t1,t2]
35712  var t1 = ( x1 - x0 ) / dt0 - ( x2 - x0 ) / ( dt0 + dt1 ) + ( x2 - x1 ) / dt1;
35713  var t2 = ( x2 - x1 ) / dt1 - ( x3 - x1 ) / ( dt1 + dt2 ) + ( x3 - x2 ) / dt2;
35714 
35715  // rescale tangents for parametrization in [0,1]
35716  t1 *= dt1;
35717  t2 *= dt1;
35718 
35719  init( x1, x2, t1, t2 );
35720 
35721  },
35722 
35723  calc: function ( t ) {
35724 
35725  var t2 = t * t;
35726  var t3 = t2 * t;
35727  return c0 + c1 * t + c2 * t2 + c3 * t3;
35728 
35729  }
35730 
35731  };
35732 
35733  }
35734 
35735  //
35736 
35737  var tmp = new Vector3();
35738  var px = new CubicPoly(), py = new CubicPoly(), pz = new CubicPoly();
35739 
35740  function CatmullRomCurve3( points, closed, curveType, tension ) {
35741 
35742  Curve.call( this );
35743 
35744  this.type = 'CatmullRomCurve3';
35745 
35746  this.points = points || [];
35747  this.closed = closed || false;
35748  this.curveType = curveType || 'centripetal';
35749  this.tension = tension || 0.5;
35750 
35751  }
35752 
35753  CatmullRomCurve3.prototype = Object.create( Curve.prototype );
35754  CatmullRomCurve3.prototype.constructor = CatmullRomCurve3;
35755 
35756  CatmullRomCurve3.prototype.isCatmullRomCurve3 = true;
35757 
35758  CatmullRomCurve3.prototype.getPoint = function ( t, optionalTarget ) {
35759 
35760  var point = optionalTarget || new Vector3();
35761 
35762  var points = this.points;
35763  var l = points.length;
35764 
35765  var p = ( l - ( this.closed ? 0 : 1 ) ) * t;
35766  var intPoint = Math.floor( p );
35767  var weight = p - intPoint;
35768 
35769  if ( this.closed ) {
35770 
35771  intPoint += intPoint > 0 ? 0 : ( Math.floor( Math.abs( intPoint ) / l ) + 1 ) * l;
35772 
35773  } else if ( weight === 0 && intPoint === l - 1 ) {
35774 
35775  intPoint = l - 2;
35776  weight = 1;
35777 
35778  }
35779 
35780  var p0, p1, p2, p3; // 4 points
35781 
35782  if ( this.closed || intPoint > 0 ) {
35783 
35784  p0 = points[ ( intPoint - 1 ) % l ];
35785 
35786  } else {
35787 
35788  // extrapolate first point
35789  tmp.subVectors( points[ 0 ], points[ 1 ] ).add( points[ 0 ] );
35790  p0 = tmp;
35791 
35792  }
35793 
35794  p1 = points[ intPoint % l ];
35795  p2 = points[ ( intPoint + 1 ) % l ];
35796 
35797  if ( this.closed || intPoint + 2 < l ) {
35798 
35799  p3 = points[ ( intPoint + 2 ) % l ];
35800 
35801  } else {
35802 
35803  // extrapolate last point
35804  tmp.subVectors( points[ l - 1 ], points[ l - 2 ] ).add( points[ l - 1 ] );
35805  p3 = tmp;
35806 
35807  }
35808 
35809  if ( this.curveType === 'centripetal' || this.curveType === 'chordal' ) {
35810 
35811  // init Centripetal / Chordal Catmull-Rom
35812  var pow = this.curveType === 'chordal' ? 0.5 : 0.25;
35813  var dt0 = Math.pow( p0.distanceToSquared( p1 ), pow );
35814  var dt1 = Math.pow( p1.distanceToSquared( p2 ), pow );
35815  var dt2 = Math.pow( p2.distanceToSquared( p3 ), pow );
35816 
35817  // safety check for repeated points
35818  if ( dt1 < 1e-4 ) dt1 = 1.0;
35819  if ( dt0 < 1e-4 ) dt0 = dt1;
35820  if ( dt2 < 1e-4 ) dt2 = dt1;
35821 
35822  px.initNonuniformCatmullRom( p0.x, p1.x, p2.x, p3.x, dt0, dt1, dt2 );
35823  py.initNonuniformCatmullRom( p0.y, p1.y, p2.y, p3.y, dt0, dt1, dt2 );
35824  pz.initNonuniformCatmullRom( p0.z, p1.z, p2.z, p3.z, dt0, dt1, dt2 );
35825 
35826  } else if ( this.curveType === 'catmullrom' ) {
35827 
35828  px.initCatmullRom( p0.x, p1.x, p2.x, p3.x, this.tension );
35829  py.initCatmullRom( p0.y, p1.y, p2.y, p3.y, this.tension );
35830  pz.initCatmullRom( p0.z, p1.z, p2.z, p3.z, this.tension );
35831 
35832  }
35833 
35834  point.set(
35835  px.calc( weight ),
35836  py.calc( weight ),
35837  pz.calc( weight )
35838  );
35839 
35840  return point;
35841 
35842  };
35843 
35844  CatmullRomCurve3.prototype.copy = function ( source ) {
35845 
35846  Curve.prototype.copy.call( this, source );
35847 
35848  this.points = [];
35849 
35850  for ( var i = 0, l = source.points.length; i < l; i ++ ) {
35851 
35852  var point = source.points[ i ];
35853 
35854  this.points.push( point.clone() );
35855 
35856  }
35857 
35858  this.closed = source.closed;
35859  this.curveType = source.curveType;
35860  this.tension = source.tension;
35861 
35862  return this;
35863 
35864  };
35865 
35866  CatmullRomCurve3.prototype.toJSON = function () {
35867 
35868  var data = Curve.prototype.toJSON.call( this );
35869 
35870  data.points = [];
35871 
35872  for ( var i = 0, l = this.points.length; i < l; i ++ ) {
35873 
35874  var point = this.points[ i ];
35875  data.points.push( point.toArray() );
35876 
35877  }
35878 
35879  data.closed = this.closed;
35880  data.curveType = this.curveType;
35881  data.tension = this.tension;
35882 
35883  return data;
35884 
35885  };
35886 
35887  CatmullRomCurve3.prototype.fromJSON = function ( json ) {
35888 
35889  Curve.prototype.fromJSON.call( this, json );
35890 
35891  this.points = [];
35892 
35893  for ( var i = 0, l = json.points.length; i < l; i ++ ) {
35894 
35895  var point = json.points[ i ];
35896  this.points.push( new Vector3().fromArray( point ) );
35897 
35898  }
35899 
35900  this.closed = json.closed;
35901  this.curveType = json.curveType;
35902  this.tension = json.tension;
35903 
35904  return this;
35905 
35906  };
35907 
35915  function CatmullRom( t, p0, p1, p2, p3 ) {
35916 
35917  var v0 = ( p2 - p0 ) * 0.5;
35918  var v1 = ( p3 - p1 ) * 0.5;
35919  var t2 = t * t;
35920  var t3 = t * t2;
35921  return ( 2 * p1 - 2 * p2 + v0 + v1 ) * t3 + ( - 3 * p1 + 3 * p2 - 2 * v0 - v1 ) * t2 + v0 * t + p1;
35922 
35923  }
35924 
35925  //
35926 
35927  function QuadraticBezierP0( t, p ) {
35928 
35929  var k = 1 - t;
35930  return k * k * p;
35931 
35932  }
35933 
35934  function QuadraticBezierP1( t, p ) {
35935 
35936  return 2 * ( 1 - t ) * t * p;
35937 
35938  }
35939 
35940  function QuadraticBezierP2( t, p ) {
35941 
35942  return t * t * p;
35943 
35944  }
35945 
35946  function QuadraticBezier( t, p0, p1, p2 ) {
35947 
35948  return QuadraticBezierP0( t, p0 ) + QuadraticBezierP1( t, p1 ) +
35949  QuadraticBezierP2( t, p2 );
35950 
35951  }
35952 
35953  //
35954 
35955  function CubicBezierP0( t, p ) {
35956 
35957  var k = 1 - t;
35958  return k * k * k * p;
35959 
35960  }
35961 
35962  function CubicBezierP1( t, p ) {
35963 
35964  var k = 1 - t;
35965  return 3 * k * k * t * p;
35966 
35967  }
35968 
35969  function CubicBezierP2( t, p ) {
35970 
35971  return 3 * ( 1 - t ) * t * t * p;
35972 
35973  }
35974 
35975  function CubicBezierP3( t, p ) {
35976 
35977  return t * t * t * p;
35978 
35979  }
35980 
35981  function CubicBezier( t, p0, p1, p2, p3 ) {
35982 
35983  return CubicBezierP0( t, p0 ) + CubicBezierP1( t, p1 ) + CubicBezierP2( t, p2 ) +
35984  CubicBezierP3( t, p3 );
35985 
35986  }
35987 
35988  function CubicBezierCurve( v0, v1, v2, v3 ) {
35989 
35990  Curve.call( this );
35991 
35992  this.type = 'CubicBezierCurve';
35993 
35994  this.v0 = v0 || new Vector2();
35995  this.v1 = v1 || new Vector2();
35996  this.v2 = v2 || new Vector2();
35997  this.v3 = v3 || new Vector2();
35998 
35999  }
36000 
36001  CubicBezierCurve.prototype = Object.create( Curve.prototype );
36002  CubicBezierCurve.prototype.constructor = CubicBezierCurve;
36003 
36004  CubicBezierCurve.prototype.isCubicBezierCurve = true;
36005 
36006  CubicBezierCurve.prototype.getPoint = function ( t, optionalTarget ) {
36007 
36008  var point = optionalTarget || new Vector2();
36009 
36010  var v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3;
36011 
36012  point.set(
36013  CubicBezier( t, v0.x, v1.x, v2.x, v3.x ),
36014  CubicBezier( t, v0.y, v1.y, v2.y, v3.y )
36015  );
36016 
36017  return point;
36018 
36019  };
36020 
36021  CubicBezierCurve.prototype.copy = function ( source ) {
36022 
36023  Curve.prototype.copy.call( this, source );
36024 
36025  this.v0.copy( source.v0 );
36026  this.v1.copy( source.v1 );
36027  this.v2.copy( source.v2 );
36028  this.v3.copy( source.v3 );
36029 
36030  return this;
36031 
36032  };
36033 
36034  CubicBezierCurve.prototype.toJSON = function () {
36035 
36036  var data = Curve.prototype.toJSON.call( this );
36037 
36038  data.v0 = this.v0.toArray();
36039  data.v1 = this.v1.toArray();
36040  data.v2 = this.v2.toArray();
36041  data.v3 = this.v3.toArray();
36042 
36043  return data;
36044 
36045  };
36046 
36047  CubicBezierCurve.prototype.fromJSON = function ( json ) {
36048 
36049  Curve.prototype.fromJSON.call( this, json );
36050 
36051  this.v0.fromArray( json.v0 );
36052  this.v1.fromArray( json.v1 );
36053  this.v2.fromArray( json.v2 );
36054  this.v3.fromArray( json.v3 );
36055 
36056  return this;
36057 
36058  };
36059 
36060  function CubicBezierCurve3( v0, v1, v2, v3 ) {
36061 
36062  Curve.call( this );
36063 
36064  this.type = 'CubicBezierCurve3';
36065 
36066  this.v0 = v0 || new Vector3();
36067  this.v1 = v1 || new Vector3();
36068  this.v2 = v2 || new Vector3();
36069  this.v3 = v3 || new Vector3();
36070 
36071  }
36072 
36073  CubicBezierCurve3.prototype = Object.create( Curve.prototype );
36074  CubicBezierCurve3.prototype.constructor = CubicBezierCurve3;
36075 
36076  CubicBezierCurve3.prototype.isCubicBezierCurve3 = true;
36077 
36078  CubicBezierCurve3.prototype.getPoint = function ( t, optionalTarget ) {
36079 
36080  var point = optionalTarget || new Vector3();
36081 
36082  var v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3;
36083 
36084  point.set(
36085  CubicBezier( t, v0.x, v1.x, v2.x, v3.x ),
36086  CubicBezier( t, v0.y, v1.y, v2.y, v3.y ),
36087  CubicBezier( t, v0.z, v1.z, v2.z, v3.z )
36088  );
36089 
36090  return point;
36091 
36092  };
36093 
36094  CubicBezierCurve3.prototype.copy = function ( source ) {
36095 
36096  Curve.prototype.copy.call( this, source );
36097 
36098  this.v0.copy( source.v0 );
36099  this.v1.copy( source.v1 );
36100  this.v2.copy( source.v2 );
36101  this.v3.copy( source.v3 );
36102 
36103  return this;
36104 
36105  };
36106 
36107  CubicBezierCurve3.prototype.toJSON = function () {
36108 
36109  var data = Curve.prototype.toJSON.call( this );
36110 
36111  data.v0 = this.v0.toArray();
36112  data.v1 = this.v1.toArray();
36113  data.v2 = this.v2.toArray();
36114  data.v3 = this.v3.toArray();
36115 
36116  return data;
36117 
36118  };
36119 
36120  CubicBezierCurve3.prototype.fromJSON = function ( json ) {
36121 
36122  Curve.prototype.fromJSON.call( this, json );
36123 
36124  this.v0.fromArray( json.v0 );
36125  this.v1.fromArray( json.v1 );
36126  this.v2.fromArray( json.v2 );
36127  this.v3.fromArray( json.v3 );
36128 
36129  return this;
36130 
36131  };
36132 
36133  function LineCurve( v1, v2 ) {
36134 
36135  Curve.call( this );
36136 
36137  this.type = 'LineCurve';
36138 
36139  this.v1 = v1 || new Vector2();
36140  this.v2 = v2 || new Vector2();
36141 
36142  }
36143 
36144  LineCurve.prototype = Object.create( Curve.prototype );
36145  LineCurve.prototype.constructor = LineCurve;
36146 
36147  LineCurve.prototype.isLineCurve = true;
36148 
36149  LineCurve.prototype.getPoint = function ( t, optionalTarget ) {
36150 
36151  var point = optionalTarget || new Vector2();
36152 
36153  if ( t === 1 ) {
36154 
36155  point.copy( this.v2 );
36156 
36157  } else {
36158 
36159  point.copy( this.v2 ).sub( this.v1 );
36160  point.multiplyScalar( t ).add( this.v1 );
36161 
36162  }
36163 
36164  return point;
36165 
36166  };
36167 
36168  // Line curve is linear, so we can overwrite default getPointAt
36169 
36170  LineCurve.prototype.getPointAt = function ( u, optionalTarget ) {
36171 
36172  return this.getPoint( u, optionalTarget );
36173 
36174  };
36175 
36176  LineCurve.prototype.getTangent = function ( /* t */ ) {
36177 
36178  var tangent = this.v2.clone().sub( this.v1 );
36179 
36180  return tangent.normalize();
36181 
36182  };
36183 
36184  LineCurve.prototype.copy = function ( source ) {
36185 
36186  Curve.prototype.copy.call( this, source );
36187 
36188  this.v1.copy( source.v1 );
36189  this.v2.copy( source.v2 );
36190 
36191  return this;
36192 
36193  };
36194 
36195  LineCurve.prototype.toJSON = function () {
36196 
36197  var data = Curve.prototype.toJSON.call( this );
36198 
36199  data.v1 = this.v1.toArray();
36200  data.v2 = this.v2.toArray();
36201 
36202  return data;
36203 
36204  };
36205 
36206  LineCurve.prototype.fromJSON = function ( json ) {
36207 
36208  Curve.prototype.fromJSON.call( this, json );
36209 
36210  this.v1.fromArray( json.v1 );
36211  this.v2.fromArray( json.v2 );
36212 
36213  return this;
36214 
36215  };
36216 
36217  function LineCurve3( v1, v2 ) {
36218 
36219  Curve.call( this );
36220 
36221  this.type = 'LineCurve3';
36222 
36223  this.v1 = v1 || new Vector3();
36224  this.v2 = v2 || new Vector3();
36225 
36226  }
36227 
36228  LineCurve3.prototype = Object.create( Curve.prototype );
36229  LineCurve3.prototype.constructor = LineCurve3;
36230 
36231  LineCurve3.prototype.isLineCurve3 = true;
36232 
36233  LineCurve3.prototype.getPoint = function ( t, optionalTarget ) {
36234 
36235  var point = optionalTarget || new Vector3();
36236 
36237  if ( t === 1 ) {
36238 
36239  point.copy( this.v2 );
36240 
36241  } else {
36242 
36243  point.copy( this.v2 ).sub( this.v1 );
36244  point.multiplyScalar( t ).add( this.v1 );
36245 
36246  }
36247 
36248  return point;
36249 
36250  };
36251 
36252  // Line curve is linear, so we can overwrite default getPointAt
36253 
36254  LineCurve3.prototype.getPointAt = function ( u, optionalTarget ) {
36255 
36256  return this.getPoint( u, optionalTarget );
36257 
36258  };
36259 
36260  LineCurve3.prototype.copy = function ( source ) {
36261 
36262  Curve.prototype.copy.call( this, source );
36263 
36264  this.v1.copy( source.v1 );
36265  this.v2.copy( source.v2 );
36266 
36267  return this;
36268 
36269  };
36270 
36271  LineCurve3.prototype.toJSON = function () {
36272 
36273  var data = Curve.prototype.toJSON.call( this );
36274 
36275  data.v1 = this.v1.toArray();
36276  data.v2 = this.v2.toArray();
36277 
36278  return data;
36279 
36280  };
36281 
36282  LineCurve3.prototype.fromJSON = function ( json ) {
36283 
36284  Curve.prototype.fromJSON.call( this, json );
36285 
36286  this.v1.fromArray( json.v1 );
36287  this.v2.fromArray( json.v2 );
36288 
36289  return this;
36290 
36291  };
36292 
36293  function QuadraticBezierCurve( v0, v1, v2 ) {
36294 
36295  Curve.call( this );
36296 
36297  this.type = 'QuadraticBezierCurve';
36298 
36299  this.v0 = v0 || new Vector2();
36300  this.v1 = v1 || new Vector2();
36301  this.v2 = v2 || new Vector2();
36302 
36303  }
36304 
36305  QuadraticBezierCurve.prototype = Object.create( Curve.prototype );
36306  QuadraticBezierCurve.prototype.constructor = QuadraticBezierCurve;
36307 
36308  QuadraticBezierCurve.prototype.isQuadraticBezierCurve = true;
36309 
36310  QuadraticBezierCurve.prototype.getPoint = function ( t, optionalTarget ) {
36311 
36312  var point = optionalTarget || new Vector2();
36313 
36314  var v0 = this.v0, v1 = this.v1, v2 = this.v2;
36315 
36316  point.set(
36317  QuadraticBezier( t, v0.x, v1.x, v2.x ),
36318  QuadraticBezier( t, v0.y, v1.y, v2.y )
36319  );
36320 
36321  return point;
36322 
36323  };
36324 
36325  QuadraticBezierCurve.prototype.copy = function ( source ) {
36326 
36327  Curve.prototype.copy.call( this, source );
36328 
36329  this.v0.copy( source.v0 );
36330  this.v1.copy( source.v1 );
36331  this.v2.copy( source.v2 );
36332 
36333  return this;
36334 
36335  };
36336 
36337  QuadraticBezierCurve.prototype.toJSON = function () {
36338 
36339  var data = Curve.prototype.toJSON.call( this );
36340 
36341  data.v0 = this.v0.toArray();
36342  data.v1 = this.v1.toArray();
36343  data.v2 = this.v2.toArray();
36344 
36345  return data;
36346 
36347  };
36348 
36349  QuadraticBezierCurve.prototype.fromJSON = function ( json ) {
36350 
36351  Curve.prototype.fromJSON.call( this, json );
36352 
36353  this.v0.fromArray( json.v0 );
36354  this.v1.fromArray( json.v1 );
36355  this.v2.fromArray( json.v2 );
36356 
36357  return this;
36358 
36359  };
36360 
36361  function QuadraticBezierCurve3( v0, v1, v2 ) {
36362 
36363  Curve.call( this );
36364 
36365  this.type = 'QuadraticBezierCurve3';
36366 
36367  this.v0 = v0 || new Vector3();
36368  this.v1 = v1 || new Vector3();
36369  this.v2 = v2 || new Vector3();
36370 
36371  }
36372 
36373  QuadraticBezierCurve3.prototype = Object.create( Curve.prototype );
36374  QuadraticBezierCurve3.prototype.constructor = QuadraticBezierCurve3;
36375 
36376  QuadraticBezierCurve3.prototype.isQuadraticBezierCurve3 = true;
36377 
36378  QuadraticBezierCurve3.prototype.getPoint = function ( t, optionalTarget ) {
36379 
36380  var point = optionalTarget || new Vector3();
36381 
36382  var v0 = this.v0, v1 = this.v1, v2 = this.v2;
36383 
36384  point.set(
36385  QuadraticBezier( t, v0.x, v1.x, v2.x ),
36386  QuadraticBezier( t, v0.y, v1.y, v2.y ),
36387  QuadraticBezier( t, v0.z, v1.z, v2.z )
36388  );
36389 
36390  return point;
36391 
36392  };
36393 
36394  QuadraticBezierCurve3.prototype.copy = function ( source ) {
36395 
36396  Curve.prototype.copy.call( this, source );
36397 
36398  this.v0.copy( source.v0 );
36399  this.v1.copy( source.v1 );
36400  this.v2.copy( source.v2 );
36401 
36402  return this;
36403 
36404  };
36405 
36406  QuadraticBezierCurve3.prototype.toJSON = function () {
36407 
36408  var data = Curve.prototype.toJSON.call( this );
36409 
36410  data.v0 = this.v0.toArray();
36411  data.v1 = this.v1.toArray();
36412  data.v2 = this.v2.toArray();
36413 
36414  return data;
36415 
36416  };
36417 
36418  QuadraticBezierCurve3.prototype.fromJSON = function ( json ) {
36419 
36420  Curve.prototype.fromJSON.call( this, json );
36421 
36422  this.v0.fromArray( json.v0 );
36423  this.v1.fromArray( json.v1 );
36424  this.v2.fromArray( json.v2 );
36425 
36426  return this;
36427 
36428  };
36429 
36430  function SplineCurve( points /* array of Vector2 */ ) {
36431 
36432  Curve.call( this );
36433 
36434  this.type = 'SplineCurve';
36435 
36436  this.points = points || [];
36437 
36438  }
36439 
36440  SplineCurve.prototype = Object.create( Curve.prototype );
36441  SplineCurve.prototype.constructor = SplineCurve;
36442 
36443  SplineCurve.prototype.isSplineCurve = true;
36444 
36445  SplineCurve.prototype.getPoint = function ( t, optionalTarget ) {
36446 
36447  var point = optionalTarget || new Vector2();
36448 
36449  var points = this.points;
36450  var p = ( points.length - 1 ) * t;
36451 
36452  var intPoint = Math.floor( p );
36453  var weight = p - intPoint;
36454 
36455  var p0 = points[ intPoint === 0 ? intPoint : intPoint - 1 ];
36456  var p1 = points[ intPoint ];
36457  var p2 = points[ intPoint > points.length - 2 ? points.length - 1 : intPoint + 1 ];
36458  var p3 = points[ intPoint > points.length - 3 ? points.length - 1 : intPoint + 2 ];
36459 
36460  point.set(
36461  CatmullRom( weight, p0.x, p1.x, p2.x, p3.x ),
36462  CatmullRom( weight, p0.y, p1.y, p2.y, p3.y )
36463  );
36464 
36465  return point;
36466 
36467  };
36468 
36469  SplineCurve.prototype.copy = function ( source ) {
36470 
36471  Curve.prototype.copy.call( this, source );
36472 
36473  this.points = [];
36474 
36475  for ( var i = 0, l = source.points.length; i < l; i ++ ) {
36476 
36477  var point = source.points[ i ];
36478 
36479  this.points.push( point.clone() );
36480 
36481  }
36482 
36483  return this;
36484 
36485  };
36486 
36487  SplineCurve.prototype.toJSON = function () {
36488 
36489  var data = Curve.prototype.toJSON.call( this );
36490 
36491  data.points = [];
36492 
36493  for ( var i = 0, l = this.points.length; i < l; i ++ ) {
36494 
36495  var point = this.points[ i ];
36496  data.points.push( point.toArray() );
36497 
36498  }
36499 
36500  return data;
36501 
36502  };
36503 
36504  SplineCurve.prototype.fromJSON = function ( json ) {
36505 
36506  Curve.prototype.fromJSON.call( this, json );
36507 
36508  this.points = [];
36509 
36510  for ( var i = 0, l = json.points.length; i < l; i ++ ) {
36511 
36512  var point = json.points[ i ];
36513  this.points.push( new Vector2().fromArray( point ) );
36514 
36515  }
36516 
36517  return this;
36518 
36519  };
36520 
36521 
36522 
36523  var Curves = /*#__PURE__*/Object.freeze({
36524  ArcCurve: ArcCurve,
36525  CatmullRomCurve3: CatmullRomCurve3,
36526  CubicBezierCurve: CubicBezierCurve,
36527  CubicBezierCurve3: CubicBezierCurve3,
36528  EllipseCurve: EllipseCurve,
36529  LineCurve: LineCurve,
36530  LineCurve3: LineCurve3,
36531  QuadraticBezierCurve: QuadraticBezierCurve,
36532  QuadraticBezierCurve3: QuadraticBezierCurve3,
36533  SplineCurve: SplineCurve
36534  });
36535 
36541  /**************************************************************
36542  * Curved Path - a curve path is simply a array of connected
36543  * curves, but retains the api of a curve
36544  **************************************************************/
36545 
36546  function CurvePath() {
36547 
36548  Curve.call( this );
36549 
36550  this.type = 'CurvePath';
36551 
36552  this.curves = [];
36553  this.autoClose = false; // Automatically closes the path
36554 
36555  }
36556 
36557  CurvePath.prototype = Object.assign( Object.create( Curve.prototype ), {
36558 
36559  constructor: CurvePath,
36560 
36561  add: function ( curve ) {
36562 
36563  this.curves.push( curve );
36564 
36565  },
36566 
36567  closePath: function () {
36568 
36569  // Add a line curve if start and end of lines are not connected
36570  var startPoint = this.curves[ 0 ].getPoint( 0 );
36571  var endPoint = this.curves[ this.curves.length - 1 ].getPoint( 1 );
36572 
36573  if ( ! startPoint.equals( endPoint ) ) {
36574 
36575  this.curves.push( new LineCurve( endPoint, startPoint ) );
36576 
36577  }
36578 
36579  },
36580 
36581  // To get accurate point with reference to
36582  // entire path distance at time t,
36583  // following has to be done:
36584 
36585  // 1. Length of each sub path have to be known
36586  // 2. Locate and identify type of curve
36587  // 3. Get t for the curve
36588  // 4. Return curve.getPointAt(t')
36589 
36590  getPoint: function ( t ) {
36591 
36592  var d = t * this.getLength();
36593  var curveLengths = this.getCurveLengths();
36594  var i = 0;
36595 
36596  // To think about boundaries points.
36597 
36598  while ( i < curveLengths.length ) {
36599 
36600  if ( curveLengths[ i ] >= d ) {
36601 
36602  var diff = curveLengths[ i ] - d;
36603  var curve = this.curves[ i ];
36604 
36605  var segmentLength = curve.getLength();
36606  var u = segmentLength === 0 ? 0 : 1 - diff / segmentLength;
36607 
36608  return curve.getPointAt( u );
36609 
36610  }
36611 
36612  i ++;
36613 
36614  }
36615 
36616  return null;
36617 
36618  // loop where sum != 0, sum > d , sum+1 <d
36619 
36620  },
36621 
36622  // We cannot use the default THREE.Curve getPoint() with getLength() because in
36623  // THREE.Curve, getLength() depends on getPoint() but in THREE.CurvePath
36624  // getPoint() depends on getLength
36625 
36626  getLength: function () {
36627 
36628  var lens = this.getCurveLengths();
36629  return lens[ lens.length - 1 ];
36630 
36631  },
36632 
36633  // cacheLengths must be recalculated.
36634  updateArcLengths: function () {
36635 
36636  this.needsUpdate = true;
36637  this.cacheLengths = null;
36638  this.getCurveLengths();
36639 
36640  },
36641 
36642  // Compute lengths and cache them
36643  // We cannot overwrite getLengths() because UtoT mapping uses it.
36644 
36645  getCurveLengths: function () {
36646 
36647  // We use cache values if curves and cache array are same length
36648 
36649  if ( this.cacheLengths && this.cacheLengths.length === this.curves.length ) {
36650 
36651  return this.cacheLengths;
36652 
36653  }
36654 
36655  // Get length of sub-curve
36656  // Push sums into cached array
36657 
36658  var lengths = [], sums = 0;
36659 
36660  for ( var i = 0, l = this.curves.length; i < l; i ++ ) {
36661 
36662  sums += this.curves[ i ].getLength();
36663  lengths.push( sums );
36664 
36665  }
36666 
36667  this.cacheLengths = lengths;
36668 
36669  return lengths;
36670 
36671  },
36672 
36673  getSpacedPoints: function ( divisions ) {
36674 
36675  if ( divisions === undefined ) divisions = 40;
36676 
36677  var points = [];
36678 
36679  for ( var i = 0; i <= divisions; i ++ ) {
36680 
36681  points.push( this.getPoint( i / divisions ) );
36682 
36683  }
36684 
36685  if ( this.autoClose ) {
36686 
36687  points.push( points[ 0 ] );
36688 
36689  }
36690 
36691  return points;
36692 
36693  },
36694 
36695  getPoints: function ( divisions ) {
36696 
36697  divisions = divisions || 12;
36698 
36699  var points = [], last;
36700 
36701  for ( var i = 0, curves = this.curves; i < curves.length; i ++ ) {
36702 
36703  var curve = curves[ i ];
36704  var resolution = ( curve && curve.isEllipseCurve ) ? divisions * 2
36705  : ( curve && ( curve.isLineCurve || curve.isLineCurve3 ) ) ? 1
36706  : ( curve && curve.isSplineCurve ) ? divisions * curve.points.length
36707  : divisions;
36708 
36709  var pts = curve.getPoints( resolution );
36710 
36711  for ( var j = 0; j < pts.length; j ++ ) {
36712 
36713  var point = pts[ j ];
36714 
36715  if ( last && last.equals( point ) ) continue; // ensures no consecutive points are duplicates
36716 
36717  points.push( point );
36718  last = point;
36719 
36720  }
36721 
36722  }
36723 
36724  if ( this.autoClose && points.length > 1 && ! points[ points.length - 1 ].equals( points[ 0 ] ) ) {
36725 
36726  points.push( points[ 0 ] );
36727 
36728  }
36729 
36730  return points;
36731 
36732  },
36733 
36734  copy: function ( source ) {
36735 
36736  Curve.prototype.copy.call( this, source );
36737 
36738  this.curves = [];
36739 
36740  for ( var i = 0, l = source.curves.length; i < l; i ++ ) {
36741 
36742  var curve = source.curves[ i ];
36743 
36744  this.curves.push( curve.clone() );
36745 
36746  }
36747 
36748  this.autoClose = source.autoClose;
36749 
36750  return this;
36751 
36752  },
36753 
36754  toJSON: function () {
36755 
36756  var data = Curve.prototype.toJSON.call( this );
36757 
36758  data.autoClose = this.autoClose;
36759  data.curves = [];
36760 
36761  for ( var i = 0, l = this.curves.length; i < l; i ++ ) {
36762 
36763  var curve = this.curves[ i ];
36764  data.curves.push( curve.toJSON() );
36765 
36766  }
36767 
36768  return data;
36769 
36770  },
36771 
36772  fromJSON: function ( json ) {
36773 
36774  Curve.prototype.fromJSON.call( this, json );
36775 
36776  this.autoClose = json.autoClose;
36777  this.curves = [];
36778 
36779  for ( var i = 0, l = json.curves.length; i < l; i ++ ) {
36780 
36781  var curve = json.curves[ i ];
36782  this.curves.push( new Curves[ curve.type ]().fromJSON( curve ) );
36783 
36784  }
36785 
36786  return this;
36787 
36788  }
36789 
36790  } );
36791 
36797  function Path( points ) {
36798 
36799  CurvePath.call( this );
36800 
36801  this.type = 'Path';
36802 
36803  this.currentPoint = new Vector2();
36804 
36805  if ( points ) {
36806 
36807  this.setFromPoints( points );
36808 
36809  }
36810 
36811  }
36812 
36813  Path.prototype = Object.assign( Object.create( CurvePath.prototype ), {
36814 
36815  constructor: Path,
36816 
36817  setFromPoints: function ( points ) {
36818 
36819  this.moveTo( points[ 0 ].x, points[ 0 ].y );
36820 
36821  for ( var i = 1, l = points.length; i < l; i ++ ) {
36822 
36823  this.lineTo( points[ i ].x, points[ i ].y );
36824 
36825  }
36826 
36827  },
36828 
36829  moveTo: function ( x, y ) {
36830 
36831  this.currentPoint.set( x, y ); // TODO consider referencing vectors instead of copying?
36832 
36833  },
36834 
36835  lineTo: function ( x, y ) {
36836 
36837  var curve = new LineCurve( this.currentPoint.clone(), new Vector2( x, y ) );
36838  this.curves.push( curve );
36839 
36840  this.currentPoint.set( x, y );
36841 
36842  },
36843 
36844  quadraticCurveTo: function ( aCPx, aCPy, aX, aY ) {
36845 
36846  var curve = new QuadraticBezierCurve(
36847  this.currentPoint.clone(),
36848  new Vector2( aCPx, aCPy ),
36849  new Vector2( aX, aY )
36850  );
36851 
36852  this.curves.push( curve );
36853 
36854  this.currentPoint.set( aX, aY );
36855 
36856  },
36857 
36858  bezierCurveTo: function ( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) {
36859 
36860  var curve = new CubicBezierCurve(
36861  this.currentPoint.clone(),
36862  new Vector2( aCP1x, aCP1y ),
36863  new Vector2( aCP2x, aCP2y ),
36864  new Vector2( aX, aY )
36865  );
36866 
36867  this.curves.push( curve );
36868 
36869  this.currentPoint.set( aX, aY );
36870 
36871  },
36872 
36873  splineThru: function ( pts /*Array of Vector*/ ) {
36874 
36875  var npts = [ this.currentPoint.clone() ].concat( pts );
36876 
36877  var curve = new SplineCurve( npts );
36878  this.curves.push( curve );
36879 
36880  this.currentPoint.copy( pts[ pts.length - 1 ] );
36881 
36882  },
36883 
36884  arc: function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
36885 
36886  var x0 = this.currentPoint.x;
36887  var y0 = this.currentPoint.y;
36888 
36889  this.absarc( aX + x0, aY + y0, aRadius,
36890  aStartAngle, aEndAngle, aClockwise );
36891 
36892  },
36893 
36894  absarc: function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
36895 
36896  this.absellipse( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
36897 
36898  },
36899 
36900  ellipse: function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
36901 
36902  var x0 = this.currentPoint.x;
36903  var y0 = this.currentPoint.y;
36904 
36905  this.absellipse( aX + x0, aY + y0, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
36906 
36907  },
36908 
36909  absellipse: function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
36910 
36911  var curve = new EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
36912 
36913  if ( this.curves.length > 0 ) {
36914 
36915  // if a previous curve is present, attempt to join
36916  var firstPoint = curve.getPoint( 0 );
36917 
36918  if ( ! firstPoint.equals( this.currentPoint ) ) {
36919 
36920  this.lineTo( firstPoint.x, firstPoint.y );
36921 
36922  }
36923 
36924  }
36925 
36926  this.curves.push( curve );
36927 
36928  var lastPoint = curve.getPoint( 1 );
36929  this.currentPoint.copy( lastPoint );
36930 
36931  },
36932 
36933  copy: function ( source ) {
36934 
36935  CurvePath.prototype.copy.call( this, source );
36936 
36937  this.currentPoint.copy( source.currentPoint );
36938 
36939  return this;
36940 
36941  },
36942 
36943  toJSON: function () {
36944 
36945  var data = CurvePath.prototype.toJSON.call( this );
36946 
36947  data.currentPoint = this.currentPoint.toArray();
36948 
36949  return data;
36950 
36951  },
36952 
36953  fromJSON: function ( json ) {
36954 
36955  CurvePath.prototype.fromJSON.call( this, json );
36956 
36957  this.currentPoint.fromArray( json.currentPoint );
36958 
36959  return this;
36960 
36961  }
36962 
36963  } );
36964 
36970  // STEP 1 Create a path.
36971  // STEP 2 Turn path into shape.
36972  // STEP 3 ExtrudeGeometry takes in Shape/Shapes
36973  // STEP 3a - Extract points from each shape, turn to vertices
36974  // STEP 3b - Triangulate each shape, add faces.
36975 
36976  function Shape( points ) {
36977 
36978  Path.call( this, points );
36979 
36980  this.uuid = _Math.generateUUID();
36981 
36982  this.type = 'Shape';
36983 
36984  this.holes = [];
36985 
36986  }
36987 
36988  Shape.prototype = Object.assign( Object.create( Path.prototype ), {
36989 
36990  constructor: Shape,
36991 
36992  getPointsHoles: function ( divisions ) {
36993 
36994  var holesPts = [];
36995 
36996  for ( var i = 0, l = this.holes.length; i < l; i ++ ) {
36997 
36998  holesPts[ i ] = this.holes[ i ].getPoints( divisions );
36999 
37000  }
37001 
37002  return holesPts;
37003 
37004  },
37005 
37006  // get points of shape and holes (keypoints based on segments parameter)
37007 
37008  extractPoints: function ( divisions ) {
37009 
37010  return {
37011 
37012  shape: this.getPoints( divisions ),
37013  holes: this.getPointsHoles( divisions )
37014 
37015  };
37016 
37017  },
37018 
37019  copy: function ( source ) {
37020 
37021  Path.prototype.copy.call( this, source );
37022 
37023  this.holes = [];
37024 
37025  for ( var i = 0, l = source.holes.length; i < l; i ++ ) {
37026 
37027  var hole = source.holes[ i ];
37028 
37029  this.holes.push( hole.clone() );
37030 
37031  }
37032 
37033  return this;
37034 
37035  },
37036 
37037  toJSON: function () {
37038 
37039  var data = Path.prototype.toJSON.call( this );
37040 
37041  data.uuid = this.uuid;
37042  data.holes = [];
37043 
37044  for ( var i = 0, l = this.holes.length; i < l; i ++ ) {
37045 
37046  var hole = this.holes[ i ];
37047  data.holes.push( hole.toJSON() );
37048 
37049  }
37050 
37051  return data;
37052 
37053  },
37054 
37055  fromJSON: function ( json ) {
37056 
37057  Path.prototype.fromJSON.call( this, json );
37058 
37059  this.uuid = json.uuid;
37060  this.holes = [];
37061 
37062  for ( var i = 0, l = json.holes.length; i < l; i ++ ) {
37063 
37064  var hole = json.holes[ i ];
37065  this.holes.push( new Path().fromJSON( hole ) );
37066 
37067  }
37068 
37069  return this;
37070 
37071  }
37072 
37073  } );
37074 
37080  function Light( color, intensity ) {
37081 
37082  Object3D.call( this );
37083 
37084  this.type = 'Light';
37085 
37086  this.color = new Color( color );
37087  this.intensity = intensity !== undefined ? intensity : 1;
37088 
37089  this.receiveShadow = undefined;
37090 
37091  }
37092 
37093  Light.prototype = Object.assign( Object.create( Object3D.prototype ), {
37094 
37095  constructor: Light,
37096 
37097  isLight: true,
37098 
37099  copy: function ( source ) {
37100 
37101  Object3D.prototype.copy.call( this, source );
37102 
37103  this.color.copy( source.color );
37104  this.intensity = source.intensity;
37105 
37106  return this;
37107 
37108  },
37109 
37110  toJSON: function ( meta ) {
37111 
37112  var data = Object3D.prototype.toJSON.call( this, meta );
37113 
37114  data.object.color = this.color.getHex();
37115  data.object.intensity = this.intensity;
37116 
37117  if ( this.groundColor !== undefined ) data.object.groundColor = this.groundColor.getHex();
37118 
37119  if ( this.distance !== undefined ) data.object.distance = this.distance;
37120  if ( this.angle !== undefined ) data.object.angle = this.angle;
37121  if ( this.decay !== undefined ) data.object.decay = this.decay;
37122  if ( this.penumbra !== undefined ) data.object.penumbra = this.penumbra;
37123 
37124  if ( this.shadow !== undefined ) data.object.shadow = this.shadow.toJSON();
37125 
37126  return data;
37127 
37128  }
37129 
37130  } );
37131 
37136  function HemisphereLight( skyColor, groundColor, intensity ) {
37137 
37138  Light.call( this, skyColor, intensity );
37139 
37140  this.type = 'HemisphereLight';
37141 
37142  this.castShadow = undefined;
37143 
37144  this.position.copy( Object3D.DefaultUp );
37145  this.updateMatrix();
37146 
37147  this.groundColor = new Color( groundColor );
37148 
37149  }
37150 
37151  HemisphereLight.prototype = Object.assign( Object.create( Light.prototype ), {
37152 
37153  constructor: HemisphereLight,
37154 
37155  isHemisphereLight: true,
37156 
37157  copy: function ( source ) {
37158 
37159  Light.prototype.copy.call( this, source );
37160 
37161  this.groundColor.copy( source.groundColor );
37162 
37163  return this;
37164 
37165  }
37166 
37167  } );
37168 
37173  function LightShadow( camera ) {
37174 
37175  this.camera = camera;
37176 
37177  this.bias = 0;
37178  this.radius = 1;
37179 
37180  this.mapSize = new Vector2( 512, 512 );
37181 
37182  this.map = null;
37183  this.matrix = new Matrix4();
37184 
37185  }
37186 
37187  Object.assign( LightShadow.prototype, {
37188 
37189  copy: function ( source ) {
37190 
37191  this.camera = source.camera.clone();
37192 
37193  this.bias = source.bias;
37194  this.radius = source.radius;
37195 
37196  this.mapSize.copy( source.mapSize );
37197 
37198  return this;
37199 
37200  },
37201 
37202  clone: function () {
37203 
37204  return new this.constructor().copy( this );
37205 
37206  },
37207 
37208  toJSON: function () {
37209 
37210  var object = {};
37211 
37212  if ( this.bias !== 0 ) object.bias = this.bias;
37213  if ( this.radius !== 1 ) object.radius = this.radius;
37214  if ( this.mapSize.x !== 512 || this.mapSize.y !== 512 ) object.mapSize = this.mapSize.toArray();
37215 
37216  object.camera = this.camera.toJSON( false ).object;
37217  delete object.camera.matrix;
37218 
37219  return object;
37220 
37221  }
37222 
37223  } );
37224 
37229  function SpotLightShadow() {
37230 
37231  LightShadow.call( this, new PerspectiveCamera( 50, 1, 0.5, 500 ) );
37232 
37233  }
37234 
37235  SpotLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype ), {
37236 
37237  constructor: SpotLightShadow,
37238 
37239  isSpotLightShadow: true,
37240 
37241  update: function ( light ) {
37242 
37243  var camera = this.camera;
37244 
37245  var fov = _Math.RAD2DEG * 2 * light.angle;
37246  var aspect = this.mapSize.width / this.mapSize.height;
37247  var far = light.distance || camera.far;
37248 
37249  if ( fov !== camera.fov || aspect !== camera.aspect || far !== camera.far ) {
37250 
37251  camera.fov = fov;
37252  camera.aspect = aspect;
37253  camera.far = far;
37254  camera.updateProjectionMatrix();
37255 
37256  }
37257 
37258  }
37259 
37260  } );
37261 
37266  function SpotLight( color, intensity, distance, angle, penumbra, decay ) {
37267 
37268  Light.call( this, color, intensity );
37269 
37270  this.type = 'SpotLight';
37271 
37272  this.position.copy( Object3D.DefaultUp );
37273  this.updateMatrix();
37274 
37275  this.target = new Object3D();
37276 
37277  Object.defineProperty( this, 'power', {
37278  get: function () {
37279 
37280  // intensity = power per solid angle.
37281  // ref: equation (17) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
37282  return this.intensity * Math.PI;
37283 
37284  },
37285  set: function ( power ) {
37286 
37287  // intensity = power per solid angle.
37288  // ref: equation (17) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
37289  this.intensity = power / Math.PI;
37290 
37291  }
37292  } );
37293 
37294  this.distance = ( distance !== undefined ) ? distance : 0;
37295  this.angle = ( angle !== undefined ) ? angle : Math.PI / 3;
37296  this.penumbra = ( penumbra !== undefined ) ? penumbra : 0;
37297  this.decay = ( decay !== undefined ) ? decay : 1; // for physically correct lights, should be 2.
37298 
37299  this.shadow = new SpotLightShadow();
37300 
37301  }
37302 
37303  SpotLight.prototype = Object.assign( Object.create( Light.prototype ), {
37304 
37305  constructor: SpotLight,
37306 
37307  isSpotLight: true,
37308 
37309  copy: function ( source ) {
37310 
37311  Light.prototype.copy.call( this, source );
37312 
37313  this.distance = source.distance;
37314  this.angle = source.angle;
37315  this.penumbra = source.penumbra;
37316  this.decay = source.decay;
37317 
37318  this.target = source.target.clone();
37319 
37320  this.shadow = source.shadow.clone();
37321 
37322  return this;
37323 
37324  }
37325 
37326  } );
37327 
37333  function PointLight( color, intensity, distance, decay ) {
37334 
37335  Light.call( this, color, intensity );
37336 
37337  this.type = 'PointLight';
37338 
37339  Object.defineProperty( this, 'power', {
37340  get: function () {
37341 
37342  // intensity = power per solid angle.
37343  // ref: equation (15) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
37344  return this.intensity * 4 * Math.PI;
37345 
37346  },
37347  set: function ( power ) {
37348 
37349  // intensity = power per solid angle.
37350  // ref: equation (15) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
37351  this.intensity = power / ( 4 * Math.PI );
37352 
37353  }
37354  } );
37355 
37356  this.distance = ( distance !== undefined ) ? distance : 0;
37357  this.decay = ( decay !== undefined ) ? decay : 1; // for physically correct lights, should be 2.
37358 
37359  this.shadow = new LightShadow( new PerspectiveCamera( 90, 1, 0.5, 500 ) );
37360 
37361  }
37362 
37363  PointLight.prototype = Object.assign( Object.create( Light.prototype ), {
37364 
37365  constructor: PointLight,
37366 
37367  isPointLight: true,
37368 
37369  copy: function ( source ) {
37370 
37371  Light.prototype.copy.call( this, source );
37372 
37373  this.distance = source.distance;
37374  this.decay = source.decay;
37375 
37376  this.shadow = source.shadow.clone();
37377 
37378  return this;
37379 
37380  }
37381 
37382  } );
37383 
37389  function OrthographicCamera( left, right, top, bottom, near, far ) {
37390 
37391  Camera.call( this );
37392 
37393  this.type = 'OrthographicCamera';
37394 
37395  this.zoom = 1;
37396  this.view = null;
37397 
37398  this.left = ( left !== undefined ) ? left : - 1;
37399  this.right = ( right !== undefined ) ? right : 1;
37400  this.top = ( top !== undefined ) ? top : 1;
37401  this.bottom = ( bottom !== undefined ) ? bottom : - 1;
37402 
37403  this.near = ( near !== undefined ) ? near : 0.1;
37404  this.far = ( far !== undefined ) ? far : 2000;
37405 
37406  this.updateProjectionMatrix();
37407 
37408  }
37409 
37410  OrthographicCamera.prototype = Object.assign( Object.create( Camera.prototype ), {
37411 
37412  constructor: OrthographicCamera,
37413 
37414  isOrthographicCamera: true,
37415 
37416  copy: function ( source, recursive ) {
37417 
37418  Camera.prototype.copy.call( this, source, recursive );
37419 
37420  this.left = source.left;
37421  this.right = source.right;
37422  this.top = source.top;
37423  this.bottom = source.bottom;
37424  this.near = source.near;
37425  this.far = source.far;
37426 
37427  this.zoom = source.zoom;
37428  this.view = source.view === null ? null : Object.assign( {}, source.view );
37429 
37430  return this;
37431 
37432  },
37433 
37434  setViewOffset: function ( fullWidth, fullHeight, x, y, width, height ) {
37435 
37436  if ( this.view === null ) {
37437 
37438  this.view = {
37439  enabled: true,
37440  fullWidth: 1,
37441  fullHeight: 1,
37442  offsetX: 0,
37443  offsetY: 0,
37444  width: 1,
37445  height: 1
37446  };
37447 
37448  }
37449 
37450  this.view.enabled = true;
37451  this.view.fullWidth = fullWidth;
37452  this.view.fullHeight = fullHeight;
37453  this.view.offsetX = x;
37454  this.view.offsetY = y;
37455  this.view.width = width;
37456  this.view.height = height;
37457 
37458  this.updateProjectionMatrix();
37459 
37460  },
37461 
37462  clearViewOffset: function () {
37463 
37464  if ( this.view !== null ) {
37465 
37466  this.view.enabled = false;
37467 
37468  }
37469 
37470  this.updateProjectionMatrix();
37471 
37472  },
37473 
37474  updateProjectionMatrix: function () {
37475 
37476  var dx = ( this.right - this.left ) / ( 2 * this.zoom );
37477  var dy = ( this.top - this.bottom ) / ( 2 * this.zoom );
37478  var cx = ( this.right + this.left ) / 2;
37479  var cy = ( this.top + this.bottom ) / 2;
37480 
37481  var left = cx - dx;
37482  var right = cx + dx;
37483  var top = cy + dy;
37484  var bottom = cy - dy;
37485 
37486  if ( this.view !== null && this.view.enabled ) {
37487 
37488  var zoomW = this.zoom / ( this.view.width / this.view.fullWidth );
37489  var zoomH = this.zoom / ( this.view.height / this.view.fullHeight );
37490  var scaleW = ( this.right - this.left ) / this.view.width;
37491  var scaleH = ( this.top - this.bottom ) / this.view.height;
37492 
37493  left += scaleW * ( this.view.offsetX / zoomW );
37494  right = left + scaleW * ( this.view.width / zoomW );
37495  top -= scaleH * ( this.view.offsetY / zoomH );
37496  bottom = top - scaleH * ( this.view.height / zoomH );
37497 
37498  }
37499 
37500  this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far );
37501 
37502  this.projectionMatrixInverse.getInverse( this.projectionMatrix );
37503 
37504  },
37505 
37506  toJSON: function ( meta ) {
37507 
37508  var data = Object3D.prototype.toJSON.call( this, meta );
37509 
37510  data.object.zoom = this.zoom;
37511  data.object.left = this.left;
37512  data.object.right = this.right;
37513  data.object.top = this.top;
37514  data.object.bottom = this.bottom;
37515  data.object.near = this.near;
37516  data.object.far = this.far;
37517 
37518  if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
37519 
37520  return data;
37521 
37522  }
37523 
37524  } );
37525 
37530  function DirectionalLightShadow( ) {
37531 
37532  LightShadow.call( this, new OrthographicCamera( - 5, 5, 5, - 5, 0.5, 500 ) );
37533 
37534  }
37535 
37536  DirectionalLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype ), {
37537 
37538  constructor: DirectionalLightShadow
37539 
37540  } );
37541 
37547  function DirectionalLight( color, intensity ) {
37548 
37549  Light.call( this, color, intensity );
37550 
37551  this.type = 'DirectionalLight';
37552 
37553  this.position.copy( Object3D.DefaultUp );
37554  this.updateMatrix();
37555 
37556  this.target = new Object3D();
37557 
37558  this.shadow = new DirectionalLightShadow();
37559 
37560  }
37561 
37562  DirectionalLight.prototype = Object.assign( Object.create( Light.prototype ), {
37563 
37564  constructor: DirectionalLight,
37565 
37566  isDirectionalLight: true,
37567 
37568  copy: function ( source ) {
37569 
37570  Light.prototype.copy.call( this, source );
37571 
37572  this.target = source.target.clone();
37573 
37574  this.shadow = source.shadow.clone();
37575 
37576  return this;
37577 
37578  }
37579 
37580  } );
37581 
37586  function AmbientLight( color, intensity ) {
37587 
37588  Light.call( this, color, intensity );
37589 
37590  this.type = 'AmbientLight';
37591 
37592  this.castShadow = undefined;
37593 
37594  }
37595 
37596  AmbientLight.prototype = Object.assign( Object.create( Light.prototype ), {
37597 
37598  constructor: AmbientLight,
37599 
37600  isAmbientLight: true
37601 
37602  } );
37603 
37608  function RectAreaLight( color, intensity, width, height ) {
37609 
37610  Light.call( this, color, intensity );
37611 
37612  this.type = 'RectAreaLight';
37613 
37614  this.width = ( width !== undefined ) ? width : 10;
37615  this.height = ( height !== undefined ) ? height : 10;
37616 
37617  }
37618 
37619  RectAreaLight.prototype = Object.assign( Object.create( Light.prototype ), {
37620 
37621  constructor: RectAreaLight,
37622 
37623  isRectAreaLight: true,
37624 
37625  copy: function ( source ) {
37626 
37627  Light.prototype.copy.call( this, source );
37628 
37629  this.width = source.width;
37630  this.height = source.height;
37631 
37632  return this;
37633 
37634  },
37635 
37636  toJSON: function ( meta ) {
37637 
37638  var data = Light.prototype.toJSON.call( this, meta );
37639 
37640  data.object.width = this.width;
37641  data.object.height = this.height;
37642 
37643  return data;
37644 
37645  }
37646 
37647  } );
37648 
37653  function MaterialLoader( manager ) {
37654 
37655  this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
37656  this.textures = {};
37657 
37658  }
37659 
37660  Object.assign( MaterialLoader.prototype, {
37661 
37662  load: function ( url, onLoad, onProgress, onError ) {
37663 
37664  var scope = this;
37665 
37666  var loader = new FileLoader( scope.manager );
37667  loader.setPath( scope.path );
37668  loader.load( url, function ( text ) {
37669 
37670  onLoad( scope.parse( JSON.parse( text ) ) );
37671 
37672  }, onProgress, onError );
37673 
37674  },
37675 
37676  parse: function ( json ) {
37677 
37678  var textures = this.textures;
37679 
37680  function getTexture( name ) {
37681 
37682  if ( textures[ name ] === undefined ) {
37683 
37684  console.warn( 'THREE.MaterialLoader: Undefined texture', name );
37685 
37686  }
37687 
37688  return textures[ name ];
37689 
37690  }
37691 
37692  var material = new Materials[ json.type ]();
37693 
37694  if ( json.uuid !== undefined ) material.uuid = json.uuid;
37695  if ( json.name !== undefined ) material.name = json.name;
37696  if ( json.color !== undefined ) material.color.setHex( json.color );
37697  if ( json.roughness !== undefined ) material.roughness = json.roughness;
37698  if ( json.metalness !== undefined ) material.metalness = json.metalness;
37699  if ( json.emissive !== undefined ) material.emissive.setHex( json.emissive );
37700  if ( json.specular !== undefined ) material.specular.setHex( json.specular );
37701  if ( json.shininess !== undefined ) material.shininess = json.shininess;
37702  if ( json.clearCoat !== undefined ) material.clearCoat = json.clearCoat;
37703  if ( json.clearCoatRoughness !== undefined ) material.clearCoatRoughness = json.clearCoatRoughness;
37704  if ( json.vertexColors !== undefined ) material.vertexColors = json.vertexColors;
37705  if ( json.fog !== undefined ) material.fog = json.fog;
37706  if ( json.flatShading !== undefined ) material.flatShading = json.flatShading;
37707  if ( json.blending !== undefined ) material.blending = json.blending;
37708  if ( json.combine !== undefined ) material.combine = json.combine;
37709  if ( json.side !== undefined ) material.side = json.side;
37710  if ( json.opacity !== undefined ) material.opacity = json.opacity;
37711  if ( json.transparent !== undefined ) material.transparent = json.transparent;
37712  if ( json.alphaTest !== undefined ) material.alphaTest = json.alphaTest;
37713  if ( json.depthTest !== undefined ) material.depthTest = json.depthTest;
37714  if ( json.depthWrite !== undefined ) material.depthWrite = json.depthWrite;
37715  if ( json.colorWrite !== undefined ) material.colorWrite = json.colorWrite;
37716  if ( json.wireframe !== undefined ) material.wireframe = json.wireframe;
37717  if ( json.wireframeLinewidth !== undefined ) material.wireframeLinewidth = json.wireframeLinewidth;
37718  if ( json.wireframeLinecap !== undefined ) material.wireframeLinecap = json.wireframeLinecap;
37719  if ( json.wireframeLinejoin !== undefined ) material.wireframeLinejoin = json.wireframeLinejoin;
37720 
37721  if ( json.rotation !== undefined ) material.rotation = json.rotation;
37722 
37723  if ( json.linewidth !== 1 ) material.linewidth = json.linewidth;
37724  if ( json.dashSize !== undefined ) material.dashSize = json.dashSize;
37725  if ( json.gapSize !== undefined ) material.gapSize = json.gapSize;
37726  if ( json.scale !== undefined ) material.scale = json.scale;
37727 
37728  if ( json.polygonOffset !== undefined ) material.polygonOffset = json.polygonOffset;
37729  if ( json.polygonOffsetFactor !== undefined ) material.polygonOffsetFactor = json.polygonOffsetFactor;
37730  if ( json.polygonOffsetUnits !== undefined ) material.polygonOffsetUnits = json.polygonOffsetUnits;
37731 
37732  if ( json.skinning !== undefined ) material.skinning = json.skinning;
37733  if ( json.morphTargets !== undefined ) material.morphTargets = json.morphTargets;
37734  if ( json.dithering !== undefined ) material.dithering = json.dithering;
37735 
37736  if ( json.visible !== undefined ) material.visible = json.visible;
37737  if ( json.userData !== undefined ) material.userData = json.userData;
37738 
37739  // Shader Material
37740 
37741  if ( json.uniforms !== undefined ) {
37742 
37743  for ( var name in json.uniforms ) {
37744 
37745  var uniform = json.uniforms[ name ];
37746 
37747  material.uniforms[ name ] = {};
37748 
37749  switch ( uniform.type ) {
37750 
37751  case 't':
37752  material.uniforms[ name ].value = getTexture( uniform.value );
37753  break;
37754 
37755  case 'c':
37756  material.uniforms[ name ].value = new Color().setHex( uniform.value );
37757  break;
37758 
37759  case 'v2':
37760  material.uniforms[ name ].value = new Vector2().fromArray( uniform.value );
37761  break;
37762 
37763  case 'v3':
37764  material.uniforms[ name ].value = new Vector3().fromArray( uniform.value );
37765  break;
37766 
37767  case 'v4':
37768  material.uniforms[ name ].value = new Vector4().fromArray( uniform.value );
37769  break;
37770 
37771  case 'm3':
37772  material.uniforms[ name ].value = new Matrix3().fromArray( uniform.value );
37773 
37774  case 'm4':
37775  material.uniforms[ name ].value = new Matrix4().fromArray( uniform.value );
37776  break;
37777 
37778  default:
37779  material.uniforms[ name ].value = uniform.value;
37780 
37781  }
37782 
37783  }
37784 
37785  }
37786 
37787  if ( json.defines !== undefined ) material.defines = json.defines;
37788  if ( json.vertexShader !== undefined ) material.vertexShader = json.vertexShader;
37789  if ( json.fragmentShader !== undefined ) material.fragmentShader = json.fragmentShader;
37790 
37791  if ( json.extensions !== undefined ) {
37792 
37793  for ( var key in json.extensions ) {
37794 
37795  material.extensions[ key ] = json.extensions[ key ];
37796 
37797  }
37798 
37799  }
37800 
37801  // Deprecated
37802 
37803  if ( json.shading !== undefined ) material.flatShading = json.shading === 1; // THREE.FlatShading
37804 
37805  // for PointsMaterial
37806 
37807  if ( json.size !== undefined ) material.size = json.size;
37808  if ( json.sizeAttenuation !== undefined ) material.sizeAttenuation = json.sizeAttenuation;
37809 
37810  // maps
37811 
37812  if ( json.map !== undefined ) material.map = getTexture( json.map );
37813 
37814  if ( json.alphaMap !== undefined ) {
37815 
37816  material.alphaMap = getTexture( json.alphaMap );
37817  material.transparent = true;
37818 
37819  }
37820 
37821  if ( json.bumpMap !== undefined ) material.bumpMap = getTexture( json.bumpMap );
37822  if ( json.bumpScale !== undefined ) material.bumpScale = json.bumpScale;
37823 
37824  if ( json.normalMap !== undefined ) material.normalMap = getTexture( json.normalMap );
37825  if ( json.normalMapType !== undefined ) material.normalMapType = json.normalMapType;
37826  if ( json.normalScale !== undefined ) {
37827 
37828  var normalScale = json.normalScale;
37829 
37830  if ( Array.isArray( normalScale ) === false ) {
37831 
37832  // Blender exporter used to export a scalar. See #7459
37833 
37834  normalScale = [ normalScale, normalScale ];
37835 
37836  }
37837 
37838  material.normalScale = new Vector2().fromArray( normalScale );
37839 
37840  }
37841 
37842  if ( json.displacementMap !== undefined ) material.displacementMap = getTexture( json.displacementMap );
37843  if ( json.displacementScale !== undefined ) material.displacementScale = json.displacementScale;
37844  if ( json.displacementBias !== undefined ) material.displacementBias = json.displacementBias;
37845 
37846  if ( json.roughnessMap !== undefined ) material.roughnessMap = getTexture( json.roughnessMap );
37847  if ( json.metalnessMap !== undefined ) material.metalnessMap = getTexture( json.metalnessMap );
37848 
37849  if ( json.emissiveMap !== undefined ) material.emissiveMap = getTexture( json.emissiveMap );
37850  if ( json.emissiveIntensity !== undefined ) material.emissiveIntensity = json.emissiveIntensity;
37851 
37852  if ( json.specularMap !== undefined ) material.specularMap = getTexture( json.specularMap );
37853 
37854  if ( json.envMap !== undefined ) material.envMap = getTexture( json.envMap );
37855  if ( json.envMapIntensity !== undefined ) material.envMapIntensity = json.envMapIntensity;
37856 
37857  if ( json.reflectivity !== undefined ) material.reflectivity = json.reflectivity;
37858 
37859  if ( json.lightMap !== undefined ) material.lightMap = getTexture( json.lightMap );
37860  if ( json.lightMapIntensity !== undefined ) material.lightMapIntensity = json.lightMapIntensity;
37861 
37862  if ( json.aoMap !== undefined ) material.aoMap = getTexture( json.aoMap );
37863  if ( json.aoMapIntensity !== undefined ) material.aoMapIntensity = json.aoMapIntensity;
37864 
37865  if ( json.gradientMap !== undefined ) material.gradientMap = getTexture( json.gradientMap );
37866 
37867  return material;
37868 
37869  },
37870 
37871  setPath: function ( value ) {
37872 
37873  this.path = value;
37874  return this;
37875 
37876  },
37877 
37878  setTextures: function ( value ) {
37879 
37880  this.textures = value;
37881  return this;
37882 
37883  }
37884 
37885  } );
37886 
37891  var LoaderUtils = {
37892 
37893  decodeText: function ( array ) {
37894 
37895  if ( typeof TextDecoder !== 'undefined' ) {
37896 
37897  return new TextDecoder().decode( array );
37898 
37899  }
37900 
37901  // Avoid the String.fromCharCode.apply(null, array) shortcut, which
37902  // throws a "maximum call stack size exceeded" error for large arrays.
37903 
37904  var s = '';
37905 
37906  for ( var i = 0, il = array.length; i < il; i ++ ) {
37907 
37908  // Implicitly assumes little-endian.
37909  s += String.fromCharCode( array[ i ] );
37910 
37911  }
37912 
37913  // Merges multi-byte utf-8 characters.
37914  return decodeURIComponent( escape( s ) );
37915 
37916  },
37917 
37918  extractUrlBase: function ( url ) {
37919 
37920  var index = url.lastIndexOf( '/' );
37921 
37922  if ( index === - 1 ) return './';
37923 
37924  return url.substr( 0, index + 1 );
37925 
37926  }
37927 
37928  };
37929 
37934  function BufferGeometryLoader( manager ) {
37935 
37936  this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
37937 
37938  }
37939 
37940  Object.assign( BufferGeometryLoader.prototype, {
37941 
37942  load: function ( url, onLoad, onProgress, onError ) {
37943 
37944  var scope = this;
37945 
37946  var loader = new FileLoader( scope.manager );
37947  loader.setPath( scope.path );
37948  loader.load( url, function ( text ) {
37949 
37950  onLoad( scope.parse( JSON.parse( text ) ) );
37951 
37952  }, onProgress, onError );
37953 
37954  },
37955 
37956  parse: function ( json ) {
37957 
37958  var geometry = new BufferGeometry();
37959 
37960  var index = json.data.index;
37961 
37962  if ( index !== undefined ) {
37963 
37964  var typedArray = new TYPED_ARRAYS[ index.type ]( index.array );
37965  geometry.setIndex( new BufferAttribute( typedArray, 1 ) );
37966 
37967  }
37968 
37969  var attributes = json.data.attributes;
37970 
37971  for ( var key in attributes ) {
37972 
37973  var attribute = attributes[ key ];
37974  var typedArray = new TYPED_ARRAYS[ attribute.type ]( attribute.array );
37975 
37976  var bufferAttribute = new BufferAttribute( typedArray, attribute.itemSize, attribute.normalized );
37977  if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name;
37978  geometry.addAttribute( key, bufferAttribute );
37979 
37980  }
37981 
37982  var morphAttributes = json.data.morphAttributes;
37983 
37984  if ( morphAttributes ) {
37985 
37986  for ( var key in morphAttributes ) {
37987 
37988  var attributeArray = morphAttributes[ key ];
37989 
37990  var array = [];
37991 
37992  for ( var i = 0, il = attributeArray.length; i < il; i ++ ) {
37993 
37994  var attribute = attributeArray[ i ];
37995  var typedArray = new TYPED_ARRAYS[ attribute.type ]( attribute.array );
37996 
37997  var bufferAttribute = new BufferAttribute( typedArray, attribute.itemSize, attribute.normalized );
37998  if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name;
37999  array.push( bufferAttribute );
38000 
38001  }
38002 
38003  geometry.morphAttributes[ key ] = array;
38004 
38005  }
38006 
38007  }
38008 
38009  var groups = json.data.groups || json.data.drawcalls || json.data.offsets;
38010 
38011  if ( groups !== undefined ) {
38012 
38013  for ( var i = 0, n = groups.length; i !== n; ++ i ) {
38014 
38015  var group = groups[ i ];
38016 
38017  geometry.addGroup( group.start, group.count, group.materialIndex );
38018 
38019  }
38020 
38021  }
38022 
38023  var boundingSphere = json.data.boundingSphere;
38024 
38025  if ( boundingSphere !== undefined ) {
38026 
38027  var center = new Vector3();
38028 
38029  if ( boundingSphere.center !== undefined ) {
38030 
38031  center.fromArray( boundingSphere.center );
38032 
38033  }
38034 
38035  geometry.boundingSphere = new Sphere( center, boundingSphere.radius );
38036 
38037  }
38038 
38039  if ( json.name ) geometry.name = json.name;
38040  if ( json.userData ) geometry.userData = json.userData;
38041 
38042  return geometry;
38043 
38044  },
38045 
38046  setPath: function ( value ) {
38047 
38048  this.path = value;
38049  return this;
38050 
38051  }
38052 
38053  } );
38054 
38055  var TYPED_ARRAYS = {
38056  Int8Array: Int8Array,
38057  Uint8Array: Uint8Array,
38058  // Workaround for IE11 pre KB2929437. See #11440
38059  Uint8ClampedArray: typeof Uint8ClampedArray !== 'undefined' ? Uint8ClampedArray : Uint8Array,
38060  Int16Array: Int16Array,
38061  Uint16Array: Uint16Array,
38062  Int32Array: Int32Array,
38063  Uint32Array: Uint32Array,
38064  Float32Array: Float32Array,
38065  Float64Array: Float64Array
38066  };
38067 
38072  function ObjectLoader( manager ) {
38073 
38074  this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
38075  this.resourcePath = '';
38076 
38077  }
38078 
38079  Object.assign( ObjectLoader.prototype, {
38080 
38081  crossOrigin: 'anonymous',
38082 
38083  load: function ( url, onLoad, onProgress, onError ) {
38084 
38085  var scope = this;
38086 
38087  var path = ( this.path === undefined ) ? LoaderUtils.extractUrlBase( url ) : this.path;
38088  this.resourcePath = this.resourcePath || path;
38089 
38090  var loader = new FileLoader( scope.manager );
38091  loader.setPath( this.path );
38092  loader.load( url, function ( text ) {
38093 
38094  var json = null;
38095 
38096  try {
38097 
38098  json = JSON.parse( text );
38099 
38100  } catch ( error ) {
38101 
38102  if ( onError !== undefined ) onError( error );
38103 
38104  console.error( 'THREE:ObjectLoader: Can\'t parse ' + url + '.', error.message );
38105 
38106  return;
38107 
38108  }
38109 
38110  var metadata = json.metadata;
38111 
38112  if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) {
38113 
38114  console.error( 'THREE.ObjectLoader: Can\'t load ' + url );
38115  return;
38116 
38117  }
38118 
38119  scope.parse( json, onLoad );
38120 
38121  }, onProgress, onError );
38122 
38123  },
38124 
38125  setPath: function ( value ) {
38126 
38127  this.path = value;
38128  return this;
38129 
38130  },
38131 
38132  setResourcePath: function ( value ) {
38133 
38134  this.resourcePath = value;
38135  return this;
38136 
38137  },
38138 
38139  setCrossOrigin: function ( value ) {
38140 
38141  this.crossOrigin = value;
38142  return this;
38143 
38144  },
38145 
38146  parse: function ( json, onLoad ) {
38147 
38148  var shapes = this.parseShape( json.shapes );
38149  var geometries = this.parseGeometries( json.geometries, shapes );
38150 
38151  var images = this.parseImages( json.images, function () {
38152 
38153  if ( onLoad !== undefined ) onLoad( object );
38154 
38155  } );
38156 
38157  var textures = this.parseTextures( json.textures, images );
38158  var materials = this.parseMaterials( json.materials, textures );
38159 
38160  var object = this.parseObject( json.object, geometries, materials );
38161 
38162  if ( json.animations ) {
38163 
38164  object.animations = this.parseAnimations( json.animations );
38165 
38166  }
38167 
38168  if ( json.images === undefined || json.images.length === 0 ) {
38169 
38170  if ( onLoad !== undefined ) onLoad( object );
38171 
38172  }
38173 
38174  return object;
38175 
38176  },
38177 
38178  parseShape: function ( json ) {
38179 
38180  var shapes = {};
38181 
38182  if ( json !== undefined ) {
38183 
38184  for ( var i = 0, l = json.length; i < l; i ++ ) {
38185 
38186  var shape = new Shape().fromJSON( json[ i ] );
38187 
38188  shapes[ shape.uuid ] = shape;
38189 
38190  }
38191 
38192  }
38193 
38194  return shapes;
38195 
38196  },
38197 
38198  parseGeometries: function ( json, shapes ) {
38199 
38200  var geometries = {};
38201 
38202  if ( json !== undefined ) {
38203 
38204  var bufferGeometryLoader = new BufferGeometryLoader();
38205 
38206  for ( var i = 0, l = json.length; i < l; i ++ ) {
38207 
38208  var geometry;
38209  var data = json[ i ];
38210 
38211  switch ( data.type ) {
38212 
38213  case 'PlaneGeometry':
38214  case 'PlaneBufferGeometry':
38215 
38216  geometry = new Geometries[ data.type ](
38217  data.width,
38218  data.height,
38219  data.widthSegments,
38220  data.heightSegments
38221  );
38222 
38223  break;
38224 
38225  case 'BoxGeometry':
38226  case 'BoxBufferGeometry':
38227  case 'CubeGeometry': // backwards compatible
38228 
38229  geometry = new Geometries[ data.type ](
38230  data.width,
38231  data.height,
38232  data.depth,
38233  data.widthSegments,
38234  data.heightSegments,
38235  data.depthSegments
38236  );
38237 
38238  break;
38239 
38240  case 'CircleGeometry':
38241  case 'CircleBufferGeometry':
38242 
38243  geometry = new Geometries[ data.type ](
38244  data.radius,
38245  data.segments,
38246  data.thetaStart,
38247  data.thetaLength
38248  );
38249 
38250  break;
38251 
38252  case 'CylinderGeometry':
38253  case 'CylinderBufferGeometry':
38254 
38255  geometry = new Geometries[ data.type ](
38256  data.radiusTop,
38257  data.radiusBottom,
38258  data.height,
38259  data.radialSegments,
38260  data.heightSegments,
38261  data.openEnded,
38262  data.thetaStart,
38263  data.thetaLength
38264  );
38265 
38266  break;
38267 
38268  case 'ConeGeometry':
38269  case 'ConeBufferGeometry':
38270 
38271  geometry = new Geometries[ data.type ](
38272  data.radius,
38273  data.height,
38274  data.radialSegments,
38275  data.heightSegments,
38276  data.openEnded,
38277  data.thetaStart,
38278  data.thetaLength
38279  );
38280 
38281  break;
38282 
38283  case 'SphereGeometry':
38284  case 'SphereBufferGeometry':
38285 
38286  geometry = new Geometries[ data.type ](
38287  data.radius,
38288  data.widthSegments,
38289  data.heightSegments,
38290  data.phiStart,
38291  data.phiLength,
38292  data.thetaStart,
38293  data.thetaLength
38294  );
38295 
38296  break;
38297 
38298  case 'DodecahedronGeometry':
38299  case 'DodecahedronBufferGeometry':
38300  case 'IcosahedronGeometry':
38301  case 'IcosahedronBufferGeometry':
38302  case 'OctahedronGeometry':
38303  case 'OctahedronBufferGeometry':
38304  case 'TetrahedronGeometry':
38305  case 'TetrahedronBufferGeometry':
38306 
38307  geometry = new Geometries[ data.type ](
38308  data.radius,
38309  data.detail
38310  );
38311 
38312  break;
38313 
38314  case 'RingGeometry':
38315  case 'RingBufferGeometry':
38316 
38317  geometry = new Geometries[ data.type ](
38318  data.innerRadius,
38319  data.outerRadius,
38320  data.thetaSegments,
38321  data.phiSegments,
38322  data.thetaStart,
38323  data.thetaLength
38324  );
38325 
38326  break;
38327 
38328  case 'TorusGeometry':
38329  case 'TorusBufferGeometry':
38330 
38331  geometry = new Geometries[ data.type ](
38332  data.radius,
38333  data.tube,
38334  data.radialSegments,
38335  data.tubularSegments,
38336  data.arc
38337  );
38338 
38339  break;
38340 
38341  case 'TorusKnotGeometry':
38342  case 'TorusKnotBufferGeometry':
38343 
38344  geometry = new Geometries[ data.type ](
38345  data.radius,
38346  data.tube,
38347  data.tubularSegments,
38348  data.radialSegments,
38349  data.p,
38350  data.q
38351  );
38352 
38353  break;
38354 
38355  case 'TubeGeometry':
38356  case 'TubeBufferGeometry':
38357 
38358  // This only works for built-in curves (e.g. CatmullRomCurve3).
38359  // User defined curves or instances of CurvePath will not be deserialized.
38360  geometry = new Geometries[ data.type ](
38361  new Curves[ data.path.type ]().fromJSON( data.path ),
38362  data.tubularSegments,
38363  data.radius,
38364  data.radialSegments,
38365  data.closed
38366  );
38367 
38368  break;
38369 
38370  case 'LatheGeometry':
38371  case 'LatheBufferGeometry':
38372 
38373  geometry = new Geometries[ data.type ](
38374  data.points,
38375  data.segments,
38376  data.phiStart,
38377  data.phiLength
38378  );
38379 
38380  break;
38381 
38382  case 'PolyhedronGeometry':
38383  case 'PolyhedronBufferGeometry':
38384 
38385  geometry = new Geometries[ data.type ](
38386  data.vertices,
38387  data.indices,
38388  data.radius,
38389  data.details
38390  );
38391 
38392  break;
38393 
38394  case 'ShapeGeometry':
38395  case 'ShapeBufferGeometry':
38396 
38397  var geometryShapes = [];
38398 
38399  for ( var j = 0, jl = data.shapes.length; j < jl; j ++ ) {
38400 
38401  var shape = shapes[ data.shapes[ j ] ];
38402 
38403  geometryShapes.push( shape );
38404 
38405  }
38406 
38407  geometry = new Geometries[ data.type ](
38408  geometryShapes,
38409  data.curveSegments
38410  );
38411 
38412  break;
38413 
38414 
38415  case 'ExtrudeGeometry':
38416  case 'ExtrudeBufferGeometry':
38417 
38418  var geometryShapes = [];
38419 
38420  for ( var j = 0, jl = data.shapes.length; j < jl; j ++ ) {
38421 
38422  var shape = shapes[ data.shapes[ j ] ];
38423 
38424  geometryShapes.push( shape );
38425 
38426  }
38427 
38428  var extrudePath = data.options.extrudePath;
38429 
38430  if ( extrudePath !== undefined ) {
38431 
38432  data.options.extrudePath = new Curves[ extrudePath.type ]().fromJSON( extrudePath );
38433 
38434  }
38435 
38436  geometry = new Geometries[ data.type ](
38437  geometryShapes,
38438  data.options
38439  );
38440 
38441  break;
38442 
38443  case 'BufferGeometry':
38444 
38445  geometry = bufferGeometryLoader.parse( data );
38446 
38447  break;
38448 
38449  case 'Geometry':
38450 
38451  if ( 'THREE' in window && 'LegacyJSONLoader' in THREE ) {
38452 
38453  var geometryLoader = new THREE.LegacyJSONLoader();
38454  geometry = geometryLoader.parse( data, this.resourcePath ).geometry;
38455 
38456 
38457  } else {
38458 
38459  console.error( 'THREE.ObjectLoader: You have to import LegacyJSONLoader in order load geometry data of type "Geometry".' );
38460 
38461  }
38462 
38463  break;
38464 
38465  default:
38466 
38467  console.warn( 'THREE.ObjectLoader: Unsupported geometry type "' + data.type + '"' );
38468 
38469  continue;
38470 
38471  }
38472 
38473  geometry.uuid = data.uuid;
38474 
38475  if ( data.name !== undefined ) geometry.name = data.name;
38476  if ( geometry.isBufferGeometry === true && data.userData !== undefined ) geometry.userData = data.userData;
38477 
38478  geometries[ data.uuid ] = geometry;
38479 
38480  }
38481 
38482  }
38483 
38484  return geometries;
38485 
38486  },
38487 
38488  parseMaterials: function ( json, textures ) {
38489 
38490  var cache = {}; // MultiMaterial
38491  var materials = {};
38492 
38493  if ( json !== undefined ) {
38494 
38495  var loader = new MaterialLoader();
38496  loader.setTextures( textures );
38497 
38498  for ( var i = 0, l = json.length; i < l; i ++ ) {
38499 
38500  var data = json[ i ];
38501 
38502  if ( data.type === 'MultiMaterial' ) {
38503 
38504  // Deprecated
38505 
38506  var array = [];
38507 
38508  for ( var j = 0; j < data.materials.length; j ++ ) {
38509 
38510  var material = data.materials[ j ];
38511 
38512  if ( cache[ material.uuid ] === undefined ) {
38513 
38514  cache[ material.uuid ] = loader.parse( material );
38515 
38516  }
38517 
38518  array.push( cache[ material.uuid ] );
38519 
38520  }
38521 
38522  materials[ data.uuid ] = array;
38523 
38524  } else {
38525 
38526  if ( cache[ data.uuid ] === undefined ) {
38527 
38528  cache[ data.uuid ] = loader.parse( data );
38529 
38530  }
38531 
38532  materials[ data.uuid ] = cache[ data.uuid ];
38533 
38534  }
38535 
38536  }
38537 
38538  }
38539 
38540  return materials;
38541 
38542  },
38543 
38544  parseAnimations: function ( json ) {
38545 
38546  var animations = [];
38547 
38548  for ( var i = 0; i < json.length; i ++ ) {
38549 
38550  var data = json[ i ];
38551 
38552  var clip = AnimationClip.parse( data );
38553 
38554  if ( data.uuid !== undefined ) clip.uuid = data.uuid;
38555 
38556  animations.push( clip );
38557 
38558  }
38559 
38560  return animations;
38561 
38562  },
38563 
38564  parseImages: function ( json, onLoad ) {
38565 
38566  var scope = this;
38567  var images = {};
38568 
38569  function loadImage( url ) {
38570 
38571  scope.manager.itemStart( url );
38572 
38573  return loader.load( url, function () {
38574 
38575  scope.manager.itemEnd( url );
38576 
38577  }, undefined, function () {
38578 
38579  scope.manager.itemError( url );
38580  scope.manager.itemEnd( url );
38581 
38582  } );
38583 
38584  }
38585 
38586  if ( json !== undefined && json.length > 0 ) {
38587 
38588  var manager = new LoadingManager( onLoad );
38589 
38590  var loader = new ImageLoader( manager );
38591  loader.setCrossOrigin( this.crossOrigin );
38592 
38593  for ( var i = 0, il = json.length; i < il; i ++ ) {
38594 
38595  var image = json[ i ];
38596  var url = image.url;
38597 
38598  if ( Array.isArray( url ) ) {
38599 
38600  // load array of images e.g CubeTexture
38601 
38602  images[ image.uuid ] = [];
38603 
38604  for ( var j = 0, jl = url.length; j < jl; j ++ ) {
38605 
38606  var currentUrl = url[ j ];
38607 
38608  var path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( currentUrl ) ? currentUrl : scope.resourcePath + currentUrl;
38609 
38610  images[ image.uuid ].push( loadImage( path ) );
38611 
38612  }
38613 
38614  } else {
38615 
38616  // load single image
38617 
38618  var path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( image.url ) ? image.url : scope.resourcePath + image.url;
38619 
38620  images[ image.uuid ] = loadImage( path );
38621 
38622  }
38623 
38624  }
38625 
38626  }
38627 
38628  return images;
38629 
38630  },
38631 
38632  parseTextures: function ( json, images ) {
38633 
38634  function parseConstant( value, type ) {
38635 
38636  if ( typeof value === 'number' ) return value;
38637 
38638  console.warn( 'THREE.ObjectLoader.parseTexture: Constant should be in numeric form.', value );
38639 
38640  return type[ value ];
38641 
38642  }
38643 
38644  var textures = {};
38645 
38646  if ( json !== undefined ) {
38647 
38648  for ( var i = 0, l = json.length; i < l; i ++ ) {
38649 
38650  var data = json[ i ];
38651 
38652  if ( data.image === undefined ) {
38653 
38654  console.warn( 'THREE.ObjectLoader: No "image" specified for', data.uuid );
38655 
38656  }
38657 
38658  if ( images[ data.image ] === undefined ) {
38659 
38660  console.warn( 'THREE.ObjectLoader: Undefined image', data.image );
38661 
38662  }
38663 
38664  var texture;
38665 
38666  if ( Array.isArray( images[ data.image ] ) ) {
38667 
38668  texture = new CubeTexture( images[ data.image ] );
38669 
38670  } else {
38671 
38672  texture = new Texture( images[ data.image ] );
38673 
38674  }
38675 
38676  texture.needsUpdate = true;
38677 
38678  texture.uuid = data.uuid;
38679 
38680  if ( data.name !== undefined ) texture.name = data.name;
38681 
38682  if ( data.mapping !== undefined ) texture.mapping = parseConstant( data.mapping, TEXTURE_MAPPING );
38683 
38684  if ( data.offset !== undefined ) texture.offset.fromArray( data.offset );
38685  if ( data.repeat !== undefined ) texture.repeat.fromArray( data.repeat );
38686  if ( data.center !== undefined ) texture.center.fromArray( data.center );
38687  if ( data.rotation !== undefined ) texture.rotation = data.rotation;
38688 
38689  if ( data.wrap !== undefined ) {
38690 
38691  texture.wrapS = parseConstant( data.wrap[ 0 ], TEXTURE_WRAPPING );
38692  texture.wrapT = parseConstant( data.wrap[ 1 ], TEXTURE_WRAPPING );
38693 
38694  }
38695 
38696  if ( data.format !== undefined ) texture.format = data.format;
38697  if ( data.type !== undefined ) texture.type = data.type;
38698  if ( data.encoding !== undefined ) texture.encoding = data.encoding;
38699 
38700  if ( data.minFilter !== undefined ) texture.minFilter = parseConstant( data.minFilter, TEXTURE_FILTER );
38701  if ( data.magFilter !== undefined ) texture.magFilter = parseConstant( data.magFilter, TEXTURE_FILTER );
38702  if ( data.anisotropy !== undefined ) texture.anisotropy = data.anisotropy;
38703 
38704  if ( data.flipY !== undefined ) texture.flipY = data.flipY;
38705 
38706  if ( data.premultiplyAlpha !== undefined ) texture.premultiplyAlpha = data.premultiplyAlpha;
38707  if ( data.unpackAlignment !== undefined ) texture.unpackAlignment = data.unpackAlignment;
38708 
38709  textures[ data.uuid ] = texture;
38710 
38711  }
38712 
38713  }
38714 
38715  return textures;
38716 
38717  },
38718 
38719  parseObject: function ( data, geometries, materials ) {
38720 
38721  var object;
38722 
38723  function getGeometry( name ) {
38724 
38725  if ( geometries[ name ] === undefined ) {
38726 
38727  console.warn( 'THREE.ObjectLoader: Undefined geometry', name );
38728 
38729  }
38730 
38731  return geometries[ name ];
38732 
38733  }
38734 
38735  function getMaterial( name ) {
38736 
38737  if ( name === undefined ) return undefined;
38738 
38739  if ( Array.isArray( name ) ) {
38740 
38741  var array = [];
38742 
38743  for ( var i = 0, l = name.length; i < l; i ++ ) {
38744 
38745  var uuid = name[ i ];
38746 
38747  if ( materials[ uuid ] === undefined ) {
38748 
38749  console.warn( 'THREE.ObjectLoader: Undefined material', uuid );
38750 
38751  }
38752 
38753  array.push( materials[ uuid ] );
38754 
38755  }
38756 
38757  return array;
38758 
38759  }
38760 
38761  if ( materials[ name ] === undefined ) {
38762 
38763  console.warn( 'THREE.ObjectLoader: Undefined material', name );
38764 
38765  }
38766 
38767  return materials[ name ];
38768 
38769  }
38770 
38771  switch ( data.type ) {
38772 
38773  case 'Scene':
38774 
38775  object = new Scene();
38776 
38777  if ( data.background !== undefined ) {
38778 
38779  if ( Number.isInteger( data.background ) ) {
38780 
38781  object.background = new Color( data.background );
38782 
38783  }
38784 
38785  }
38786 
38787  if ( data.fog !== undefined ) {
38788 
38789  if ( data.fog.type === 'Fog' ) {
38790 
38791  object.fog = new Fog( data.fog.color, data.fog.near, data.fog.far );
38792 
38793  } else if ( data.fog.type === 'FogExp2' ) {
38794 
38795  object.fog = new FogExp2( data.fog.color, data.fog.density );
38796 
38797  }
38798 
38799  }
38800 
38801  break;
38802 
38803  case 'PerspectiveCamera':
38804 
38805  object = new PerspectiveCamera( data.fov, data.aspect, data.near, data.far );
38806 
38807  if ( data.focus !== undefined ) object.focus = data.focus;
38808  if ( data.zoom !== undefined ) object.zoom = data.zoom;
38809  if ( data.filmGauge !== undefined ) object.filmGauge = data.filmGauge;
38810  if ( data.filmOffset !== undefined ) object.filmOffset = data.filmOffset;
38811  if ( data.view !== undefined ) object.view = Object.assign( {}, data.view );
38812 
38813  break;
38814 
38815  case 'OrthographicCamera':
38816 
38817  object = new OrthographicCamera( data.left, data.right, data.top, data.bottom, data.near, data.far );
38818 
38819  if ( data.zoom !== undefined ) object.zoom = data.zoom;
38820  if ( data.view !== undefined ) object.view = Object.assign( {}, data.view );
38821 
38822  break;
38823 
38824  case 'AmbientLight':
38825 
38826  object = new AmbientLight( data.color, data.intensity );
38827 
38828  break;
38829 
38830  case 'DirectionalLight':
38831 
38832  object = new DirectionalLight( data.color, data.intensity );
38833 
38834  break;
38835 
38836  case 'PointLight':
38837 
38838  object = new PointLight( data.color, data.intensity, data.distance, data.decay );
38839 
38840  break;
38841 
38842  case 'RectAreaLight':
38843 
38844  object = new RectAreaLight( data.color, data.intensity, data.width, data.height );
38845 
38846  break;
38847 
38848  case 'SpotLight':
38849 
38850  object = new SpotLight( data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay );
38851 
38852  break;
38853 
38854  case 'HemisphereLight':
38855 
38856  object = new HemisphereLight( data.color, data.groundColor, data.intensity );
38857 
38858  break;
38859 
38860  case 'SkinnedMesh':
38861 
38862  console.warn( 'THREE.ObjectLoader.parseObject() does not support SkinnedMesh yet.' );
38863 
38864  case 'Mesh':
38865 
38866  var geometry = getGeometry( data.geometry );
38867  var material = getMaterial( data.material );
38868 
38869  if ( geometry.bones && geometry.bones.length > 0 ) {
38870 
38871  object = new SkinnedMesh( geometry, material );
38872 
38873  } else {
38874 
38875  object = new Mesh( geometry, material );
38876 
38877  }
38878 
38879  if ( data.drawMode !== undefined ) object.setDrawMode( data.drawMode );
38880 
38881  break;
38882 
38883  case 'LOD':
38884 
38885  object = new LOD();
38886 
38887  break;
38888 
38889  case 'Line':
38890 
38891  object = new Line( getGeometry( data.geometry ), getMaterial( data.material ), data.mode );
38892 
38893  break;
38894 
38895  case 'LineLoop':
38896 
38897  object = new LineLoop( getGeometry( data.geometry ), getMaterial( data.material ) );
38898 
38899  break;
38900 
38901  case 'LineSegments':
38902 
38903  object = new LineSegments( getGeometry( data.geometry ), getMaterial( data.material ) );
38904 
38905  break;
38906 
38907  case 'PointCloud':
38908  case 'Points':
38909 
38910  object = new Points( getGeometry( data.geometry ), getMaterial( data.material ) );
38911 
38912  break;
38913 
38914  case 'Sprite':
38915 
38916  object = new Sprite( getMaterial( data.material ) );
38917 
38918  break;
38919 
38920  case 'Group':
38921 
38922  object = new Group();
38923 
38924  break;
38925 
38926  default:
38927 
38928  object = new Object3D();
38929 
38930  }
38931 
38932  object.uuid = data.uuid;
38933 
38934  if ( data.name !== undefined ) object.name = data.name;
38935 
38936  if ( data.matrix !== undefined ) {
38937 
38938  object.matrix.fromArray( data.matrix );
38939 
38940  if ( data.matrixAutoUpdate !== undefined ) object.matrixAutoUpdate = data.matrixAutoUpdate;
38941  if ( object.matrixAutoUpdate ) object.matrix.decompose( object.position, object.quaternion, object.scale );
38942 
38943  } else {
38944 
38945  if ( data.position !== undefined ) object.position.fromArray( data.position );
38946  if ( data.rotation !== undefined ) object.rotation.fromArray( data.rotation );
38947  if ( data.quaternion !== undefined ) object.quaternion.fromArray( data.quaternion );
38948  if ( data.scale !== undefined ) object.scale.fromArray( data.scale );
38949 
38950  }
38951 
38952  if ( data.castShadow !== undefined ) object.castShadow = data.castShadow;
38953  if ( data.receiveShadow !== undefined ) object.receiveShadow = data.receiveShadow;
38954 
38955  if ( data.shadow ) {
38956 
38957  if ( data.shadow.bias !== undefined ) object.shadow.bias = data.shadow.bias;
38958  if ( data.shadow.radius !== undefined ) object.shadow.radius = data.shadow.radius;
38959  if ( data.shadow.mapSize !== undefined ) object.shadow.mapSize.fromArray( data.shadow.mapSize );
38960  if ( data.shadow.camera !== undefined ) object.shadow.camera = this.parseObject( data.shadow.camera );
38961 
38962  }
38963 
38964  if ( data.visible !== undefined ) object.visible = data.visible;
38965  if ( data.frustumCulled !== undefined ) object.frustumCulled = data.frustumCulled;
38966  if ( data.renderOrder !== undefined ) object.renderOrder = data.renderOrder;
38967  if ( data.userData !== undefined ) object.userData = data.userData;
38968  if ( data.layers !== undefined ) object.layers.mask = data.layers;
38969 
38970  if ( data.children !== undefined ) {
38971 
38972  var children = data.children;
38973 
38974  for ( var i = 0; i < children.length; i ++ ) {
38975 
38976  object.add( this.parseObject( children[ i ], geometries, materials ) );
38977 
38978  }
38979 
38980  }
38981 
38982  if ( data.type === 'LOD' ) {
38983 
38984  var levels = data.levels;
38985 
38986  for ( var l = 0; l < levels.length; l ++ ) {
38987 
38988  var level = levels[ l ];
38989  var child = object.getObjectByProperty( 'uuid', level.object );
38990 
38991  if ( child !== undefined ) {
38992 
38993  object.addLevel( child, level.distance );
38994 
38995  }
38996 
38997  }
38998 
38999  }
39000 
39001  return object;
39002 
39003  }
39004 
39005  } );
39006 
39007  var TEXTURE_MAPPING = {
39008  UVMapping: UVMapping,
39009  CubeReflectionMapping: CubeReflectionMapping,
39010  CubeRefractionMapping: CubeRefractionMapping,
39011  EquirectangularReflectionMapping: EquirectangularReflectionMapping,
39012  EquirectangularRefractionMapping: EquirectangularRefractionMapping,
39013  SphericalReflectionMapping: SphericalReflectionMapping,
39014  CubeUVReflectionMapping: CubeUVReflectionMapping,
39015  CubeUVRefractionMapping: CubeUVRefractionMapping
39016  };
39017 
39018  var TEXTURE_WRAPPING = {
39019  RepeatWrapping: RepeatWrapping,
39020  ClampToEdgeWrapping: ClampToEdgeWrapping,
39021  MirroredRepeatWrapping: MirroredRepeatWrapping
39022  };
39023 
39024  var TEXTURE_FILTER = {
39025  NearestFilter: NearestFilter,
39026  NearestMipMapNearestFilter: NearestMipMapNearestFilter,
39027  NearestMipMapLinearFilter: NearestMipMapLinearFilter,
39028  LinearFilter: LinearFilter,
39029  LinearMipMapNearestFilter: LinearMipMapNearestFilter,
39030  LinearMipMapLinearFilter: LinearMipMapLinearFilter
39031  };
39032 
39038  function ImageBitmapLoader( manager ) {
39039 
39040  if ( typeof createImageBitmap === 'undefined' ) {
39041 
39042  console.warn( 'THREE.ImageBitmapLoader: createImageBitmap() not supported.' );
39043 
39044  }
39045 
39046  if ( typeof fetch === 'undefined' ) {
39047 
39048  console.warn( 'THREE.ImageBitmapLoader: fetch() not supported.' );
39049 
39050  }
39051 
39052  this.manager = manager !== undefined ? manager : DefaultLoadingManager;
39053  this.options = undefined;
39054 
39055  }
39056 
39057  ImageBitmapLoader.prototype = {
39058 
39059  constructor: ImageBitmapLoader,
39060 
39061  setOptions: function setOptions( options ) {
39062 
39063  this.options = options;
39064 
39065  return this;
39066 
39067  },
39068 
39069  load: function ( url, onLoad, onProgress, onError ) {
39070 
39071  if ( url === undefined ) url = '';
39072 
39073  if ( this.path !== undefined ) url = this.path + url;
39074 
39075  url = this.manager.resolveURL( url );
39076 
39077  var scope = this;
39078 
39079  var cached = Cache.get( url );
39080 
39081  if ( cached !== undefined ) {
39082 
39083  scope.manager.itemStart( url );
39084 
39085  setTimeout( function () {
39086 
39087  if ( onLoad ) onLoad( cached );
39088 
39089  scope.manager.itemEnd( url );
39090 
39091  }, 0 );
39092 
39093  return cached;
39094 
39095  }
39096 
39097  fetch( url ).then( function ( res ) {
39098 
39099  return res.blob();
39100 
39101  } ).then( function ( blob ) {
39102 
39103  return createImageBitmap( blob, scope.options );
39104 
39105  } ).then( function ( imageBitmap ) {
39106 
39107  Cache.add( url, imageBitmap );
39108 
39109  if ( onLoad ) onLoad( imageBitmap );
39110 
39111  scope.manager.itemEnd( url );
39112 
39113  } ).catch( function ( e ) {
39114 
39115  if ( onError ) onError( e );
39116 
39117  scope.manager.itemError( url );
39118  scope.manager.itemEnd( url );
39119 
39120  } );
39121 
39122  scope.manager.itemStart( url );
39123 
39124  },
39125 
39126  setCrossOrigin: function ( /* value */ ) {
39127 
39128  return this;
39129 
39130  },
39131 
39132  setPath: function ( value ) {
39133 
39134  this.path = value;
39135  return this;
39136 
39137  }
39138 
39139  };
39140 
39146  function ShapePath() {
39147 
39148  this.type = 'ShapePath';
39149 
39150  this.color = new Color();
39151 
39152  this.subPaths = [];
39153  this.currentPath = null;
39154 
39155  }
39156 
39157  Object.assign( ShapePath.prototype, {
39158 
39159  moveTo: function ( x, y ) {
39160 
39161  this.currentPath = new Path();
39162  this.subPaths.push( this.currentPath );
39163  this.currentPath.moveTo( x, y );
39164 
39165  },
39166 
39167  lineTo: function ( x, y ) {
39168 
39169  this.currentPath.lineTo( x, y );
39170 
39171  },
39172 
39173  quadraticCurveTo: function ( aCPx, aCPy, aX, aY ) {
39174 
39175  this.currentPath.quadraticCurveTo( aCPx, aCPy, aX, aY );
39176 
39177  },
39178 
39179  bezierCurveTo: function ( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) {
39180 
39181  this.currentPath.bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY );
39182 
39183  },
39184 
39185  splineThru: function ( pts ) {
39186 
39187  this.currentPath.splineThru( pts );
39188 
39189  },
39190 
39191  toShapes: function ( isCCW, noHoles ) {
39192 
39193  function toShapesNoHoles( inSubpaths ) {
39194 
39195  var shapes = [];
39196 
39197  for ( var i = 0, l = inSubpaths.length; i < l; i ++ ) {
39198 
39199  var tmpPath = inSubpaths[ i ];
39200 
39201  var tmpShape = new Shape();
39202  tmpShape.curves = tmpPath.curves;
39203 
39204  shapes.push( tmpShape );
39205 
39206  }
39207 
39208  return shapes;
39209 
39210  }
39211 
39212  function isPointInsidePolygon( inPt, inPolygon ) {
39213 
39214  var polyLen = inPolygon.length;
39215 
39216  // inPt on polygon contour => immediate success or
39217  // toggling of inside/outside at every single! intersection point of an edge
39218  // with the horizontal line through inPt, left of inPt
39219  // not counting lowerY endpoints of edges and whole edges on that line
39220  var inside = false;
39221  for ( var p = polyLen - 1, q = 0; q < polyLen; p = q ++ ) {
39222 
39223  var edgeLowPt = inPolygon[ p ];
39224  var edgeHighPt = inPolygon[ q ];
39225 
39226  var edgeDx = edgeHighPt.x - edgeLowPt.x;
39227  var edgeDy = edgeHighPt.y - edgeLowPt.y;
39228 
39229  if ( Math.abs( edgeDy ) > Number.EPSILON ) {
39230 
39231  // not parallel
39232  if ( edgeDy < 0 ) {
39233 
39234  edgeLowPt = inPolygon[ q ]; edgeDx = - edgeDx;
39235  edgeHighPt = inPolygon[ p ]; edgeDy = - edgeDy;
39236 
39237  }
39238  if ( ( inPt.y < edgeLowPt.y ) || ( inPt.y > edgeHighPt.y ) ) continue;
39239 
39240  if ( inPt.y === edgeLowPt.y ) {
39241 
39242  if ( inPt.x === edgeLowPt.x ) return true; // inPt is on contour ?
39243  // continue; // no intersection or edgeLowPt => doesn't count !!!
39244 
39245  } else {
39246 
39247  var perpEdge = edgeDy * ( inPt.x - edgeLowPt.x ) - edgeDx * ( inPt.y - edgeLowPt.y );
39248  if ( perpEdge === 0 ) return true; // inPt is on contour ?
39249  if ( perpEdge < 0 ) continue;
39250  inside = ! inside; // true intersection left of inPt
39251 
39252  }
39253 
39254  } else {
39255 
39256  // parallel or collinear
39257  if ( inPt.y !== edgeLowPt.y ) continue; // parallel
39258  // edge lies on the same horizontal line as inPt
39259  if ( ( ( edgeHighPt.x <= inPt.x ) && ( inPt.x <= edgeLowPt.x ) ) ||
39260  ( ( edgeLowPt.x <= inPt.x ) && ( inPt.x <= edgeHighPt.x ) ) ) return true; // inPt: Point on contour !
39261  // continue;
39262 
39263  }
39264 
39265  }
39266 
39267  return inside;
39268 
39269  }
39270 
39271  var isClockWise = ShapeUtils.isClockWise;
39272 
39273  var subPaths = this.subPaths;
39274  if ( subPaths.length === 0 ) return [];
39275 
39276  if ( noHoles === true ) return toShapesNoHoles( subPaths );
39277 
39278 
39279  var solid, tmpPath, tmpShape, shapes = [];
39280 
39281  if ( subPaths.length === 1 ) {
39282 
39283  tmpPath = subPaths[ 0 ];
39284  tmpShape = new Shape();
39285  tmpShape.curves = tmpPath.curves;
39286  shapes.push( tmpShape );
39287  return shapes;
39288 
39289  }
39290 
39291  var holesFirst = ! isClockWise( subPaths[ 0 ].getPoints() );
39292  holesFirst = isCCW ? ! holesFirst : holesFirst;
39293 
39294  // console.log("Holes first", holesFirst);
39295 
39296  var betterShapeHoles = [];
39297  var newShapes = [];
39298  var newShapeHoles = [];
39299  var mainIdx = 0;
39300  var tmpPoints;
39301 
39302  newShapes[ mainIdx ] = undefined;
39303  newShapeHoles[ mainIdx ] = [];
39304 
39305  for ( var i = 0, l = subPaths.length; i < l; i ++ ) {
39306 
39307  tmpPath = subPaths[ i ];
39308  tmpPoints = tmpPath.getPoints();
39309  solid = isClockWise( tmpPoints );
39310  solid = isCCW ? ! solid : solid;
39311 
39312  if ( solid ) {
39313 
39314  if ( ( ! holesFirst ) && ( newShapes[ mainIdx ] ) ) mainIdx ++;
39315 
39316  newShapes[ mainIdx ] = { s: new Shape(), p: tmpPoints };
39317  newShapes[ mainIdx ].s.curves = tmpPath.curves;
39318 
39319  if ( holesFirst ) mainIdx ++;
39320  newShapeHoles[ mainIdx ] = [];
39321 
39322  //console.log('cw', i);
39323 
39324  } else {
39325 
39326  newShapeHoles[ mainIdx ].push( { h: tmpPath, p: tmpPoints[ 0 ] } );
39327 
39328  //console.log('ccw', i);
39329 
39330  }
39331 
39332  }
39333 
39334  // only Holes? -> probably all Shapes with wrong orientation
39335  if ( ! newShapes[ 0 ] ) return toShapesNoHoles( subPaths );
39336 
39337 
39338  if ( newShapes.length > 1 ) {
39339 
39340  var ambiguous = false;
39341  var toChange = [];
39342 
39343  for ( var sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
39344 
39345  betterShapeHoles[ sIdx ] = [];
39346 
39347  }
39348 
39349  for ( var sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
39350 
39351  var sho = newShapeHoles[ sIdx ];
39352 
39353  for ( var hIdx = 0; hIdx < sho.length; hIdx ++ ) {
39354 
39355  var ho = sho[ hIdx ];
39356  var hole_unassigned = true;
39357 
39358  for ( var s2Idx = 0; s2Idx < newShapes.length; s2Idx ++ ) {
39359 
39360  if ( isPointInsidePolygon( ho.p, newShapes[ s2Idx ].p ) ) {
39361 
39362  if ( sIdx !== s2Idx ) toChange.push( { froms: sIdx, tos: s2Idx, hole: hIdx } );
39363  if ( hole_unassigned ) {
39364 
39365  hole_unassigned = false;
39366  betterShapeHoles[ s2Idx ].push( ho );
39367 
39368  } else {
39369 
39370  ambiguous = true;
39371 
39372  }
39373 
39374  }
39375 
39376  }
39377  if ( hole_unassigned ) {
39378 
39379  betterShapeHoles[ sIdx ].push( ho );
39380 
39381  }
39382 
39383  }
39384 
39385  }
39386  // console.log("ambiguous: ", ambiguous);
39387  if ( toChange.length > 0 ) {
39388 
39389  // console.log("to change: ", toChange);
39390  if ( ! ambiguous ) newShapeHoles = betterShapeHoles;
39391 
39392  }
39393 
39394  }
39395 
39396  var tmpHoles;
39397 
39398  for ( var i = 0, il = newShapes.length; i < il; i ++ ) {
39399 
39400  tmpShape = newShapes[ i ].s;
39401  shapes.push( tmpShape );
39402  tmpHoles = newShapeHoles[ i ];
39403 
39404  for ( var j = 0, jl = tmpHoles.length; j < jl; j ++ ) {
39405 
39406  tmpShape.holes.push( tmpHoles[ j ].h );
39407 
39408  }
39409 
39410  }
39411 
39412  //console.log("shape", shapes);
39413 
39414  return shapes;
39415 
39416  }
39417 
39418  } );
39419 
39426  function Font( data ) {
39427 
39428  this.type = 'Font';
39429 
39430  this.data = data;
39431 
39432  }
39433 
39434  Object.assign( Font.prototype, {
39435 
39436  isFont: true,
39437 
39438  generateShapes: function ( text, size ) {
39439 
39440  if ( size === undefined ) size = 100;
39441 
39442  var shapes = [];
39443  var paths = createPaths( text, size, this.data );
39444 
39445  for ( var p = 0, pl = paths.length; p < pl; p ++ ) {
39446 
39447  Array.prototype.push.apply( shapes, paths[ p ].toShapes() );
39448 
39449  }
39450 
39451  return shapes;
39452 
39453  }
39454 
39455  } );
39456 
39457  function createPaths( text, size, data ) {
39458 
39459  var chars = Array.from ? Array.from( text ) : String( text ).split( '' ); // see #13988
39460  var scale = size / data.resolution;
39461  var line_height = ( data.boundingBox.yMax - data.boundingBox.yMin + data.underlineThickness ) * scale;
39462 
39463  var paths = [];
39464 
39465  var offsetX = 0, offsetY = 0;
39466 
39467  for ( var i = 0; i < chars.length; i ++ ) {
39468 
39469  var char = chars[ i ];
39470 
39471  if ( char === '\n' ) {
39472 
39473  offsetX = 0;
39474  offsetY -= line_height;
39475 
39476  } else {
39477 
39478  var ret = createPath( char, scale, offsetX, offsetY, data );
39479  offsetX += ret.offsetX;
39480  paths.push( ret.path );
39481 
39482  }
39483 
39484  }
39485 
39486  return paths;
39487 
39488  }
39489 
39490  function createPath( char, scale, offsetX, offsetY, data ) {
39491 
39492  var glyph = data.glyphs[ char ] || data.glyphs[ '?' ];
39493 
39494  if ( ! glyph ) return;
39495 
39496  var path = new ShapePath();
39497 
39498  var x, y, cpx, cpy, cpx1, cpy1, cpx2, cpy2;
39499 
39500  if ( glyph.o ) {
39501 
39502  var outline = glyph._cachedOutline || ( glyph._cachedOutline = glyph.o.split( ' ' ) );
39503 
39504  for ( var i = 0, l = outline.length; i < l; ) {
39505 
39506  var action = outline[ i ++ ];
39507 
39508  switch ( action ) {
39509 
39510  case 'm': // moveTo
39511 
39512  x = outline[ i ++ ] * scale + offsetX;
39513  y = outline[ i ++ ] * scale + offsetY;
39514 
39515  path.moveTo( x, y );
39516 
39517  break;
39518 
39519  case 'l': // lineTo
39520 
39521  x = outline[ i ++ ] * scale + offsetX;
39522  y = outline[ i ++ ] * scale + offsetY;
39523 
39524  path.lineTo( x, y );
39525 
39526  break;
39527 
39528  case 'q': // quadraticCurveTo
39529 
39530  cpx = outline[ i ++ ] * scale + offsetX;
39531  cpy = outline[ i ++ ] * scale + offsetY;
39532  cpx1 = outline[ i ++ ] * scale + offsetX;
39533  cpy1 = outline[ i ++ ] * scale + offsetY;
39534 
39535  path.quadraticCurveTo( cpx1, cpy1, cpx, cpy );
39536 
39537  break;
39538 
39539  case 'b': // bezierCurveTo
39540 
39541  cpx = outline[ i ++ ] * scale + offsetX;
39542  cpy = outline[ i ++ ] * scale + offsetY;
39543  cpx1 = outline[ i ++ ] * scale + offsetX;
39544  cpy1 = outline[ i ++ ] * scale + offsetY;
39545  cpx2 = outline[ i ++ ] * scale + offsetX;
39546  cpy2 = outline[ i ++ ] * scale + offsetY;
39547 
39548  path.bezierCurveTo( cpx1, cpy1, cpx2, cpy2, cpx, cpy );
39549 
39550  break;
39551 
39552  }
39553 
39554  }
39555 
39556  }
39557 
39558  return { offsetX: glyph.ha * scale, path: path };
39559 
39560  }
39561 
39566  function FontLoader( manager ) {
39567 
39568  this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
39569 
39570  }
39571 
39572  Object.assign( FontLoader.prototype, {
39573 
39574  load: function ( url, onLoad, onProgress, onError ) {
39575 
39576  var scope = this;
39577 
39578  var loader = new FileLoader( this.manager );
39579  loader.setPath( this.path );
39580  loader.load( url, function ( text ) {
39581 
39582  var json;
39583 
39584  try {
39585 
39586  json = JSON.parse( text );
39587 
39588  } catch ( e ) {
39589 
39590  console.warn( 'THREE.FontLoader: typeface.js support is being deprecated. Use typeface.json instead.' );
39591  json = JSON.parse( text.substring( 65, text.length - 2 ) );
39592 
39593  }
39594 
39595  var font = scope.parse( json );
39596 
39597  if ( onLoad ) onLoad( font );
39598 
39599  }, onProgress, onError );
39600 
39601  },
39602 
39603  parse: function ( json ) {
39604 
39605  return new Font( json );
39606 
39607  },
39608 
39609  setPath: function ( value ) {
39610 
39611  this.path = value;
39612  return this;
39613 
39614  }
39615 
39616  } );
39617 
39622  function Loader() {}
39623 
39624  Loader.Handlers = {
39625 
39626  handlers: [],
39627 
39628  add: function ( regex, loader ) {
39629 
39630  this.handlers.push( regex, loader );
39631 
39632  },
39633 
39634  get: function ( file ) {
39635 
39636  var handlers = this.handlers;
39637 
39638  for ( var i = 0, l = handlers.length; i < l; i += 2 ) {
39639 
39640  var regex = handlers[ i ];
39641  var loader = handlers[ i + 1 ];
39642 
39643  if ( regex.test( file ) ) {
39644 
39645  return loader;
39646 
39647  }
39648 
39649  }
39650 
39651  return null;
39652 
39653  }
39654 
39655  };
39656 
39657  Object.assign( Loader.prototype, {
39658 
39659  crossOrigin: 'anonymous',
39660 
39661  onLoadStart: function () {},
39662 
39663  onLoadProgress: function () {},
39664 
39665  onLoadComplete: function () {},
39666 
39667  initMaterials: function ( materials, texturePath, crossOrigin ) {
39668 
39669  var array = [];
39670 
39671  for ( var i = 0; i < materials.length; ++ i ) {
39672 
39673  array[ i ] = this.createMaterial( materials[ i ], texturePath, crossOrigin );
39674 
39675  }
39676 
39677  return array;
39678 
39679  },
39680 
39681  createMaterial: ( function () {
39682 
39683  var BlendingMode = {
39684  NoBlending: NoBlending,
39685  NormalBlending: NormalBlending,
39686  AdditiveBlending: AdditiveBlending,
39687  SubtractiveBlending: SubtractiveBlending,
39688  MultiplyBlending: MultiplyBlending,
39689  CustomBlending: CustomBlending
39690  };
39691 
39692  var color = new Color();
39693  var textureLoader = new TextureLoader();
39694  var materialLoader = new MaterialLoader();
39695 
39696  return function createMaterial( m, texturePath, crossOrigin ) {
39697 
39698  // convert from old material format
39699 
39700  var textures = {};
39701 
39702  function loadTexture( path, repeat, offset, wrap, anisotropy ) {
39703 
39704  var fullPath = texturePath + path;
39705  var loader = Loader.Handlers.get( fullPath );
39706 
39707  var texture;
39708 
39709  if ( loader !== null ) {
39710 
39711  texture = loader.load( fullPath );
39712 
39713  } else {
39714 
39715  textureLoader.setCrossOrigin( crossOrigin );
39716  texture = textureLoader.load( fullPath );
39717 
39718  }
39719 
39720  if ( repeat !== undefined ) {
39721 
39722  texture.repeat.fromArray( repeat );
39723 
39724  if ( repeat[ 0 ] !== 1 ) texture.wrapS = RepeatWrapping;
39725  if ( repeat[ 1 ] !== 1 ) texture.wrapT = RepeatWrapping;
39726 
39727  }
39728 
39729  if ( offset !== undefined ) {
39730 
39731  texture.offset.fromArray( offset );
39732 
39733  }
39734 
39735  if ( wrap !== undefined ) {
39736 
39737  if ( wrap[ 0 ] === 'repeat' ) texture.wrapS = RepeatWrapping;
39738  if ( wrap[ 0 ] === 'mirror' ) texture.wrapS = MirroredRepeatWrapping;
39739 
39740  if ( wrap[ 1 ] === 'repeat' ) texture.wrapT = RepeatWrapping;
39741  if ( wrap[ 1 ] === 'mirror' ) texture.wrapT = MirroredRepeatWrapping;
39742 
39743  }
39744 
39745  if ( anisotropy !== undefined ) {
39746 
39747  texture.anisotropy = anisotropy;
39748 
39749  }
39750 
39751  var uuid = _Math.generateUUID();
39752 
39753  textures[ uuid ] = texture;
39754 
39755  return uuid;
39756 
39757  }
39758 
39759  //
39760 
39761  var json = {
39762  uuid: _Math.generateUUID(),
39763  type: 'MeshLambertMaterial'
39764  };
39765 
39766  for ( var name in m ) {
39767 
39768  var value = m[ name ];
39769 
39770  switch ( name ) {
39771 
39772  case 'DbgColor':
39773  case 'DbgIndex':
39774  case 'opticalDensity':
39775  case 'illumination':
39776  break;
39777  case 'DbgName':
39778  json.name = value;
39779  break;
39780  case 'blending':
39781  json.blending = BlendingMode[ value ];
39782  break;
39783  case 'colorAmbient':
39784  case 'mapAmbient':
39785  console.warn( 'THREE.Loader.createMaterial:', name, 'is no longer supported.' );
39786  break;
39787  case 'colorDiffuse':
39788  json.color = color.fromArray( value ).getHex();
39789  break;
39790  case 'colorSpecular':
39791  json.specular = color.fromArray( value ).getHex();
39792  break;
39793  case 'colorEmissive':
39794  json.emissive = color.fromArray( value ).getHex();
39795  break;
39796  case 'specularCoef':
39797  json.shininess = value;
39798  break;
39799  case 'shading':
39800  if ( value.toLowerCase() === 'basic' ) json.type = 'MeshBasicMaterial';
39801  if ( value.toLowerCase() === 'phong' ) json.type = 'MeshPhongMaterial';
39802  if ( value.toLowerCase() === 'standard' ) json.type = 'MeshStandardMaterial';
39803  break;
39804  case 'mapDiffuse':
39805  json.map = loadTexture( value, m.mapDiffuseRepeat, m.mapDiffuseOffset, m.mapDiffuseWrap, m.mapDiffuseAnisotropy );
39806  break;
39807  case 'mapDiffuseRepeat':
39808  case 'mapDiffuseOffset':
39809  case 'mapDiffuseWrap':
39810  case 'mapDiffuseAnisotropy':
39811  break;
39812  case 'mapEmissive':
39813  json.emissiveMap = loadTexture( value, m.mapEmissiveRepeat, m.mapEmissiveOffset, m.mapEmissiveWrap, m.mapEmissiveAnisotropy );
39814  break;
39815  case 'mapEmissiveRepeat':
39816  case 'mapEmissiveOffset':
39817  case 'mapEmissiveWrap':
39818  case 'mapEmissiveAnisotropy':
39819  break;
39820  case 'mapLight':
39821  json.lightMap = loadTexture( value, m.mapLightRepeat, m.mapLightOffset, m.mapLightWrap, m.mapLightAnisotropy );
39822  break;
39823  case 'mapLightRepeat':
39824  case 'mapLightOffset':
39825  case 'mapLightWrap':
39826  case 'mapLightAnisotropy':
39827  break;
39828  case 'mapAO':
39829  json.aoMap = loadTexture( value, m.mapAORepeat, m.mapAOOffset, m.mapAOWrap, m.mapAOAnisotropy );
39830  break;
39831  case 'mapAORepeat':
39832  case 'mapAOOffset':
39833  case 'mapAOWrap':
39834  case 'mapAOAnisotropy':
39835  break;
39836  case 'mapBump':
39837  json.bumpMap = loadTexture( value, m.mapBumpRepeat, m.mapBumpOffset, m.mapBumpWrap, m.mapBumpAnisotropy );
39838  break;
39839  case 'mapBumpScale':
39840  json.bumpScale = value;
39841  break;
39842  case 'mapBumpRepeat':
39843  case 'mapBumpOffset':
39844  case 'mapBumpWrap':
39845  case 'mapBumpAnisotropy':
39846  break;
39847  case 'mapNormal':
39848  json.normalMap = loadTexture( value, m.mapNormalRepeat, m.mapNormalOffset, m.mapNormalWrap, m.mapNormalAnisotropy );
39849  break;
39850  case 'mapNormalFactor':
39851  json.normalScale = value;
39852  break;
39853  case 'mapNormalRepeat':
39854  case 'mapNormalOffset':
39855  case 'mapNormalWrap':
39856  case 'mapNormalAnisotropy':
39857  break;
39858  case 'mapSpecular':
39859  json.specularMap = loadTexture( value, m.mapSpecularRepeat, m.mapSpecularOffset, m.mapSpecularWrap, m.mapSpecularAnisotropy );
39860  break;
39861  case 'mapSpecularRepeat':
39862  case 'mapSpecularOffset':
39863  case 'mapSpecularWrap':
39864  case 'mapSpecularAnisotropy':
39865  break;
39866  case 'mapMetalness':
39867  json.metalnessMap = loadTexture( value, m.mapMetalnessRepeat, m.mapMetalnessOffset, m.mapMetalnessWrap, m.mapMetalnessAnisotropy );
39868  break;
39869  case 'mapMetalnessRepeat':
39870  case 'mapMetalnessOffset':
39871  case 'mapMetalnessWrap':
39872  case 'mapMetalnessAnisotropy':
39873  break;
39874  case 'mapRoughness':
39875  json.roughnessMap = loadTexture( value, m.mapRoughnessRepeat, m.mapRoughnessOffset, m.mapRoughnessWrap, m.mapRoughnessAnisotropy );
39876  break;
39877  case 'mapRoughnessRepeat':
39878  case 'mapRoughnessOffset':
39879  case 'mapRoughnessWrap':
39880  case 'mapRoughnessAnisotropy':
39881  break;
39882  case 'mapAlpha':
39883  json.alphaMap = loadTexture( value, m.mapAlphaRepeat, m.mapAlphaOffset, m.mapAlphaWrap, m.mapAlphaAnisotropy );
39884  break;
39885  case 'mapAlphaRepeat':
39886  case 'mapAlphaOffset':
39887  case 'mapAlphaWrap':
39888  case 'mapAlphaAnisotropy':
39889  break;
39890  case 'flipSided':
39891  json.side = BackSide;
39892  break;
39893  case 'doubleSided':
39894  json.side = DoubleSide;
39895  break;
39896  case 'transparency':
39897  console.warn( 'THREE.Loader.createMaterial: transparency has been renamed to opacity' );
39898  json.opacity = value;
39899  break;
39900  case 'depthTest':
39901  case 'depthWrite':
39902  case 'colorWrite':
39903  case 'opacity':
39904  case 'reflectivity':
39905  case 'transparent':
39906  case 'visible':
39907  case 'wireframe':
39908  json[ name ] = value;
39909  break;
39910  case 'vertexColors':
39911  if ( value === true ) json.vertexColors = VertexColors;
39912  if ( value === 'face' ) json.vertexColors = FaceColors;
39913  break;
39914  default:
39915  console.error( 'THREE.Loader.createMaterial: Unsupported', name, value );
39916  break;
39917 
39918  }
39919 
39920  }
39921 
39922  if ( json.type === 'MeshBasicMaterial' ) delete json.emissive;
39923  if ( json.type !== 'MeshPhongMaterial' ) delete json.specular;
39924 
39925  if ( json.opacity < 1 ) json.transparent = true;
39926 
39927  materialLoader.setTextures( textures );
39928 
39929  return materialLoader.parse( json );
39930 
39931  };
39932 
39933  } )()
39934 
39935  } );
39936 
39941  var context;
39942 
39943  var AudioContext = {
39944 
39945  getContext: function () {
39946 
39947  if ( context === undefined ) {
39948 
39949  context = new ( window.AudioContext || window.webkitAudioContext )();
39950 
39951  }
39952 
39953  return context;
39954 
39955  },
39956 
39957  setContext: function ( value ) {
39958 
39959  context = value;
39960 
39961  }
39962 
39963  };
39964 
39969  function AudioLoader( manager ) {
39970 
39971  this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
39972 
39973  }
39974 
39975  Object.assign( AudioLoader.prototype, {
39976 
39977  load: function ( url, onLoad, onProgress, onError ) {
39978 
39979  var loader = new FileLoader( this.manager );
39980  loader.setResponseType( 'arraybuffer' );
39981  loader.setPath( this.path );
39982  loader.load( url, function ( buffer ) {
39983 
39984  // Create a copy of the buffer. The `decodeAudioData` method
39985  // detaches the buffer when complete, preventing reuse.
39986  var bufferCopy = buffer.slice( 0 );
39987 
39988  var context = AudioContext.getContext();
39989  context.decodeAudioData( bufferCopy, function ( audioBuffer ) {
39990 
39991  onLoad( audioBuffer );
39992 
39993  } );
39994 
39995  }, onProgress, onError );
39996 
39997  },
39998 
39999  setPath: function ( value ) {
40000 
40001  this.path = value;
40002  return this;
40003 
40004  }
40005 
40006  } );
40007 
40012  function StereoCamera() {
40013 
40014  this.type = 'StereoCamera';
40015 
40016  this.aspect = 1;
40017 
40018  this.eyeSep = 0.064;
40019 
40020  this.cameraL = new PerspectiveCamera();
40021  this.cameraL.layers.enable( 1 );
40022  this.cameraL.matrixAutoUpdate = false;
40023 
40024  this.cameraR = new PerspectiveCamera();
40025  this.cameraR.layers.enable( 2 );
40026  this.cameraR.matrixAutoUpdate = false;
40027 
40028  }
40029 
40030  Object.assign( StereoCamera.prototype, {
40031 
40032  update: ( function () {
40033 
40034  var instance, focus, fov, aspect, near, far, zoom, eyeSep;
40035 
40036  var eyeRight = new Matrix4();
40037  var eyeLeft = new Matrix4();
40038 
40039  return function update( camera ) {
40040 
40041  var needsUpdate = instance !== this || focus !== camera.focus || fov !== camera.fov ||
40042  aspect !== camera.aspect * this.aspect || near !== camera.near ||
40043  far !== camera.far || zoom !== camera.zoom || eyeSep !== this.eyeSep;
40044 
40045  if ( needsUpdate ) {
40046 
40047  instance = this;
40048  focus = camera.focus;
40049  fov = camera.fov;
40050  aspect = camera.aspect * this.aspect;
40051  near = camera.near;
40052  far = camera.far;
40053  zoom = camera.zoom;
40054 
40055  // Off-axis stereoscopic effect based on
40056  // http://paulbourke.net/stereographics/stereorender/
40057 
40058  var projectionMatrix = camera.projectionMatrix.clone();
40059  eyeSep = this.eyeSep / 2;
40060  var eyeSepOnProjection = eyeSep * near / focus;
40061  var ymax = ( near * Math.tan( _Math.DEG2RAD * fov * 0.5 ) ) / zoom;
40062  var xmin, xmax;
40063 
40064  // translate xOffset
40065 
40066  eyeLeft.elements[ 12 ] = - eyeSep;
40067  eyeRight.elements[ 12 ] = eyeSep;
40068 
40069  // for left eye
40070 
40071  xmin = - ymax * aspect + eyeSepOnProjection;
40072  xmax = ymax * aspect + eyeSepOnProjection;
40073 
40074  projectionMatrix.elements[ 0 ] = 2 * near / ( xmax - xmin );
40075  projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
40076 
40077  this.cameraL.projectionMatrix.copy( projectionMatrix );
40078 
40079  // for right eye
40080 
40081  xmin = - ymax * aspect - eyeSepOnProjection;
40082  xmax = ymax * aspect - eyeSepOnProjection;
40083 
40084  projectionMatrix.elements[ 0 ] = 2 * near / ( xmax - xmin );
40085  projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
40086 
40087  this.cameraR.projectionMatrix.copy( projectionMatrix );
40088 
40089  }
40090 
40091  this.cameraL.matrixWorld.copy( camera.matrixWorld ).multiply( eyeLeft );
40092  this.cameraR.matrixWorld.copy( camera.matrixWorld ).multiply( eyeRight );
40093 
40094  };
40095 
40096  } )()
40097 
40098  } );
40099 
40107  function CubeCamera( near, far, cubeResolution, options ) {
40108 
40109  Object3D.call( this );
40110 
40111  this.type = 'CubeCamera';
40112 
40113  var fov = 90, aspect = 1;
40114 
40115  var cameraPX = new PerspectiveCamera( fov, aspect, near, far );
40116  cameraPX.up.set( 0, - 1, 0 );
40117  cameraPX.lookAt( new Vector3( 1, 0, 0 ) );
40118  this.add( cameraPX );
40119 
40120  var cameraNX = new PerspectiveCamera( fov, aspect, near, far );
40121  cameraNX.up.set( 0, - 1, 0 );
40122  cameraNX.lookAt( new Vector3( - 1, 0, 0 ) );
40123  this.add( cameraNX );
40124 
40125  var cameraPY = new PerspectiveCamera( fov, aspect, near, far );
40126  cameraPY.up.set( 0, 0, 1 );
40127  cameraPY.lookAt( new Vector3( 0, 1, 0 ) );
40128  this.add( cameraPY );
40129 
40130  var cameraNY = new PerspectiveCamera( fov, aspect, near, far );
40131  cameraNY.up.set( 0, 0, - 1 );
40132  cameraNY.lookAt( new Vector3( 0, - 1, 0 ) );
40133  this.add( cameraNY );
40134 
40135  var cameraPZ = new PerspectiveCamera( fov, aspect, near, far );
40136  cameraPZ.up.set( 0, - 1, 0 );
40137  cameraPZ.lookAt( new Vector3( 0, 0, 1 ) );
40138  this.add( cameraPZ );
40139 
40140  var cameraNZ = new PerspectiveCamera( fov, aspect, near, far );
40141  cameraNZ.up.set( 0, - 1, 0 );
40142  cameraNZ.lookAt( new Vector3( 0, 0, - 1 ) );
40143  this.add( cameraNZ );
40144 
40145  options = options || { format: RGBFormat, magFilter: LinearFilter, minFilter: LinearFilter };
40146 
40147  this.renderTarget = new WebGLRenderTargetCube( cubeResolution, cubeResolution, options );
40148  this.renderTarget.texture.name = "CubeCamera";
40149 
40150  this.update = function ( renderer, scene ) {
40151 
40152  if ( this.parent === null ) this.updateMatrixWorld();
40153 
40154  var currentRenderTarget = renderer.getRenderTarget();
40155 
40156  var renderTarget = this.renderTarget;
40157  var generateMipmaps = renderTarget.texture.generateMipmaps;
40158 
40159  renderTarget.texture.generateMipmaps = false;
40160 
40161  renderer.setRenderTarget( renderTarget, 0 );
40162  renderer.render( scene, cameraPX );
40163 
40164  renderer.setRenderTarget( renderTarget, 1 );
40165  renderer.render( scene, cameraNX );
40166 
40167  renderer.setRenderTarget( renderTarget, 2 );
40168  renderer.render( scene, cameraPY );
40169 
40170  renderer.setRenderTarget( renderTarget, 3 );
40171  renderer.render( scene, cameraNY );
40172 
40173  renderer.setRenderTarget( renderTarget, 4 );
40174  renderer.render( scene, cameraPZ );
40175 
40176  renderTarget.texture.generateMipmaps = generateMipmaps;
40177 
40178  renderer.setRenderTarget( renderTarget, 5 );
40179  renderer.render( scene, cameraNZ );
40180 
40181  renderer.setRenderTarget( currentRenderTarget );
40182 
40183  };
40184 
40185  this.clear = function ( renderer, color, depth, stencil ) {
40186 
40187  var currentRenderTarget = renderer.getRenderTarget();
40188 
40189  var renderTarget = this.renderTarget;
40190 
40191  for ( var i = 0; i < 6; i ++ ) {
40192 
40193  renderer.setRenderTarget( renderTarget, i );
40194 
40195  renderer.clear( color, depth, stencil );
40196 
40197  }
40198 
40199  renderer.setRenderTarget( currentRenderTarget );
40200 
40201  };
40202 
40203  }
40204 
40205  CubeCamera.prototype = Object.create( Object3D.prototype );
40206  CubeCamera.prototype.constructor = CubeCamera;
40207 
40212  function Clock( autoStart ) {
40213 
40214  this.autoStart = ( autoStart !== undefined ) ? autoStart : true;
40215 
40216  this.startTime = 0;
40217  this.oldTime = 0;
40218  this.elapsedTime = 0;
40219 
40220  this.running = false;
40221 
40222  }
40223 
40224  Object.assign( Clock.prototype, {
40225 
40226  start: function () {
40227 
40228  this.startTime = ( typeof performance === 'undefined' ? Date : performance ).now(); // see #10732
40229 
40230  this.oldTime = this.startTime;
40231  this.elapsedTime = 0;
40232  this.running = true;
40233 
40234  },
40235 
40236  stop: function () {
40237 
40238  this.getElapsedTime();
40239  this.running = false;
40240  this.autoStart = false;
40241 
40242  },
40243 
40244  getElapsedTime: function () {
40245 
40246  this.getDelta();
40247  return this.elapsedTime;
40248 
40249  },
40250 
40251  getDelta: function () {
40252 
40253  var diff = 0;
40254 
40255  if ( this.autoStart && ! this.running ) {
40256 
40257  this.start();
40258  return 0;
40259 
40260  }
40261 
40262  if ( this.running ) {
40263 
40264  var newTime = ( typeof performance === 'undefined' ? Date : performance ).now();
40265 
40266  diff = ( newTime - this.oldTime ) / 1000;
40267  this.oldTime = newTime;
40268 
40269  this.elapsedTime += diff;
40270 
40271  }
40272 
40273  return diff;
40274 
40275  }
40276 
40277  } );
40278 
40283  function AudioListener() {
40284 
40285  Object3D.call( this );
40286 
40287  this.type = 'AudioListener';
40288 
40289  this.context = AudioContext.getContext();
40290 
40291  this.gain = this.context.createGain();
40292  this.gain.connect( this.context.destination );
40293 
40294  this.filter = null;
40295 
40296  this.timeDelta = 0;
40297 
40298  }
40299 
40300  AudioListener.prototype = Object.assign( Object.create( Object3D.prototype ), {
40301 
40302  constructor: AudioListener,
40303 
40304  getInput: function () {
40305 
40306  return this.gain;
40307 
40308  },
40309 
40310  removeFilter: function ( ) {
40311 
40312  if ( this.filter !== null ) {
40313 
40314  this.gain.disconnect( this.filter );
40315  this.filter.disconnect( this.context.destination );
40316  this.gain.connect( this.context.destination );
40317  this.filter = null;
40318 
40319  }
40320 
40321  return this;
40322 
40323  },
40324 
40325  getFilter: function () {
40326 
40327  return this.filter;
40328 
40329  },
40330 
40331  setFilter: function ( value ) {
40332 
40333  if ( this.filter !== null ) {
40334 
40335  this.gain.disconnect( this.filter );
40336  this.filter.disconnect( this.context.destination );
40337 
40338  } else {
40339 
40340  this.gain.disconnect( this.context.destination );
40341 
40342  }
40343 
40344  this.filter = value;
40345  this.gain.connect( this.filter );
40346  this.filter.connect( this.context.destination );
40347 
40348  return this;
40349 
40350  },
40351 
40352  getMasterVolume: function () {
40353 
40354  return this.gain.gain.value;
40355 
40356  },
40357 
40358  setMasterVolume: function ( value ) {
40359 
40360  this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 );
40361 
40362  return this;
40363 
40364  },
40365 
40366  updateMatrixWorld: ( function () {
40367 
40368  var position = new Vector3();
40369  var quaternion = new Quaternion();
40370  var scale = new Vector3();
40371 
40372  var orientation = new Vector3();
40373  var clock = new Clock();
40374 
40375  return function updateMatrixWorld( force ) {
40376 
40377  Object3D.prototype.updateMatrixWorld.call( this, force );
40378 
40379  var listener = this.context.listener;
40380  var up = this.up;
40381 
40382  this.timeDelta = clock.getDelta();
40383 
40384  this.matrixWorld.decompose( position, quaternion, scale );
40385 
40386  orientation.set( 0, 0, - 1 ).applyQuaternion( quaternion );
40387 
40388  if ( listener.positionX ) {
40389 
40390  // code path for Chrome (see #14393)
40391 
40392  var endTime = this.context.currentTime + this.timeDelta;
40393 
40394  listener.positionX.linearRampToValueAtTime( position.x, endTime );
40395  listener.positionY.linearRampToValueAtTime( position.y, endTime );
40396  listener.positionZ.linearRampToValueAtTime( position.z, endTime );
40397  listener.forwardX.linearRampToValueAtTime( orientation.x, endTime );
40398  listener.forwardY.linearRampToValueAtTime( orientation.y, endTime );
40399  listener.forwardZ.linearRampToValueAtTime( orientation.z, endTime );
40400  listener.upX.linearRampToValueAtTime( up.x, endTime );
40401  listener.upY.linearRampToValueAtTime( up.y, endTime );
40402  listener.upZ.linearRampToValueAtTime( up.z, endTime );
40403 
40404  } else {
40405 
40406  listener.setPosition( position.x, position.y, position.z );
40407  listener.setOrientation( orientation.x, orientation.y, orientation.z, up.x, up.y, up.z );
40408 
40409  }
40410 
40411  };
40412 
40413  } )()
40414 
40415  } );
40416 
40422  function Audio( listener ) {
40423 
40424  Object3D.call( this );
40425 
40426  this.type = 'Audio';
40427 
40428  this.listener = listener;
40429  this.context = listener.context;
40430 
40431  this.gain = this.context.createGain();
40432  this.gain.connect( listener.getInput() );
40433 
40434  this.autoplay = false;
40435 
40436  this.buffer = null;
40437  this.detune = 0;
40438  this.loop = false;
40439  this.startTime = 0;
40440  this.offset = 0;
40441  this.playbackRate = 1;
40442  this.isPlaying = false;
40443  this.hasPlaybackControl = true;
40444  this.sourceType = 'empty';
40445 
40446  this.filters = [];
40447 
40448  }
40449 
40450  Audio.prototype = Object.assign( Object.create( Object3D.prototype ), {
40451 
40452  constructor: Audio,
40453 
40454  getOutput: function () {
40455 
40456  return this.gain;
40457 
40458  },
40459 
40460  setNodeSource: function ( audioNode ) {
40461 
40462  this.hasPlaybackControl = false;
40463  this.sourceType = 'audioNode';
40464  this.source = audioNode;
40465  this.connect();
40466 
40467  return this;
40468 
40469  },
40470 
40471  setMediaElementSource: function ( mediaElement ) {
40472 
40473  this.hasPlaybackControl = false;
40474  this.sourceType = 'mediaNode';
40475  this.source = this.context.createMediaElementSource( mediaElement );
40476  this.connect();
40477 
40478  return this;
40479 
40480  },
40481 
40482  setBuffer: function ( audioBuffer ) {
40483 
40484  this.buffer = audioBuffer;
40485  this.sourceType = 'buffer';
40486 
40487  if ( this.autoplay ) this.play();
40488 
40489  return this;
40490 
40491  },
40492 
40493  play: function () {
40494 
40495  if ( this.isPlaying === true ) {
40496 
40497  console.warn( 'THREE.Audio: Audio is already playing.' );
40498  return;
40499 
40500  }
40501 
40502  if ( this.hasPlaybackControl === false ) {
40503 
40504  console.warn( 'THREE.Audio: this Audio has no playback control.' );
40505  return;
40506 
40507  }
40508 
40509  var source = this.context.createBufferSource();
40510 
40511  source.buffer = this.buffer;
40512  source.loop = this.loop;
40513  source.onended = this.onEnded.bind( this );
40514  this.startTime = this.context.currentTime;
40515  source.start( this.startTime, this.offset );
40516 
40517  this.isPlaying = true;
40518 
40519  this.source = source;
40520 
40521  this.setDetune( this.detune );
40522  this.setPlaybackRate( this.playbackRate );
40523 
40524  return this.connect();
40525 
40526  },
40527 
40528  pause: function () {
40529 
40530  if ( this.hasPlaybackControl === false ) {
40531 
40532  console.warn( 'THREE.Audio: this Audio has no playback control.' );
40533  return;
40534 
40535  }
40536 
40537  if ( this.isPlaying === true ) {
40538 
40539  this.source.stop();
40540  this.source.onended = null;
40541  this.offset += ( this.context.currentTime - this.startTime ) * this.playbackRate;
40542  this.isPlaying = false;
40543 
40544  }
40545 
40546  return this;
40547 
40548  },
40549 
40550  stop: function () {
40551 
40552  if ( this.hasPlaybackControl === false ) {
40553 
40554  console.warn( 'THREE.Audio: this Audio has no playback control.' );
40555  return;
40556 
40557  }
40558 
40559  this.source.stop();
40560  this.source.onended = null;
40561  this.offset = 0;
40562  this.isPlaying = false;
40563 
40564  return this;
40565 
40566  },
40567 
40568  connect: function () {
40569 
40570  if ( this.filters.length > 0 ) {
40571 
40572  this.source.connect( this.filters[ 0 ] );
40573 
40574  for ( var i = 1, l = this.filters.length; i < l; i ++ ) {
40575 
40576  this.filters[ i - 1 ].connect( this.filters[ i ] );
40577 
40578  }
40579 
40580  this.filters[ this.filters.length - 1 ].connect( this.getOutput() );
40581 
40582  } else {
40583 
40584  this.source.connect( this.getOutput() );
40585 
40586  }
40587 
40588  return this;
40589 
40590  },
40591 
40592  disconnect: function () {
40593 
40594  if ( this.filters.length > 0 ) {
40595 
40596  this.source.disconnect( this.filters[ 0 ] );
40597 
40598  for ( var i = 1, l = this.filters.length; i < l; i ++ ) {
40599 
40600  this.filters[ i - 1 ].disconnect( this.filters[ i ] );
40601 
40602  }
40603 
40604  this.filters[ this.filters.length - 1 ].disconnect( this.getOutput() );
40605 
40606  } else {
40607 
40608  this.source.disconnect( this.getOutput() );
40609 
40610  }
40611 
40612  return this;
40613 
40614  },
40615 
40616  getFilters: function () {
40617 
40618  return this.filters;
40619 
40620  },
40621 
40622  setFilters: function ( value ) {
40623 
40624  if ( ! value ) value = [];
40625 
40626  if ( this.isPlaying === true ) {
40627 
40628  this.disconnect();
40629  this.filters = value;
40630  this.connect();
40631 
40632  } else {
40633 
40634  this.filters = value;
40635 
40636  }
40637 
40638  return this;
40639 
40640  },
40641 
40642  setDetune: function ( value ) {
40643 
40644  this.detune = value;
40645 
40646  if ( this.source.detune === undefined ) return; // only set detune when available
40647 
40648  if ( this.isPlaying === true ) {
40649 
40650  this.source.detune.setTargetAtTime( this.detune, this.context.currentTime, 0.01 );
40651 
40652  }
40653 
40654  return this;
40655 
40656  },
40657 
40658  getDetune: function () {
40659 
40660  return this.detune;
40661 
40662  },
40663 
40664  getFilter: function () {
40665 
40666  return this.getFilters()[ 0 ];
40667 
40668  },
40669 
40670  setFilter: function ( filter ) {
40671 
40672  return this.setFilters( filter ? [ filter ] : [] );
40673 
40674  },
40675 
40676  setPlaybackRate: function ( value ) {
40677 
40678  if ( this.hasPlaybackControl === false ) {
40679 
40680  console.warn( 'THREE.Audio: this Audio has no playback control.' );
40681  return;
40682 
40683  }
40684 
40685  this.playbackRate = value;
40686 
40687  if ( this.isPlaying === true ) {
40688 
40689  this.source.playbackRate.setTargetAtTime( this.playbackRate, this.context.currentTime, 0.01 );
40690 
40691  }
40692 
40693  return this;
40694 
40695  },
40696 
40697  getPlaybackRate: function () {
40698 
40699  return this.playbackRate;
40700 
40701  },
40702 
40703  onEnded: function () {
40704 
40705  this.isPlaying = false;
40706 
40707  },
40708 
40709  getLoop: function () {
40710 
40711  if ( this.hasPlaybackControl === false ) {
40712 
40713  console.warn( 'THREE.Audio: this Audio has no playback control.' );
40714  return false;
40715 
40716  }
40717 
40718  return this.loop;
40719 
40720  },
40721 
40722  setLoop: function ( value ) {
40723 
40724  if ( this.hasPlaybackControl === false ) {
40725 
40726  console.warn( 'THREE.Audio: this Audio has no playback control.' );
40727  return;
40728 
40729  }
40730 
40731  this.loop = value;
40732 
40733  if ( this.isPlaying === true ) {
40734 
40735  this.source.loop = this.loop;
40736 
40737  }
40738 
40739  return this;
40740 
40741  },
40742 
40743  getVolume: function () {
40744 
40745  return this.gain.gain.value;
40746 
40747  },
40748 
40749  setVolume: function ( value ) {
40750 
40751  this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 );
40752 
40753  return this;
40754 
40755  }
40756 
40757  } );
40758 
40763  function PositionalAudio( listener ) {
40764 
40765  Audio.call( this, listener );
40766 
40767  this.panner = this.context.createPanner();
40768  this.panner.connect( this.gain );
40769 
40770  }
40771 
40772  PositionalAudio.prototype = Object.assign( Object.create( Audio.prototype ), {
40773 
40774  constructor: PositionalAudio,
40775 
40776  getOutput: function () {
40777 
40778  return this.panner;
40779 
40780  },
40781 
40782  getRefDistance: function () {
40783 
40784  return this.panner.refDistance;
40785 
40786  },
40787 
40788  setRefDistance: function ( value ) {
40789 
40790  this.panner.refDistance = value;
40791 
40792  return this;
40793 
40794  },
40795 
40796  getRolloffFactor: function () {
40797 
40798  return this.panner.rolloffFactor;
40799 
40800  },
40801 
40802  setRolloffFactor: function ( value ) {
40803 
40804  this.panner.rolloffFactor = value;
40805 
40806  return this;
40807 
40808  },
40809 
40810  getDistanceModel: function () {
40811 
40812  return this.panner.distanceModel;
40813 
40814  },
40815 
40816  setDistanceModel: function ( value ) {
40817 
40818  this.panner.distanceModel = value;
40819 
40820  return this;
40821 
40822  },
40823 
40824  getMaxDistance: function () {
40825 
40826  return this.panner.maxDistance;
40827 
40828  },
40829 
40830  setMaxDistance: function ( value ) {
40831 
40832  this.panner.maxDistance = value;
40833 
40834  return this;
40835 
40836  },
40837 
40838  setDirectionalCone: function ( coneInnerAngle, coneOuterAngle, coneOuterGain ) {
40839 
40840  this.panner.coneInnerAngle = coneInnerAngle;
40841  this.panner.coneOuterAngle = coneOuterAngle;
40842  this.panner.coneOuterGain = coneOuterGain;
40843 
40844  return this;
40845 
40846  },
40847 
40848  updateMatrixWorld: ( function () {
40849 
40850  var position = new Vector3();
40851  var quaternion = new Quaternion();
40852  var scale = new Vector3();
40853 
40854  var orientation = new Vector3();
40855 
40856  return function updateMatrixWorld( force ) {
40857 
40858  Object3D.prototype.updateMatrixWorld.call( this, force );
40859 
40860  if ( this.hasPlaybackControl === true && this.isPlaying === false ) return;
40861 
40862  this.matrixWorld.decompose( position, quaternion, scale );
40863 
40864  orientation.set( 0, 0, 1 ).applyQuaternion( quaternion );
40865 
40866  var panner = this.panner;
40867 
40868  if ( panner.positionX ) {
40869 
40870  // code path for Chrome and Firefox (see #14393)
40871 
40872  var endTime = this.context.currentTime + this.listener.timeDelta;
40873 
40874  panner.positionX.linearRampToValueAtTime( position.x, endTime );
40875  panner.positionY.linearRampToValueAtTime( position.y, endTime );
40876  panner.positionZ.linearRampToValueAtTime( position.z, endTime );
40877  panner.orientationX.linearRampToValueAtTime( orientation.x, endTime );
40878  panner.orientationY.linearRampToValueAtTime( orientation.y, endTime );
40879  panner.orientationZ.linearRampToValueAtTime( orientation.z, endTime );
40880 
40881  } else {
40882 
40883  panner.setPosition( position.x, position.y, position.z );
40884  panner.setOrientation( orientation.x, orientation.y, orientation.z );
40885 
40886  }
40887 
40888  };
40889 
40890  } )()
40891 
40892 
40893  } );
40894 
40899  function AudioAnalyser( audio, fftSize ) {
40900 
40901  this.analyser = audio.context.createAnalyser();
40902  this.analyser.fftSize = fftSize !== undefined ? fftSize : 2048;
40903 
40904  this.data = new Uint8Array( this.analyser.frequencyBinCount );
40905 
40906  audio.getOutput().connect( this.analyser );
40907 
40908  }
40909 
40910  Object.assign( AudioAnalyser.prototype, {
40911 
40912  getFrequencyData: function () {
40913 
40914  this.analyser.getByteFrequencyData( this.data );
40915 
40916  return this.data;
40917 
40918  },
40919 
40920  getAverageFrequency: function () {
40921 
40922  var value = 0, data = this.getFrequencyData();
40923 
40924  for ( var i = 0; i < data.length; i ++ ) {
40925 
40926  value += data[ i ];
40927 
40928  }
40929 
40930  return value / data.length;
40931 
40932  }
40933 
40934  } );
40935 
40946  function PropertyMixer( binding, typeName, valueSize ) {
40947 
40948  this.binding = binding;
40949  this.valueSize = valueSize;
40950 
40951  var bufferType = Float64Array,
40952  mixFunction;
40953 
40954  switch ( typeName ) {
40955 
40956  case 'quaternion':
40957  mixFunction = this._slerp;
40958  break;
40959 
40960  case 'string':
40961  case 'bool':
40962  bufferType = Array;
40963  mixFunction = this._select;
40964  break;
40965 
40966  default:
40967  mixFunction = this._lerp;
40968 
40969  }
40970 
40971  this.buffer = new bufferType( valueSize * 4 );
40972  // layout: [ incoming | accu0 | accu1 | orig ]
40973  //
40974  // interpolators can use .buffer as their .result
40975  // the data then goes to 'incoming'
40976  //
40977  // 'accu0' and 'accu1' are used frame-interleaved for
40978  // the cumulative result and are compared to detect
40979  // changes
40980  //
40981  // 'orig' stores the original state of the property
40982 
40983  this._mixBufferRegion = mixFunction;
40984 
40985  this.cumulativeWeight = 0;
40986 
40987  this.useCount = 0;
40988  this.referenceCount = 0;
40989 
40990  }
40991 
40992  Object.assign( PropertyMixer.prototype, {
40993 
40994  // accumulate data in the 'incoming' region into 'accu<i>'
40995  accumulate: function ( accuIndex, weight ) {
40996 
40997  // note: happily accumulating nothing when weight = 0, the caller knows
40998  // the weight and shouldn't have made the call in the first place
40999 
41000  var buffer = this.buffer,
41001  stride = this.valueSize,
41002  offset = accuIndex * stride + stride,
41003 
41004  currentWeight = this.cumulativeWeight;
41005 
41006  if ( currentWeight === 0 ) {
41007 
41008  // accuN := incoming * weight
41009 
41010  for ( var i = 0; i !== stride; ++ i ) {
41011 
41012  buffer[ offset + i ] = buffer[ i ];
41013 
41014  }
41015 
41016  currentWeight = weight;
41017 
41018  } else {
41019 
41020  // accuN := accuN + incoming * weight
41021 
41022  currentWeight += weight;
41023  var mix = weight / currentWeight;
41024  this._mixBufferRegion( buffer, offset, 0, mix, stride );
41025 
41026  }
41027 
41028  this.cumulativeWeight = currentWeight;
41029 
41030  },
41031 
41032  // apply the state of 'accu<i>' to the binding when accus differ
41033  apply: function ( accuIndex ) {
41034 
41035  var stride = this.valueSize,
41036  buffer = this.buffer,
41037  offset = accuIndex * stride + stride,
41038 
41039  weight = this.cumulativeWeight,
41040 
41041  binding = this.binding;
41042 
41043  this.cumulativeWeight = 0;
41044 
41045  if ( weight < 1 ) {
41046 
41047  // accuN := accuN + original * ( 1 - cumulativeWeight )
41048 
41049  var originalValueOffset = stride * 3;
41050 
41051  this._mixBufferRegion(
41052  buffer, offset, originalValueOffset, 1 - weight, stride );
41053 
41054  }
41055 
41056  for ( var i = stride, e = stride + stride; i !== e; ++ i ) {
41057 
41058  if ( buffer[ i ] !== buffer[ i + stride ] ) {
41059 
41060  // value has changed -> update scene graph
41061 
41062  binding.setValue( buffer, offset );
41063  break;
41064 
41065  }
41066 
41067  }
41068 
41069  },
41070 
41071  // remember the state of the bound property and copy it to both accus
41072  saveOriginalState: function () {
41073 
41074  var binding = this.binding;
41075 
41076  var buffer = this.buffer,
41077  stride = this.valueSize,
41078 
41079  originalValueOffset = stride * 3;
41080 
41081  binding.getValue( buffer, originalValueOffset );
41082 
41083  // accu[0..1] := orig -- initially detect changes against the original
41084  for ( var i = stride, e = originalValueOffset; i !== e; ++ i ) {
41085 
41086  buffer[ i ] = buffer[ originalValueOffset + ( i % stride ) ];
41087 
41088  }
41089 
41090  this.cumulativeWeight = 0;
41091 
41092  },
41093 
41094  // apply the state previously taken via 'saveOriginalState' to the binding
41095  restoreOriginalState: function () {
41096 
41097  var originalValueOffset = this.valueSize * 3;
41098  this.binding.setValue( this.buffer, originalValueOffset );
41099 
41100  },
41101 
41102 
41103  // mix functions
41104 
41105  _select: function ( buffer, dstOffset, srcOffset, t, stride ) {
41106 
41107  if ( t >= 0.5 ) {
41108 
41109  for ( var i = 0; i !== stride; ++ i ) {
41110 
41111  buffer[ dstOffset + i ] = buffer[ srcOffset + i ];
41112 
41113  }
41114 
41115  }
41116 
41117  },
41118 
41119  _slerp: function ( buffer, dstOffset, srcOffset, t ) {
41120 
41121  Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, srcOffset, t );
41122 
41123  },
41124 
41125  _lerp: function ( buffer, dstOffset, srcOffset, t, stride ) {
41126 
41127  var s = 1 - t;
41128 
41129  for ( var i = 0; i !== stride; ++ i ) {
41130 
41131  var j = dstOffset + i;
41132 
41133  buffer[ j ] = buffer[ j ] * s + buffer[ srcOffset + i ] * t;
41134 
41135  }
41136 
41137  }
41138 
41139  } );
41140 
41151  // Characters [].:/ are reserved for track binding syntax.
41152  var RESERVED_CHARS_RE = '\\[\\]\\.:\\/';
41153 
41154  function Composite( targetGroup, path, optionalParsedPath ) {
41155 
41156  var parsedPath = optionalParsedPath || PropertyBinding.parseTrackName( path );
41157 
41158  this._targetGroup = targetGroup;
41159  this._bindings = targetGroup.subscribe_( path, parsedPath );
41160 
41161  }
41162 
41163  Object.assign( Composite.prototype, {
41164 
41165  getValue: function ( array, offset ) {
41166 
41167  this.bind(); // bind all binding
41168 
41169  var firstValidIndex = this._targetGroup.nCachedObjects_,
41170  binding = this._bindings[ firstValidIndex ];
41171 
41172  // and only call .getValue on the first
41173  if ( binding !== undefined ) binding.getValue( array, offset );
41174 
41175  },
41176 
41177  setValue: function ( array, offset ) {
41178 
41179  var bindings = this._bindings;
41180 
41181  for ( var i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {
41182 
41183  bindings[ i ].setValue( array, offset );
41184 
41185  }
41186 
41187  },
41188 
41189  bind: function () {
41190 
41191  var bindings = this._bindings;
41192 
41193  for ( var i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {
41194 
41195  bindings[ i ].bind();
41196 
41197  }
41198 
41199  },
41200 
41201  unbind: function () {
41202 
41203  var bindings = this._bindings;
41204 
41205  for ( var i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {
41206 
41207  bindings[ i ].unbind();
41208 
41209  }
41210 
41211  }
41212 
41213  } );
41214 
41215 
41216  function PropertyBinding( rootNode, path, parsedPath ) {
41217 
41218  this.path = path;
41219  this.parsedPath = parsedPath || PropertyBinding.parseTrackName( path );
41220 
41221  this.node = PropertyBinding.findNode( rootNode, this.parsedPath.nodeName ) || rootNode;
41222 
41223  this.rootNode = rootNode;
41224 
41225  }
41226 
41227  Object.assign( PropertyBinding, {
41228 
41229  Composite: Composite,
41230 
41231  create: function ( root, path, parsedPath ) {
41232 
41233  if ( ! ( root && root.isAnimationObjectGroup ) ) {
41234 
41235  return new PropertyBinding( root, path, parsedPath );
41236 
41237  } else {
41238 
41239  return new PropertyBinding.Composite( root, path, parsedPath );
41240 
41241  }
41242 
41243  },
41244 
41252  sanitizeNodeName: ( function () {
41253 
41254  var reservedRe = new RegExp( '[' + RESERVED_CHARS_RE + ']', 'g' );
41255 
41256  return function sanitizeNodeName( name ) {
41257 
41258  return name.replace( /\s/g, '_' ).replace( reservedRe, '' );
41259 
41260  };
41261 
41262  }() ),
41263 
41264  parseTrackName: function () {
41265 
41266  // Attempts to allow node names from any language. ES5's `\w` regexp matches
41267  // only latin characters, and the unicode \p{L} is not yet supported. So
41268  // instead, we exclude reserved characters and match everything else.
41269  var wordChar = '[^' + RESERVED_CHARS_RE + ']';
41270  var wordCharOrDot = '[^' + RESERVED_CHARS_RE.replace( '\\.', '' ) + ']';
41271 
41272  // Parent directories, delimited by '/' or ':'. Currently unused, but must
41273  // be matched to parse the rest of the track name.
41274  var directoryRe = /((?:WC+[\/:])*)/.source.replace( 'WC', wordChar );
41275 
41276  // Target node. May contain word characters (a-zA-Z0-9_) and '.' or '-'.
41277  var nodeRe = /(WCOD+)?/.source.replace( 'WCOD', wordCharOrDot );
41278 
41279  // Object on target node, and accessor. May not contain reserved
41280  // characters. Accessor may contain any character except closing bracket.
41281  var objectRe = /(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace( 'WC', wordChar );
41282 
41283  // Property and accessor. May not contain reserved characters. Accessor may
41284  // contain any non-bracket characters.
41285  var propertyRe = /\.(WC+)(?:\[(.+)\])?/.source.replace( 'WC', wordChar );
41286 
41287  var trackRe = new RegExp( ''
41288  + '^'
41289  + directoryRe
41290  + nodeRe
41291  + objectRe
41292  + propertyRe
41293  + '$'
41294  );
41295 
41296  var supportedObjectNames = [ 'material', 'materials', 'bones' ];
41297 
41298  return function parseTrackName( trackName ) {
41299 
41300  var matches = trackRe.exec( trackName );
41301 
41302  if ( ! matches ) {
41303 
41304  throw new Error( 'PropertyBinding: Cannot parse trackName: ' + trackName );
41305 
41306  }
41307 
41308  var results = {
41309  // directoryName: matches[ 1 ], // (tschw) currently unused
41310  nodeName: matches[ 2 ],
41311  objectName: matches[ 3 ],
41312  objectIndex: matches[ 4 ],
41313  propertyName: matches[ 5 ], // required
41314  propertyIndex: matches[ 6 ]
41315  };
41316 
41317  var lastDot = results.nodeName && results.nodeName.lastIndexOf( '.' );
41318 
41319  if ( lastDot !== undefined && lastDot !== - 1 ) {
41320 
41321  var objectName = results.nodeName.substring( lastDot + 1 );
41322 
41323  // Object names must be checked against a whitelist. Otherwise, there
41324  // is no way to parse 'foo.bar.baz': 'baz' must be a property, but
41325  // 'bar' could be the objectName, or part of a nodeName (which can
41326  // include '.' characters).
41327  if ( supportedObjectNames.indexOf( objectName ) !== - 1 ) {
41328 
41329  results.nodeName = results.nodeName.substring( 0, lastDot );
41330  results.objectName = objectName;
41331 
41332  }
41333 
41334  }
41335 
41336  if ( results.propertyName === null || results.propertyName.length === 0 ) {
41337 
41338  throw new Error( 'PropertyBinding: can not parse propertyName from trackName: ' + trackName );
41339 
41340  }
41341 
41342  return results;
41343 
41344  };
41345 
41346  }(),
41347 
41348  findNode: function ( root, nodeName ) {
41349 
41350  if ( ! nodeName || nodeName === "" || nodeName === "root" || nodeName === "." || nodeName === - 1 || nodeName === root.name || nodeName === root.uuid ) {
41351 
41352  return root;
41353 
41354  }
41355 
41356  // search into skeleton bones.
41357  if ( root.skeleton ) {
41358 
41359  var bone = root.skeleton.getBoneByName( nodeName );
41360 
41361  if ( bone !== undefined ) {
41362 
41363  return bone;
41364 
41365  }
41366 
41367  }
41368 
41369  // search into node subtree.
41370  if ( root.children ) {
41371 
41372  var searchNodeSubtree = function ( children ) {
41373 
41374  for ( var i = 0; i < children.length; i ++ ) {
41375 
41376  var childNode = children[ i ];
41377 
41378  if ( childNode.name === nodeName || childNode.uuid === nodeName ) {
41379 
41380  return childNode;
41381 
41382  }
41383 
41384  var result = searchNodeSubtree( childNode.children );
41385 
41386  if ( result ) return result;
41387 
41388  }
41389 
41390  return null;
41391 
41392  };
41393 
41394  var subTreeNode = searchNodeSubtree( root.children );
41395 
41396  if ( subTreeNode ) {
41397 
41398  return subTreeNode;
41399 
41400  }
41401 
41402  }
41403 
41404  return null;
41405 
41406  }
41407 
41408  } );
41409 
41410  Object.assign( PropertyBinding.prototype, { // prototype, continued
41411 
41412  // these are used to "bind" a nonexistent property
41413  _getValue_unavailable: function () {},
41414  _setValue_unavailable: function () {},
41415 
41416  BindingType: {
41417  Direct: 0,
41418  EntireArray: 1,
41419  ArrayElement: 2,
41420  HasFromToArray: 3
41421  },
41422 
41423  Versioning: {
41424  None: 0,
41425  NeedsUpdate: 1,
41426  MatrixWorldNeedsUpdate: 2
41427  },
41428 
41429  GetterByBindingType: [
41430 
41431  function getValue_direct( buffer, offset ) {
41432 
41433  buffer[ offset ] = this.node[ this.propertyName ];
41434 
41435  },
41436 
41437  function getValue_array( buffer, offset ) {
41438 
41439  var source = this.resolvedProperty;
41440 
41441  for ( var i = 0, n = source.length; i !== n; ++ i ) {
41442 
41443  buffer[ offset ++ ] = source[ i ];
41444 
41445  }
41446 
41447  },
41448 
41449  function getValue_arrayElement( buffer, offset ) {
41450 
41451  buffer[ offset ] = this.resolvedProperty[ this.propertyIndex ];
41452 
41453  },
41454 
41455  function getValue_toArray( buffer, offset ) {
41456 
41457  this.resolvedProperty.toArray( buffer, offset );
41458 
41459  }
41460 
41461  ],
41462 
41463  SetterByBindingTypeAndVersioning: [
41464 
41465  [
41466  // Direct
41467 
41468  function setValue_direct( buffer, offset ) {
41469 
41470  this.targetObject[ this.propertyName ] = buffer[ offset ];
41471 
41472  },
41473 
41474  function setValue_direct_setNeedsUpdate( buffer, offset ) {
41475 
41476  this.targetObject[ this.propertyName ] = buffer[ offset ];
41477  this.targetObject.needsUpdate = true;
41478 
41479  },
41480 
41481  function setValue_direct_setMatrixWorldNeedsUpdate( buffer, offset ) {
41482 
41483  this.targetObject[ this.propertyName ] = buffer[ offset ];
41484  this.targetObject.matrixWorldNeedsUpdate = true;
41485 
41486  }
41487 
41488  ], [
41489 
41490  // EntireArray
41491 
41492  function setValue_array( buffer, offset ) {
41493 
41494  var dest = this.resolvedProperty;
41495 
41496  for ( var i = 0, n = dest.length; i !== n; ++ i ) {
41497 
41498  dest[ i ] = buffer[ offset ++ ];
41499 
41500  }
41501 
41502  },
41503 
41504  function setValue_array_setNeedsUpdate( buffer, offset ) {
41505 
41506  var dest = this.resolvedProperty;
41507 
41508  for ( var i = 0, n = dest.length; i !== n; ++ i ) {
41509 
41510  dest[ i ] = buffer[ offset ++ ];
41511 
41512  }
41513 
41514  this.targetObject.needsUpdate = true;
41515 
41516  },
41517 
41518  function setValue_array_setMatrixWorldNeedsUpdate( buffer, offset ) {
41519 
41520  var dest = this.resolvedProperty;
41521 
41522  for ( var i = 0, n = dest.length; i !== n; ++ i ) {
41523 
41524  dest[ i ] = buffer[ offset ++ ];
41525 
41526  }
41527 
41528  this.targetObject.matrixWorldNeedsUpdate = true;
41529 
41530  }
41531 
41532  ], [
41533 
41534  // ArrayElement
41535 
41536  function setValue_arrayElement( buffer, offset ) {
41537 
41538  this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
41539 
41540  },
41541 
41542  function setValue_arrayElement_setNeedsUpdate( buffer, offset ) {
41543 
41544  this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
41545  this.targetObject.needsUpdate = true;
41546 
41547  },
41548 
41549  function setValue_arrayElement_setMatrixWorldNeedsUpdate( buffer, offset ) {
41550 
41551  this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
41552  this.targetObject.matrixWorldNeedsUpdate = true;
41553 
41554  }
41555 
41556  ], [
41557 
41558  // HasToFromArray
41559 
41560  function setValue_fromArray( buffer, offset ) {
41561 
41562  this.resolvedProperty.fromArray( buffer, offset );
41563 
41564  },
41565 
41566  function setValue_fromArray_setNeedsUpdate( buffer, offset ) {
41567 
41568  this.resolvedProperty.fromArray( buffer, offset );
41569  this.targetObject.needsUpdate = true;
41570 
41571  },
41572 
41573  function setValue_fromArray_setMatrixWorldNeedsUpdate( buffer, offset ) {
41574 
41575  this.resolvedProperty.fromArray( buffer, offset );
41576  this.targetObject.matrixWorldNeedsUpdate = true;
41577 
41578  }
41579 
41580  ]
41581 
41582  ],
41583 
41584  getValue: function getValue_unbound( targetArray, offset ) {
41585 
41586  this.bind();
41587  this.getValue( targetArray, offset );
41588 
41589  // Note: This class uses a State pattern on a per-method basis:
41590  // 'bind' sets 'this.getValue' / 'setValue' and shadows the
41591  // prototype version of these methods with one that represents
41592  // the bound state. When the property is not found, the methods
41593  // become no-ops.
41594 
41595  },
41596 
41597  setValue: function getValue_unbound( sourceArray, offset ) {
41598 
41599  this.bind();
41600  this.setValue( sourceArray, offset );
41601 
41602  },
41603 
41604  // create getter / setter pair for a property in the scene graph
41605  bind: function () {
41606 
41607  var targetObject = this.node,
41608  parsedPath = this.parsedPath,
41609 
41610  objectName = parsedPath.objectName,
41611  propertyName = parsedPath.propertyName,
41612  propertyIndex = parsedPath.propertyIndex;
41613 
41614  if ( ! targetObject ) {
41615 
41616  targetObject = PropertyBinding.findNode( this.rootNode, parsedPath.nodeName ) || this.rootNode;
41617 
41618  this.node = targetObject;
41619 
41620  }
41621 
41622  // set fail state so we can just 'return' on error
41623  this.getValue = this._getValue_unavailable;
41624  this.setValue = this._setValue_unavailable;
41625 
41626  // ensure there is a value node
41627  if ( ! targetObject ) {
41628 
41629  console.error( 'THREE.PropertyBinding: Trying to update node for track: ' + this.path + ' but it wasn\'t found.' );
41630  return;
41631 
41632  }
41633 
41634  if ( objectName ) {
41635 
41636  var objectIndex = parsedPath.objectIndex;
41637 
41638  // special cases were we need to reach deeper into the hierarchy to get the face materials....
41639  switch ( objectName ) {
41640 
41641  case 'materials':
41642 
41643  if ( ! targetObject.material ) {
41644 
41645  console.error( 'THREE.PropertyBinding: Can not bind to material as node does not have a material.', this );
41646  return;
41647 
41648  }
41649 
41650  if ( ! targetObject.material.materials ) {
41651 
41652  console.error( 'THREE.PropertyBinding: Can not bind to material.materials as node.material does not have a materials array.', this );
41653  return;
41654 
41655  }
41656 
41657  targetObject = targetObject.material.materials;
41658 
41659  break;
41660 
41661  case 'bones':
41662 
41663  if ( ! targetObject.skeleton ) {
41664 
41665  console.error( 'THREE.PropertyBinding: Can not bind to bones as node does not have a skeleton.', this );
41666  return;
41667 
41668  }
41669 
41670  // potential future optimization: skip this if propertyIndex is already an integer
41671  // and convert the integer string to a true integer.
41672 
41673  targetObject = targetObject.skeleton.bones;
41674 
41675  // support resolving morphTarget names into indices.
41676  for ( var i = 0; i < targetObject.length; i ++ ) {
41677 
41678  if ( targetObject[ i ].name === objectIndex ) {
41679 
41680  objectIndex = i;
41681  break;
41682 
41683  }
41684 
41685  }
41686 
41687  break;
41688 
41689  default:
41690 
41691  if ( targetObject[ objectName ] === undefined ) {
41692 
41693  console.error( 'THREE.PropertyBinding: Can not bind to objectName of node undefined.', this );
41694  return;
41695 
41696  }
41697 
41698  targetObject = targetObject[ objectName ];
41699 
41700  }
41701 
41702 
41703  if ( objectIndex !== undefined ) {
41704 
41705  if ( targetObject[ objectIndex ] === undefined ) {
41706 
41707  console.error( 'THREE.PropertyBinding: Trying to bind to objectIndex of objectName, but is undefined.', this, targetObject );
41708  return;
41709 
41710  }
41711 
41712  targetObject = targetObject[ objectIndex ];
41713 
41714  }
41715 
41716  }
41717 
41718  // resolve property
41719  var nodeProperty = targetObject[ propertyName ];
41720 
41721  if ( nodeProperty === undefined ) {
41722 
41723  var nodeName = parsedPath.nodeName;
41724 
41725  console.error( 'THREE.PropertyBinding: Trying to update property for track: ' + nodeName +
41726  '.' + propertyName + ' but it wasn\'t found.', targetObject );
41727  return;
41728 
41729  }
41730 
41731  // determine versioning scheme
41732  var versioning = this.Versioning.None;
41733 
41734  this.targetObject = targetObject;
41735 
41736  if ( targetObject.needsUpdate !== undefined ) { // material
41737 
41738  versioning = this.Versioning.NeedsUpdate;
41739 
41740  } else if ( targetObject.matrixWorldNeedsUpdate !== undefined ) { // node transform
41741 
41742  versioning = this.Versioning.MatrixWorldNeedsUpdate;
41743 
41744  }
41745 
41746  // determine how the property gets bound
41747  var bindingType = this.BindingType.Direct;
41748 
41749  if ( propertyIndex !== undefined ) {
41750 
41751  // access a sub element of the property array (only primitives are supported right now)
41752 
41753  if ( propertyName === "morphTargetInfluences" ) {
41754 
41755  // potential optimization, skip this if propertyIndex is already an integer, and convert the integer string to a true integer.
41756 
41757  // support resolving morphTarget names into indices.
41758  if ( ! targetObject.geometry ) {
41759 
41760  console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.', this );
41761  return;
41762 
41763  }
41764 
41765  if ( targetObject.geometry.isBufferGeometry ) {
41766 
41767  if ( ! targetObject.geometry.morphAttributes ) {
41768 
41769  console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphAttributes.', this );
41770  return;
41771 
41772  }
41773 
41774  for ( var i = 0; i < this.node.geometry.morphAttributes.position.length; i ++ ) {
41775 
41776  if ( targetObject.geometry.morphAttributes.position[ i ].name === propertyIndex ) {
41777 
41778  propertyIndex = i;
41779  break;
41780 
41781  }
41782 
41783  }
41784 
41785 
41786  } else {
41787 
41788  if ( ! targetObject.geometry.morphTargets ) {
41789 
41790  console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphTargets.', this );
41791  return;
41792 
41793  }
41794 
41795  for ( var i = 0; i < this.node.geometry.morphTargets.length; i ++ ) {
41796 
41797  if ( targetObject.geometry.morphTargets[ i ].name === propertyIndex ) {
41798 
41799  propertyIndex = i;
41800  break;
41801 
41802  }
41803 
41804  }
41805 
41806  }
41807 
41808  }
41809 
41810  bindingType = this.BindingType.ArrayElement;
41811 
41812  this.resolvedProperty = nodeProperty;
41813  this.propertyIndex = propertyIndex;
41814 
41815  } else if ( nodeProperty.fromArray !== undefined && nodeProperty.toArray !== undefined ) {
41816 
41817  // must use copy for Object3D.Euler/Quaternion
41818 
41819  bindingType = this.BindingType.HasFromToArray;
41820 
41821  this.resolvedProperty = nodeProperty;
41822 
41823  } else if ( Array.isArray( nodeProperty ) ) {
41824 
41825  bindingType = this.BindingType.EntireArray;
41826 
41827  this.resolvedProperty = nodeProperty;
41828 
41829  } else {
41830 
41831  this.propertyName = propertyName;
41832 
41833  }
41834 
41835  // select getter / setter
41836  this.getValue = this.GetterByBindingType[ bindingType ];
41837  this.setValue = this.SetterByBindingTypeAndVersioning[ bindingType ][ versioning ];
41838 
41839  },
41840 
41841  unbind: function () {
41842 
41843  this.node = null;
41844 
41845  // back to the prototype version of getValue / setValue
41846  // note: avoiding to mutate the shape of 'this' via 'delete'
41847  this.getValue = this._getValue_unbound;
41848  this.setValue = this._setValue_unbound;
41849 
41850  }
41851 
41852  } );
41853 
41855  Object.assign( PropertyBinding.prototype, {
41856 
41857  // initial state of these methods that calls 'bind'
41858  _getValue_unbound: PropertyBinding.prototype.getValue,
41859  _setValue_unbound: PropertyBinding.prototype.setValue,
41860 
41861  } );
41862 
41894  function AnimationObjectGroup() {
41895 
41896  this.uuid = _Math.generateUUID();
41897 
41898  // cached objects followed by the active ones
41899  this._objects = Array.prototype.slice.call( arguments );
41900 
41901  this.nCachedObjects_ = 0; // threshold
41902  // note: read by PropertyBinding.Composite
41903 
41904  var indices = {};
41905  this._indicesByUUID = indices; // for bookkeeping
41906 
41907  for ( var i = 0, n = arguments.length; i !== n; ++ i ) {
41908 
41909  indices[ arguments[ i ].uuid ] = i;
41910 
41911  }
41912 
41913  this._paths = []; // inside: string
41914  this._parsedPaths = []; // inside: { we don't care, here }
41915  this._bindings = []; // inside: Array< PropertyBinding >
41916  this._bindingsIndicesByPath = {}; // inside: indices in these arrays
41917 
41918  var scope = this;
41919 
41920  this.stats = {
41921 
41922  objects: {
41923  get total() {
41924 
41925  return scope._objects.length;
41926 
41927  },
41928  get inUse() {
41929 
41930  return this.total - scope.nCachedObjects_;
41931 
41932  }
41933  },
41934  get bindingsPerObject() {
41935 
41936  return scope._bindings.length;
41937 
41938  }
41939 
41940  };
41941 
41942  }
41943 
41944  Object.assign( AnimationObjectGroup.prototype, {
41945 
41946  isAnimationObjectGroup: true,
41947 
41948  add: function () {
41949 
41950  var objects = this._objects,
41951  nObjects = objects.length,
41952  nCachedObjects = this.nCachedObjects_,
41953  indicesByUUID = this._indicesByUUID,
41954  paths = this._paths,
41955  parsedPaths = this._parsedPaths,
41956  bindings = this._bindings,
41957  nBindings = bindings.length,
41958  knownObject = undefined;
41959 
41960  for ( var i = 0, n = arguments.length; i !== n; ++ i ) {
41961 
41962  var object = arguments[ i ],
41963  uuid = object.uuid,
41964  index = indicesByUUID[ uuid ];
41965 
41966  if ( index === undefined ) {
41967 
41968  // unknown object -> add it to the ACTIVE region
41969 
41970  index = nObjects ++;
41971  indicesByUUID[ uuid ] = index;
41972  objects.push( object );
41973 
41974  // accounting is done, now do the same for all bindings
41975 
41976  for ( var j = 0, m = nBindings; j !== m; ++ j ) {
41977 
41978  bindings[ j ].push( new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ) );
41979 
41980  }
41981 
41982  } else if ( index < nCachedObjects ) {
41983 
41984  knownObject = objects[ index ];
41985 
41986  // move existing object to the ACTIVE region
41987 
41988  var firstActiveIndex = -- nCachedObjects,
41989  lastCachedObject = objects[ firstActiveIndex ];
41990 
41991  indicesByUUID[ lastCachedObject.uuid ] = index;
41992  objects[ index ] = lastCachedObject;
41993 
41994  indicesByUUID[ uuid ] = firstActiveIndex;
41995  objects[ firstActiveIndex ] = object;
41996 
41997  // accounting is done, now do the same for all bindings
41998 
41999  for ( var j = 0, m = nBindings; j !== m; ++ j ) {
42000 
42001  var bindingsForPath = bindings[ j ],
42002  lastCached = bindingsForPath[ firstActiveIndex ],
42003  binding = bindingsForPath[ index ];
42004 
42005  bindingsForPath[ index ] = lastCached;
42006 
42007  if ( binding === undefined ) {
42008 
42009  // since we do not bother to create new bindings
42010  // for objects that are cached, the binding may
42011  // or may not exist
42012 
42013  binding = new PropertyBinding( object, paths[ j ], parsedPaths[ j ] );
42014 
42015  }
42016 
42017  bindingsForPath[ firstActiveIndex ] = binding;
42018 
42019  }
42020 
42021  } else if ( objects[ index ] !== knownObject ) {
42022 
42023  console.error( 'THREE.AnimationObjectGroup: Different objects with the same UUID ' +
42024  'detected. Clean the caches or recreate your infrastructure when reloading scenes.' );
42025 
42026  } // else the object is already where we want it to be
42027 
42028  } // for arguments
42029 
42030  this.nCachedObjects_ = nCachedObjects;
42031 
42032  },
42033 
42034  remove: function () {
42035 
42036  var objects = this._objects,
42037  nCachedObjects = this.nCachedObjects_,
42038  indicesByUUID = this._indicesByUUID,
42039  bindings = this._bindings,
42040  nBindings = bindings.length;
42041 
42042  for ( var i = 0, n = arguments.length; i !== n; ++ i ) {
42043 
42044  var object = arguments[ i ],
42045  uuid = object.uuid,
42046  index = indicesByUUID[ uuid ];
42047 
42048  if ( index !== undefined && index >= nCachedObjects ) {
42049 
42050  // move existing object into the CACHED region
42051 
42052  var lastCachedIndex = nCachedObjects ++,
42053  firstActiveObject = objects[ lastCachedIndex ];
42054 
42055  indicesByUUID[ firstActiveObject.uuid ] = index;
42056  objects[ index ] = firstActiveObject;
42057 
42058  indicesByUUID[ uuid ] = lastCachedIndex;
42059  objects[ lastCachedIndex ] = object;
42060 
42061  // accounting is done, now do the same for all bindings
42062 
42063  for ( var j = 0, m = nBindings; j !== m; ++ j ) {
42064 
42065  var bindingsForPath = bindings[ j ],
42066  firstActive = bindingsForPath[ lastCachedIndex ],
42067  binding = bindingsForPath[ index ];
42068 
42069  bindingsForPath[ index ] = firstActive;
42070  bindingsForPath[ lastCachedIndex ] = binding;
42071 
42072  }
42073 
42074  }
42075 
42076  } // for arguments
42077 
42078  this.nCachedObjects_ = nCachedObjects;
42079 
42080  },
42081 
42082  // remove & forget
42083  uncache: function () {
42084 
42085  var objects = this._objects,
42086  nObjects = objects.length,
42087  nCachedObjects = this.nCachedObjects_,
42088  indicesByUUID = this._indicesByUUID,
42089  bindings = this._bindings,
42090  nBindings = bindings.length;
42091 
42092  for ( var i = 0, n = arguments.length; i !== n; ++ i ) {
42093 
42094  var object = arguments[ i ],
42095  uuid = object.uuid,
42096  index = indicesByUUID[ uuid ];
42097 
42098  if ( index !== undefined ) {
42099 
42100  delete indicesByUUID[ uuid ];
42101 
42102  if ( index < nCachedObjects ) {
42103 
42104  // object is cached, shrink the CACHED region
42105 
42106  var firstActiveIndex = -- nCachedObjects,
42107  lastCachedObject = objects[ firstActiveIndex ],
42108  lastIndex = -- nObjects,
42109  lastObject = objects[ lastIndex ];
42110 
42111  // last cached object takes this object's place
42112  indicesByUUID[ lastCachedObject.uuid ] = index;
42113  objects[ index ] = lastCachedObject;
42114 
42115  // last object goes to the activated slot and pop
42116  indicesByUUID[ lastObject.uuid ] = firstActiveIndex;
42117  objects[ firstActiveIndex ] = lastObject;
42118  objects.pop();
42119 
42120  // accounting is done, now do the same for all bindings
42121 
42122  for ( var j = 0, m = nBindings; j !== m; ++ j ) {
42123 
42124  var bindingsForPath = bindings[ j ],
42125  lastCached = bindingsForPath[ firstActiveIndex ],
42126  last = bindingsForPath[ lastIndex ];
42127 
42128  bindingsForPath[ index ] = lastCached;
42129  bindingsForPath[ firstActiveIndex ] = last;
42130  bindingsForPath.pop();
42131 
42132  }
42133 
42134  } else {
42135 
42136  // object is active, just swap with the last and pop
42137 
42138  var lastIndex = -- nObjects,
42139  lastObject = objects[ lastIndex ];
42140 
42141  indicesByUUID[ lastObject.uuid ] = index;
42142  objects[ index ] = lastObject;
42143  objects.pop();
42144 
42145  // accounting is done, now do the same for all bindings
42146 
42147  for ( var j = 0, m = nBindings; j !== m; ++ j ) {
42148 
42149  var bindingsForPath = bindings[ j ];
42150 
42151  bindingsForPath[ index ] = bindingsForPath[ lastIndex ];
42152  bindingsForPath.pop();
42153 
42154  }
42155 
42156  } // cached or active
42157 
42158  } // if object is known
42159 
42160  } // for arguments
42161 
42162  this.nCachedObjects_ = nCachedObjects;
42163 
42164  },
42165 
42166  // Internal interface used by befriended PropertyBinding.Composite:
42167 
42168  subscribe_: function ( path, parsedPath ) {
42169 
42170  // returns an array of bindings for the given path that is changed
42171  // according to the contained objects in the group
42172 
42173  var indicesByPath = this._bindingsIndicesByPath,
42174  index = indicesByPath[ path ],
42175  bindings = this._bindings;
42176 
42177  if ( index !== undefined ) return bindings[ index ];
42178 
42179  var paths = this._paths,
42180  parsedPaths = this._parsedPaths,
42181  objects = this._objects,
42182  nObjects = objects.length,
42183  nCachedObjects = this.nCachedObjects_,
42184  bindingsForPath = new Array( nObjects );
42185 
42186  index = bindings.length;
42187 
42188  indicesByPath[ path ] = index;
42189 
42190  paths.push( path );
42191  parsedPaths.push( parsedPath );
42192  bindings.push( bindingsForPath );
42193 
42194  for ( var i = nCachedObjects, n = objects.length; i !== n; ++ i ) {
42195 
42196  var object = objects[ i ];
42197  bindingsForPath[ i ] = new PropertyBinding( object, path, parsedPath );
42198 
42199  }
42200 
42201  return bindingsForPath;
42202 
42203  },
42204 
42205  unsubscribe_: function ( path ) {
42206 
42207  // tells the group to forget about a property path and no longer
42208  // update the array previously obtained with 'subscribe_'
42209 
42210  var indicesByPath = this._bindingsIndicesByPath,
42211  index = indicesByPath[ path ];
42212 
42213  if ( index !== undefined ) {
42214 
42215  var paths = this._paths,
42216  parsedPaths = this._parsedPaths,
42217  bindings = this._bindings,
42218  lastBindingsIndex = bindings.length - 1,
42219  lastBindings = bindings[ lastBindingsIndex ],
42220  lastBindingsPath = path[ lastBindingsIndex ];
42221 
42222  indicesByPath[ lastBindingsPath ] = index;
42223 
42224  bindings[ index ] = lastBindings;
42225  bindings.pop();
42226 
42227  parsedPaths[ index ] = parsedPaths[ lastBindingsIndex ];
42228  parsedPaths.pop();
42229 
42230  paths[ index ] = paths[ lastBindingsIndex ];
42231  paths.pop();
42232 
42233  }
42234 
42235  }
42236 
42237  } );
42238 
42250  function AnimationAction( mixer, clip, localRoot ) {
42251 
42252  this._mixer = mixer;
42253  this._clip = clip;
42254  this._localRoot = localRoot || null;
42255 
42256  var tracks = clip.tracks,
42257  nTracks = tracks.length,
42258  interpolants = new Array( nTracks );
42259 
42260  var interpolantSettings = {
42261  endingStart: ZeroCurvatureEnding,
42262  endingEnd: ZeroCurvatureEnding
42263  };
42264 
42265  for ( var i = 0; i !== nTracks; ++ i ) {
42266 
42267  var interpolant = tracks[ i ].createInterpolant( null );
42268  interpolants[ i ] = interpolant;
42269  interpolant.settings = interpolantSettings;
42270 
42271  }
42272 
42273  this._interpolantSettings = interpolantSettings;
42274 
42275  this._interpolants = interpolants; // bound by the mixer
42276 
42277  // inside: PropertyMixer (managed by the mixer)
42278  this._propertyBindings = new Array( nTracks );
42279 
42280  this._cacheIndex = null; // for the memory manager
42281  this._byClipCacheIndex = null; // for the memory manager
42282 
42283  this._timeScaleInterpolant = null;
42284  this._weightInterpolant = null;
42285 
42286  this.loop = LoopRepeat;
42287  this._loopCount = - 1;
42288 
42289  // global mixer time when the action is to be started
42290  // it's set back to 'null' upon start of the action
42291  this._startTime = null;
42292 
42293  // scaled local time of the action
42294  // gets clamped or wrapped to 0..clip.duration according to loop
42295  this.time = 0;
42296 
42297  this.timeScale = 1;
42298  this._effectiveTimeScale = 1;
42299 
42300  this.weight = 1;
42301  this._effectiveWeight = 1;
42302 
42303  this.repetitions = Infinity; // no. of repetitions when looping
42304 
42305  this.paused = false; // true -> zero effective time scale
42306  this.enabled = true; // false -> zero effective weight
42307 
42308  this.clampWhenFinished = false;// keep feeding the last frame?
42309 
42310  this.zeroSlopeAtStart = true;// for smooth interpolation w/o separate
42311  this.zeroSlopeAtEnd = true;// clips for start, loop and end
42312 
42313  }
42314 
42315  Object.assign( AnimationAction.prototype, {
42316 
42317  // State & Scheduling
42318 
42319  play: function () {
42320 
42321  this._mixer._activateAction( this );
42322 
42323  return this;
42324 
42325  },
42326 
42327  stop: function () {
42328 
42329  this._mixer._deactivateAction( this );
42330 
42331  return this.reset();
42332 
42333  },
42334 
42335  reset: function () {
42336 
42337  this.paused = false;
42338  this.enabled = true;
42339 
42340  this.time = 0; // restart clip
42341  this._loopCount = - 1;// forget previous loops
42342  this._startTime = null;// forget scheduling
42343 
42344  return this.stopFading().stopWarping();
42345 
42346  },
42347 
42348  isRunning: function () {
42349 
42350  return this.enabled && ! this.paused && this.timeScale !== 0 &&
42351  this._startTime === null && this._mixer._isActiveAction( this );
42352 
42353  },
42354 
42355  // return true when play has been called
42356  isScheduled: function () {
42357 
42358  return this._mixer._isActiveAction( this );
42359 
42360  },
42361 
42362  startAt: function ( time ) {
42363 
42364  this._startTime = time;
42365 
42366  return this;
42367 
42368  },
42369 
42370  setLoop: function ( mode, repetitions ) {
42371 
42372  this.loop = mode;
42373  this.repetitions = repetitions;
42374 
42375  return this;
42376 
42377  },
42378 
42379  // Weight
42380 
42381  // set the weight stopping any scheduled fading
42382  // although .enabled = false yields an effective weight of zero, this
42383  // method does *not* change .enabled, because it would be confusing
42384  setEffectiveWeight: function ( weight ) {
42385 
42386  this.weight = weight;
42387 
42388  // note: same logic as when updated at runtime
42389  this._effectiveWeight = this.enabled ? weight : 0;
42390 
42391  return this.stopFading();
42392 
42393  },
42394 
42395  // return the weight considering fading and .enabled
42396  getEffectiveWeight: function () {
42397 
42398  return this._effectiveWeight;
42399 
42400  },
42401 
42402  fadeIn: function ( duration ) {
42403 
42404  return this._scheduleFading( duration, 0, 1 );
42405 
42406  },
42407 
42408  fadeOut: function ( duration ) {
42409 
42410  return this._scheduleFading( duration, 1, 0 );
42411 
42412  },
42413 
42414  crossFadeFrom: function ( fadeOutAction, duration, warp ) {
42415 
42416  fadeOutAction.fadeOut( duration );
42417  this.fadeIn( duration );
42418 
42419  if ( warp ) {
42420 
42421  var fadeInDuration = this._clip.duration,
42422  fadeOutDuration = fadeOutAction._clip.duration,
42423 
42424  startEndRatio = fadeOutDuration / fadeInDuration,
42425  endStartRatio = fadeInDuration / fadeOutDuration;
42426 
42427  fadeOutAction.warp( 1.0, startEndRatio, duration );
42428  this.warp( endStartRatio, 1.0, duration );
42429 
42430  }
42431 
42432  return this;
42433 
42434  },
42435 
42436  crossFadeTo: function ( fadeInAction, duration, warp ) {
42437 
42438  return fadeInAction.crossFadeFrom( this, duration, warp );
42439 
42440  },
42441 
42442  stopFading: function () {
42443 
42444  var weightInterpolant = this._weightInterpolant;
42445 
42446  if ( weightInterpolant !== null ) {
42447 
42448  this._weightInterpolant = null;
42449  this._mixer._takeBackControlInterpolant( weightInterpolant );
42450 
42451  }
42452 
42453  return this;
42454 
42455  },
42456 
42457  // Time Scale Control
42458 
42459  // set the time scale stopping any scheduled warping
42460  // although .paused = true yields an effective time scale of zero, this
42461  // method does *not* change .paused, because it would be confusing
42462  setEffectiveTimeScale: function ( timeScale ) {
42463 
42464  this.timeScale = timeScale;
42465  this._effectiveTimeScale = this.paused ? 0 : timeScale;
42466 
42467  return this.stopWarping();
42468 
42469  },
42470 
42471  // return the time scale considering warping and .paused
42472  getEffectiveTimeScale: function () {
42473 
42474  return this._effectiveTimeScale;
42475 
42476  },
42477 
42478  setDuration: function ( duration ) {
42479 
42480  this.timeScale = this._clip.duration / duration;
42481 
42482  return this.stopWarping();
42483 
42484  },
42485 
42486  syncWith: function ( action ) {
42487 
42488  this.time = action.time;
42489  this.timeScale = action.timeScale;
42490 
42491  return this.stopWarping();
42492 
42493  },
42494 
42495  halt: function ( duration ) {
42496 
42497  return this.warp( this._effectiveTimeScale, 0, duration );
42498 
42499  },
42500 
42501  warp: function ( startTimeScale, endTimeScale, duration ) {
42502 
42503  var mixer = this._mixer, now = mixer.time,
42504  interpolant = this._timeScaleInterpolant,
42505 
42506  timeScale = this.timeScale;
42507 
42508  if ( interpolant === null ) {
42509 
42510  interpolant = mixer._lendControlInterpolant();
42511  this._timeScaleInterpolant = interpolant;
42512 
42513  }
42514 
42515  var times = interpolant.parameterPositions,
42516  values = interpolant.sampleValues;
42517 
42518  times[ 0 ] = now;
42519  times[ 1 ] = now + duration;
42520 
42521  values[ 0 ] = startTimeScale / timeScale;
42522  values[ 1 ] = endTimeScale / timeScale;
42523 
42524  return this;
42525 
42526  },
42527 
42528  stopWarping: function () {
42529 
42530  var timeScaleInterpolant = this._timeScaleInterpolant;
42531 
42532  if ( timeScaleInterpolant !== null ) {
42533 
42534  this._timeScaleInterpolant = null;
42535  this._mixer._takeBackControlInterpolant( timeScaleInterpolant );
42536 
42537  }
42538 
42539  return this;
42540 
42541  },
42542 
42543  // Object Accessors
42544 
42545  getMixer: function () {
42546 
42547  return this._mixer;
42548 
42549  },
42550 
42551  getClip: function () {
42552 
42553  return this._clip;
42554 
42555  },
42556 
42557  getRoot: function () {
42558 
42559  return this._localRoot || this._mixer._root;
42560 
42561  },
42562 
42563  // Interna
42564 
42565  _update: function ( time, deltaTime, timeDirection, accuIndex ) {
42566 
42567  // called by the mixer
42568 
42569  if ( ! this.enabled ) {
42570 
42571  // call ._updateWeight() to update ._effectiveWeight
42572 
42573  this._updateWeight( time );
42574  return;
42575 
42576  }
42577 
42578  var startTime = this._startTime;
42579 
42580  if ( startTime !== null ) {
42581 
42582  // check for scheduled start of action
42583 
42584  var timeRunning = ( time - startTime ) * timeDirection;
42585  if ( timeRunning < 0 || timeDirection === 0 ) {
42586 
42587  return; // yet to come / don't decide when delta = 0
42588 
42589  }
42590 
42591  // start
42592 
42593  this._startTime = null; // unschedule
42594  deltaTime = timeDirection * timeRunning;
42595 
42596  }
42597 
42598  // apply time scale and advance time
42599 
42600  deltaTime *= this._updateTimeScale( time );
42601  var clipTime = this._updateTime( deltaTime );
42602 
42603  // note: _updateTime may disable the action resulting in
42604  // an effective weight of 0
42605 
42606  var weight = this._updateWeight( time );
42607 
42608  if ( weight > 0 ) {
42609 
42610  var interpolants = this._interpolants;
42611  var propertyMixers = this._propertyBindings;
42612 
42613  for ( var j = 0, m = interpolants.length; j !== m; ++ j ) {
42614 
42615  interpolants[ j ].evaluate( clipTime );
42616  propertyMixers[ j ].accumulate( accuIndex, weight );
42617 
42618  }
42619 
42620  }
42621 
42622  },
42623 
42624  _updateWeight: function ( time ) {
42625 
42626  var weight = 0;
42627 
42628  if ( this.enabled ) {
42629 
42630  weight = this.weight;
42631  var interpolant = this._weightInterpolant;
42632 
42633  if ( interpolant !== null ) {
42634 
42635  var interpolantValue = interpolant.evaluate( time )[ 0 ];
42636 
42637  weight *= interpolantValue;
42638 
42639  if ( time > interpolant.parameterPositions[ 1 ] ) {
42640 
42641  this.stopFading();
42642 
42643  if ( interpolantValue === 0 ) {
42644 
42645  // faded out, disable
42646  this.enabled = false;
42647 
42648  }
42649 
42650  }
42651 
42652  }
42653 
42654  }
42655 
42656  this._effectiveWeight = weight;
42657  return weight;
42658 
42659  },
42660 
42661  _updateTimeScale: function ( time ) {
42662 
42663  var timeScale = 0;
42664 
42665  if ( ! this.paused ) {
42666 
42667  timeScale = this.timeScale;
42668 
42669  var interpolant = this._timeScaleInterpolant;
42670 
42671  if ( interpolant !== null ) {
42672 
42673  var interpolantValue = interpolant.evaluate( time )[ 0 ];
42674 
42675  timeScale *= interpolantValue;
42676 
42677  if ( time > interpolant.parameterPositions[ 1 ] ) {
42678 
42679  this.stopWarping();
42680 
42681  if ( timeScale === 0 ) {
42682 
42683  // motion has halted, pause
42684  this.paused = true;
42685 
42686  } else {
42687 
42688  // warp done - apply final time scale
42689  this.timeScale = timeScale;
42690 
42691  }
42692 
42693  }
42694 
42695  }
42696 
42697  }
42698 
42699  this._effectiveTimeScale = timeScale;
42700  return timeScale;
42701 
42702  },
42703 
42704  _updateTime: function ( deltaTime ) {
42705 
42706  var time = this.time + deltaTime;
42707  var duration = this._clip.duration;
42708  var loop = this.loop;
42709  var loopCount = this._loopCount;
42710 
42711  var pingPong = ( loop === LoopPingPong );
42712 
42713  if ( deltaTime === 0 ) {
42714 
42715  if ( loopCount === - 1 ) return time;
42716 
42717  return ( pingPong && ( loopCount & 1 ) === 1 ) ? duration - time : time;
42718 
42719  }
42720 
42721  if ( loop === LoopOnce ) {
42722 
42723  if ( loopCount === - 1 ) {
42724 
42725  // just started
42726 
42727  this._loopCount = 0;
42728  this._setEndings( true, true, false );
42729 
42730  }
42731 
42732  handle_stop: {
42733 
42734  if ( time >= duration ) {
42735 
42736  time = duration;
42737 
42738  } else if ( time < 0 ) {
42739 
42740  time = 0;
42741 
42742  } else break handle_stop;
42743 
42744  if ( this.clampWhenFinished ) this.paused = true;
42745  else this.enabled = false;
42746 
42747  this._mixer.dispatchEvent( {
42748  type: 'finished', action: this,
42749  direction: deltaTime < 0 ? - 1 : 1
42750  } );
42751 
42752  }
42753 
42754  } else { // repetitive Repeat or PingPong
42755 
42756  if ( loopCount === - 1 ) {
42757 
42758  // just started
42759 
42760  if ( deltaTime >= 0 ) {
42761 
42762  loopCount = 0;
42763 
42764  this._setEndings( true, this.repetitions === 0, pingPong );
42765 
42766  } else {
42767 
42768  // when looping in reverse direction, the initial
42769  // transition through zero counts as a repetition,
42770  // so leave loopCount at -1
42771 
42772  this._setEndings( this.repetitions === 0, true, pingPong );
42773 
42774  }
42775 
42776  }
42777 
42778  if ( time >= duration || time < 0 ) {
42779 
42780  // wrap around
42781 
42782  var loopDelta = Math.floor( time / duration ); // signed
42783  time -= duration * loopDelta;
42784 
42785  loopCount += Math.abs( loopDelta );
42786 
42787  var pending = this.repetitions - loopCount;
42788 
42789  if ( pending <= 0 ) {
42790 
42791  // have to stop (switch state, clamp time, fire event)
42792 
42793  if ( this.clampWhenFinished ) this.paused = true;
42794  else this.enabled = false;
42795 
42796  time = deltaTime > 0 ? duration : 0;
42797 
42798  this._mixer.dispatchEvent( {
42799  type: 'finished', action: this,
42800  direction: deltaTime > 0 ? 1 : - 1
42801  } );
42802 
42803  } else {
42804 
42805  // keep running
42806 
42807  if ( pending === 1 ) {
42808 
42809  // entering the last round
42810 
42811  var atStart = deltaTime < 0;
42812  this._setEndings( atStart, ! atStart, pingPong );
42813 
42814  } else {
42815 
42816  this._setEndings( false, false, pingPong );
42817 
42818  }
42819 
42820  this._loopCount = loopCount;
42821 
42822  this._mixer.dispatchEvent( {
42823  type: 'loop', action: this, loopDelta: loopDelta
42824  } );
42825 
42826  }
42827 
42828  }
42829 
42830  if ( pingPong && ( loopCount & 1 ) === 1 ) {
42831 
42832  // invert time for the "pong round"
42833 
42834  this.time = time;
42835  return duration - time;
42836 
42837  }
42838 
42839  }
42840 
42841  this.time = time;
42842  return time;
42843 
42844  },
42845 
42846  _setEndings: function ( atStart, atEnd, pingPong ) {
42847 
42848  var settings = this._interpolantSettings;
42849 
42850  if ( pingPong ) {
42851 
42852  settings.endingStart = ZeroSlopeEnding;
42853  settings.endingEnd = ZeroSlopeEnding;
42854 
42855  } else {
42856 
42857  // assuming for LoopOnce atStart == atEnd == true
42858 
42859  if ( atStart ) {
42860 
42861  settings.endingStart = this.zeroSlopeAtStart ? ZeroSlopeEnding : ZeroCurvatureEnding;
42862 
42863  } else {
42864 
42865  settings.endingStart = WrapAroundEnding;
42866 
42867  }
42868 
42869  if ( atEnd ) {
42870 
42871  settings.endingEnd = this.zeroSlopeAtEnd ? ZeroSlopeEnding : ZeroCurvatureEnding;
42872 
42873  } else {
42874 
42875  settings.endingEnd = WrapAroundEnding;
42876 
42877  }
42878 
42879  }
42880 
42881  },
42882 
42883  _scheduleFading: function ( duration, weightNow, weightThen ) {
42884 
42885  var mixer = this._mixer, now = mixer.time,
42886  interpolant = this._weightInterpolant;
42887 
42888  if ( interpolant === null ) {
42889 
42890  interpolant = mixer._lendControlInterpolant();
42891  this._weightInterpolant = interpolant;
42892 
42893  }
42894 
42895  var times = interpolant.parameterPositions,
42896  values = interpolant.sampleValues;
42897 
42898  times[ 0 ] = now;
42899  values[ 0 ] = weightNow;
42900  times[ 1 ] = now + duration;
42901  values[ 1 ] = weightThen;
42902 
42903  return this;
42904 
42905  }
42906 
42907  } );
42908 
42919  function AnimationMixer( root ) {
42920 
42921  this._root = root;
42922  this._initMemoryManager();
42923  this._accuIndex = 0;
42924 
42925  this.time = 0;
42926 
42927  this.timeScale = 1.0;
42928 
42929  }
42930 
42931  AnimationMixer.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
42932 
42933  constructor: AnimationMixer,
42934 
42935  _bindAction: function ( action, prototypeAction ) {
42936 
42937  var root = action._localRoot || this._root,
42938  tracks = action._clip.tracks,
42939  nTracks = tracks.length,
42940  bindings = action._propertyBindings,
42941  interpolants = action._interpolants,
42942  rootUuid = root.uuid,
42943  bindingsByRoot = this._bindingsByRootAndName,
42944  bindingsByName = bindingsByRoot[ rootUuid ];
42945 
42946  if ( bindingsByName === undefined ) {
42947 
42948  bindingsByName = {};
42949  bindingsByRoot[ rootUuid ] = bindingsByName;
42950 
42951  }
42952 
42953  for ( var i = 0; i !== nTracks; ++ i ) {
42954 
42955  var track = tracks[ i ],
42956  trackName = track.name,
42957  binding = bindingsByName[ trackName ];
42958 
42959  if ( binding !== undefined ) {
42960 
42961  bindings[ i ] = binding;
42962 
42963  } else {
42964 
42965  binding = bindings[ i ];
42966 
42967  if ( binding !== undefined ) {
42968 
42969  // existing binding, make sure the cache knows
42970 
42971  if ( binding._cacheIndex === null ) {
42972 
42973  ++ binding.referenceCount;
42974  this._addInactiveBinding( binding, rootUuid, trackName );
42975 
42976  }
42977 
42978  continue;
42979 
42980  }
42981 
42982  var path = prototypeAction && prototypeAction.
42983  _propertyBindings[ i ].binding.parsedPath;
42984 
42985  binding = new PropertyMixer(
42986  PropertyBinding.create( root, trackName, path ),
42987  track.ValueTypeName, track.getValueSize() );
42988 
42989  ++ binding.referenceCount;
42990  this._addInactiveBinding( binding, rootUuid, trackName );
42991 
42992  bindings[ i ] = binding;
42993 
42994  }
42995 
42996  interpolants[ i ].resultBuffer = binding.buffer;
42997 
42998  }
42999 
43000  },
43001 
43002  _activateAction: function ( action ) {
43003 
43004  if ( ! this._isActiveAction( action ) ) {
43005 
43006  if ( action._cacheIndex === null ) {
43007 
43008  // this action has been forgotten by the cache, but the user
43009  // appears to be still using it -> rebind
43010 
43011  var rootUuid = ( action._localRoot || this._root ).uuid,
43012  clipUuid = action._clip.uuid,
43013  actionsForClip = this._actionsByClip[ clipUuid ];
43014 
43015  this._bindAction( action,
43016  actionsForClip && actionsForClip.knownActions[ 0 ] );
43017 
43018  this._addInactiveAction( action, clipUuid, rootUuid );
43019 
43020  }
43021 
43022  var bindings = action._propertyBindings;
43023 
43024  // increment reference counts / sort out state
43025  for ( var i = 0, n = bindings.length; i !== n; ++ i ) {
43026 
43027  var binding = bindings[ i ];
43028 
43029  if ( binding.useCount ++ === 0 ) {
43030 
43031  this._lendBinding( binding );
43032  binding.saveOriginalState();
43033 
43034  }
43035 
43036  }
43037 
43038  this._lendAction( action );
43039 
43040  }
43041 
43042  },
43043 
43044  _deactivateAction: function ( action ) {
43045 
43046  if ( this._isActiveAction( action ) ) {
43047 
43048  var bindings = action._propertyBindings;
43049 
43050  // decrement reference counts / sort out state
43051  for ( var i = 0, n = bindings.length; i !== n; ++ i ) {
43052 
43053  var binding = bindings[ i ];
43054 
43055  if ( -- binding.useCount === 0 ) {
43056 
43057  binding.restoreOriginalState();
43058  this._takeBackBinding( binding );
43059 
43060  }
43061 
43062  }
43063 
43064  this._takeBackAction( action );
43065 
43066  }
43067 
43068  },
43069 
43070  // Memory manager
43071 
43072  _initMemoryManager: function () {
43073 
43074  this._actions = []; // 'nActiveActions' followed by inactive ones
43075  this._nActiveActions = 0;
43076 
43077  this._actionsByClip = {};
43078  // inside:
43079  // {
43080  // knownActions: Array< AnimationAction > - used as prototypes
43081  // actionByRoot: AnimationAction - lookup
43082  // }
43083 
43084 
43085  this._bindings = []; // 'nActiveBindings' followed by inactive ones
43086  this._nActiveBindings = 0;
43087 
43088  this._bindingsByRootAndName = {}; // inside: Map< name, PropertyMixer >
43089 
43090 
43091  this._controlInterpolants = []; // same game as above
43092  this._nActiveControlInterpolants = 0;
43093 
43094  var scope = this;
43095 
43096  this.stats = {
43097 
43098  actions: {
43099  get total() {
43100 
43101  return scope._actions.length;
43102 
43103  },
43104  get inUse() {
43105 
43106  return scope._nActiveActions;
43107 
43108  }
43109  },
43110  bindings: {
43111  get total() {
43112 
43113  return scope._bindings.length;
43114 
43115  },
43116  get inUse() {
43117 
43118  return scope._nActiveBindings;
43119 
43120  }
43121  },
43122  controlInterpolants: {
43123  get total() {
43124 
43125  return scope._controlInterpolants.length;
43126 
43127  },
43128  get inUse() {
43129 
43130  return scope._nActiveControlInterpolants;
43131 
43132  }
43133  }
43134 
43135  };
43136 
43137  },
43138 
43139  // Memory management for AnimationAction objects
43140 
43141  _isActiveAction: function ( action ) {
43142 
43143  var index = action._cacheIndex;
43144  return index !== null && index < this._nActiveActions;
43145 
43146  },
43147 
43148  _addInactiveAction: function ( action, clipUuid, rootUuid ) {
43149 
43150  var actions = this._actions,
43151  actionsByClip = this._actionsByClip,
43152  actionsForClip = actionsByClip[ clipUuid ];
43153 
43154  if ( actionsForClip === undefined ) {
43155 
43156  actionsForClip = {
43157 
43158  knownActions: [ action ],
43159  actionByRoot: {}
43160 
43161  };
43162 
43163  action._byClipCacheIndex = 0;
43164 
43165  actionsByClip[ clipUuid ] = actionsForClip;
43166 
43167  } else {
43168 
43169  var knownActions = actionsForClip.knownActions;
43170 
43171  action._byClipCacheIndex = knownActions.length;
43172  knownActions.push( action );
43173 
43174  }
43175 
43176  action._cacheIndex = actions.length;
43177  actions.push( action );
43178 
43179  actionsForClip.actionByRoot[ rootUuid ] = action;
43180 
43181  },
43182 
43183  _removeInactiveAction: function ( action ) {
43184 
43185  var actions = this._actions,
43186  lastInactiveAction = actions[ actions.length - 1 ],
43187  cacheIndex = action._cacheIndex;
43188 
43189  lastInactiveAction._cacheIndex = cacheIndex;
43190  actions[ cacheIndex ] = lastInactiveAction;
43191  actions.pop();
43192 
43193  action._cacheIndex = null;
43194 
43195 
43196  var clipUuid = action._clip.uuid,
43197  actionsByClip = this._actionsByClip,
43198  actionsForClip = actionsByClip[ clipUuid ],
43199  knownActionsForClip = actionsForClip.knownActions,
43200 
43201  lastKnownAction =
43202  knownActionsForClip[ knownActionsForClip.length - 1 ],
43203 
43204  byClipCacheIndex = action._byClipCacheIndex;
43205 
43206  lastKnownAction._byClipCacheIndex = byClipCacheIndex;
43207  knownActionsForClip[ byClipCacheIndex ] = lastKnownAction;
43208  knownActionsForClip.pop();
43209 
43210  action._byClipCacheIndex = null;
43211 
43212 
43213  var actionByRoot = actionsForClip.actionByRoot,
43214  rootUuid = ( action._localRoot || this._root ).uuid;
43215 
43216  delete actionByRoot[ rootUuid ];
43217 
43218  if ( knownActionsForClip.length === 0 ) {
43219 
43220  delete actionsByClip[ clipUuid ];
43221 
43222  }
43223 
43224  this._removeInactiveBindingsForAction( action );
43225 
43226  },
43227 
43228  _removeInactiveBindingsForAction: function ( action ) {
43229 
43230  var bindings = action._propertyBindings;
43231  for ( var i = 0, n = bindings.length; i !== n; ++ i ) {
43232 
43233  var binding = bindings[ i ];
43234 
43235  if ( -- binding.referenceCount === 0 ) {
43236 
43237  this._removeInactiveBinding( binding );
43238 
43239  }
43240 
43241  }
43242 
43243  },
43244 
43245  _lendAction: function ( action ) {
43246 
43247  // [ active actions | inactive actions ]
43248  // [ active actions >| inactive actions ]
43249  // s a
43250  // <-swap->
43251  // a s
43252 
43253  var actions = this._actions,
43254  prevIndex = action._cacheIndex,
43255 
43256  lastActiveIndex = this._nActiveActions ++,
43257 
43258  firstInactiveAction = actions[ lastActiveIndex ];
43259 
43260  action._cacheIndex = lastActiveIndex;
43261  actions[ lastActiveIndex ] = action;
43262 
43263  firstInactiveAction._cacheIndex = prevIndex;
43264  actions[ prevIndex ] = firstInactiveAction;
43265 
43266  },
43267 
43268  _takeBackAction: function ( action ) {
43269 
43270  // [ active actions | inactive actions ]
43271  // [ active actions |< inactive actions ]
43272  // a s
43273  // <-swap->
43274  // s a
43275 
43276  var actions = this._actions,
43277  prevIndex = action._cacheIndex,
43278 
43279  firstInactiveIndex = -- this._nActiveActions,
43280 
43281  lastActiveAction = actions[ firstInactiveIndex ];
43282 
43283  action._cacheIndex = firstInactiveIndex;
43284  actions[ firstInactiveIndex ] = action;
43285 
43286  lastActiveAction._cacheIndex = prevIndex;
43287  actions[ prevIndex ] = lastActiveAction;
43288 
43289  },
43290 
43291  // Memory management for PropertyMixer objects
43292 
43293  _addInactiveBinding: function ( binding, rootUuid, trackName ) {
43294 
43295  var bindingsByRoot = this._bindingsByRootAndName,
43296  bindingByName = bindingsByRoot[ rootUuid ],
43297 
43298  bindings = this._bindings;
43299 
43300  if ( bindingByName === undefined ) {
43301 
43302  bindingByName = {};
43303  bindingsByRoot[ rootUuid ] = bindingByName;
43304 
43305  }
43306 
43307  bindingByName[ trackName ] = binding;
43308 
43309  binding._cacheIndex = bindings.length;
43310  bindings.push( binding );
43311 
43312  },
43313 
43314  _removeInactiveBinding: function ( binding ) {
43315 
43316  var bindings = this._bindings,
43317  propBinding = binding.binding,
43318  rootUuid = propBinding.rootNode.uuid,
43319  trackName = propBinding.path,
43320  bindingsByRoot = this._bindingsByRootAndName,
43321  bindingByName = bindingsByRoot[ rootUuid ],
43322 
43323  lastInactiveBinding = bindings[ bindings.length - 1 ],
43324  cacheIndex = binding._cacheIndex;
43325 
43326  lastInactiveBinding._cacheIndex = cacheIndex;
43327  bindings[ cacheIndex ] = lastInactiveBinding;
43328  bindings.pop();
43329 
43330  delete bindingByName[ trackName ];
43331 
43332  remove_empty_map: {
43333 
43334  for ( var _ in bindingByName ) break remove_empty_map; // eslint-disable-line no-unused-vars
43335 
43336  delete bindingsByRoot[ rootUuid ];
43337 
43338  }
43339 
43340  },
43341 
43342  _lendBinding: function ( binding ) {
43343 
43344  var bindings = this._bindings,
43345  prevIndex = binding._cacheIndex,
43346 
43347  lastActiveIndex = this._nActiveBindings ++,
43348 
43349  firstInactiveBinding = bindings[ lastActiveIndex ];
43350 
43351  binding._cacheIndex = lastActiveIndex;
43352  bindings[ lastActiveIndex ] = binding;
43353 
43354  firstInactiveBinding._cacheIndex = prevIndex;
43355  bindings[ prevIndex ] = firstInactiveBinding;
43356 
43357  },
43358 
43359  _takeBackBinding: function ( binding ) {
43360 
43361  var bindings = this._bindings,
43362  prevIndex = binding._cacheIndex,
43363 
43364  firstInactiveIndex = -- this._nActiveBindings,
43365 
43366  lastActiveBinding = bindings[ firstInactiveIndex ];
43367 
43368  binding._cacheIndex = firstInactiveIndex;
43369  bindings[ firstInactiveIndex ] = binding;
43370 
43371  lastActiveBinding._cacheIndex = prevIndex;
43372  bindings[ prevIndex ] = lastActiveBinding;
43373 
43374  },
43375 
43376 
43377  // Memory management of Interpolants for weight and time scale
43378 
43379  _lendControlInterpolant: function () {
43380 
43381  var interpolants = this._controlInterpolants,
43382  lastActiveIndex = this._nActiveControlInterpolants ++,
43383  interpolant = interpolants[ lastActiveIndex ];
43384 
43385  if ( interpolant === undefined ) {
43386 
43387  interpolant = new LinearInterpolant(
43388  new Float32Array( 2 ), new Float32Array( 2 ),
43389  1, this._controlInterpolantsResultBuffer );
43390 
43391  interpolant.__cacheIndex = lastActiveIndex;
43392  interpolants[ lastActiveIndex ] = interpolant;
43393 
43394  }
43395 
43396  return interpolant;
43397 
43398  },
43399 
43400  _takeBackControlInterpolant: function ( interpolant ) {
43401 
43402  var interpolants = this._controlInterpolants,
43403  prevIndex = interpolant.__cacheIndex,
43404 
43405  firstInactiveIndex = -- this._nActiveControlInterpolants,
43406 
43407  lastActiveInterpolant = interpolants[ firstInactiveIndex ];
43408 
43409  interpolant.__cacheIndex = firstInactiveIndex;
43410  interpolants[ firstInactiveIndex ] = interpolant;
43411 
43412  lastActiveInterpolant.__cacheIndex = prevIndex;
43413  interpolants[ prevIndex ] = lastActiveInterpolant;
43414 
43415  },
43416 
43417  _controlInterpolantsResultBuffer: new Float32Array( 1 ),
43418 
43419  // return an action for a clip optionally using a custom root target
43420  // object (this method allocates a lot of dynamic memory in case a
43421  // previously unknown clip/root combination is specified)
43422  clipAction: function ( clip, optionalRoot ) {
43423 
43424  var root = optionalRoot || this._root,
43425  rootUuid = root.uuid,
43426 
43427  clipObject = typeof clip === 'string' ?
43428  AnimationClip.findByName( root, clip ) : clip,
43429 
43430  clipUuid = clipObject !== null ? clipObject.uuid : clip,
43431 
43432  actionsForClip = this._actionsByClip[ clipUuid ],
43433  prototypeAction = null;
43434 
43435  if ( actionsForClip !== undefined ) {
43436 
43437  var existingAction =
43438  actionsForClip.actionByRoot[ rootUuid ];
43439 
43440  if ( existingAction !== undefined ) {
43441 
43442  return existingAction;
43443 
43444  }
43445 
43446  // we know the clip, so we don't have to parse all
43447  // the bindings again but can just copy
43448  prototypeAction = actionsForClip.knownActions[ 0 ];
43449 
43450  // also, take the clip from the prototype action
43451  if ( clipObject === null )
43452  clipObject = prototypeAction._clip;
43453 
43454  }
43455 
43456  // clip must be known when specified via string
43457  if ( clipObject === null ) return null;
43458 
43459  // allocate all resources required to run it
43460  var newAction = new AnimationAction( this, clipObject, optionalRoot );
43461 
43462  this._bindAction( newAction, prototypeAction );
43463 
43464  // and make the action known to the memory manager
43465  this._addInactiveAction( newAction, clipUuid, rootUuid );
43466 
43467  return newAction;
43468 
43469  },
43470 
43471  // get an existing action
43472  existingAction: function ( clip, optionalRoot ) {
43473 
43474  var root = optionalRoot || this._root,
43475  rootUuid = root.uuid,
43476 
43477  clipObject = typeof clip === 'string' ?
43478  AnimationClip.findByName( root, clip ) : clip,
43479 
43480  clipUuid = clipObject ? clipObject.uuid : clip,
43481 
43482  actionsForClip = this._actionsByClip[ clipUuid ];
43483 
43484  if ( actionsForClip !== undefined ) {
43485 
43486  return actionsForClip.actionByRoot[ rootUuid ] || null;
43487 
43488  }
43489 
43490  return null;
43491 
43492  },
43493 
43494  // deactivates all previously scheduled actions
43495  stopAllAction: function () {
43496 
43497  var actions = this._actions,
43498  nActions = this._nActiveActions,
43499  bindings = this._bindings,
43500  nBindings = this._nActiveBindings;
43501 
43502  this._nActiveActions = 0;
43503  this._nActiveBindings = 0;
43504 
43505  for ( var i = 0; i !== nActions; ++ i ) {
43506 
43507  actions[ i ].reset();
43508 
43509  }
43510 
43511  for ( var i = 0; i !== nBindings; ++ i ) {
43512 
43513  bindings[ i ].useCount = 0;
43514 
43515  }
43516 
43517  return this;
43518 
43519  },
43520 
43521  // advance the time and update apply the animation
43522  update: function ( deltaTime ) {
43523 
43524  deltaTime *= this.timeScale;
43525 
43526  var actions = this._actions,
43527  nActions = this._nActiveActions,
43528 
43529  time = this.time += deltaTime,
43530  timeDirection = Math.sign( deltaTime ),
43531 
43532  accuIndex = this._accuIndex ^= 1;
43533 
43534  // run active actions
43535 
43536  for ( var i = 0; i !== nActions; ++ i ) {
43537 
43538  var action = actions[ i ];
43539 
43540  action._update( time, deltaTime, timeDirection, accuIndex );
43541 
43542  }
43543 
43544  // update scene graph
43545 
43546  var bindings = this._bindings,
43547  nBindings = this._nActiveBindings;
43548 
43549  for ( var i = 0; i !== nBindings; ++ i ) {
43550 
43551  bindings[ i ].apply( accuIndex );
43552 
43553  }
43554 
43555  return this;
43556 
43557  },
43558 
43559  // return this mixer's root target object
43560  getRoot: function () {
43561 
43562  return this._root;
43563 
43564  },
43565 
43566  // free all resources specific to a particular clip
43567  uncacheClip: function ( clip ) {
43568 
43569  var actions = this._actions,
43570  clipUuid = clip.uuid,
43571  actionsByClip = this._actionsByClip,
43572  actionsForClip = actionsByClip[ clipUuid ];
43573 
43574  if ( actionsForClip !== undefined ) {
43575 
43576  // note: just calling _removeInactiveAction would mess up the
43577  // iteration state and also require updating the state we can
43578  // just throw away
43579 
43580  var actionsToRemove = actionsForClip.knownActions;
43581 
43582  for ( var i = 0, n = actionsToRemove.length; i !== n; ++ i ) {
43583 
43584  var action = actionsToRemove[ i ];
43585 
43586  this._deactivateAction( action );
43587 
43588  var cacheIndex = action._cacheIndex,
43589  lastInactiveAction = actions[ actions.length - 1 ];
43590 
43591  action._cacheIndex = null;
43592  action._byClipCacheIndex = null;
43593 
43594  lastInactiveAction._cacheIndex = cacheIndex;
43595  actions[ cacheIndex ] = lastInactiveAction;
43596  actions.pop();
43597 
43598  this._removeInactiveBindingsForAction( action );
43599 
43600  }
43601 
43602  delete actionsByClip[ clipUuid ];
43603 
43604  }
43605 
43606  },
43607 
43608  // free all resources specific to a particular root target object
43609  uncacheRoot: function ( root ) {
43610 
43611  var rootUuid = root.uuid,
43612  actionsByClip = this._actionsByClip;
43613 
43614  for ( var clipUuid in actionsByClip ) {
43615 
43616  var actionByRoot = actionsByClip[ clipUuid ].actionByRoot,
43617  action = actionByRoot[ rootUuid ];
43618 
43619  if ( action !== undefined ) {
43620 
43621  this._deactivateAction( action );
43622  this._removeInactiveAction( action );
43623 
43624  }
43625 
43626  }
43627 
43628  var bindingsByRoot = this._bindingsByRootAndName,
43629  bindingByName = bindingsByRoot[ rootUuid ];
43630 
43631  if ( bindingByName !== undefined ) {
43632 
43633  for ( var trackName in bindingByName ) {
43634 
43635  var binding = bindingByName[ trackName ];
43636  binding.restoreOriginalState();
43637  this._removeInactiveBinding( binding );
43638 
43639  }
43640 
43641  }
43642 
43643  },
43644 
43645  // remove a targeted clip from the cache
43646  uncacheAction: function ( clip, optionalRoot ) {
43647 
43648  var action = this.existingAction( clip, optionalRoot );
43649 
43650  if ( action !== null ) {
43651 
43652  this._deactivateAction( action );
43653  this._removeInactiveAction( action );
43654 
43655  }
43656 
43657  }
43658 
43659  } );
43660 
43665  function Uniform( value ) {
43666 
43667  if ( typeof value === 'string' ) {
43668 
43669  console.warn( 'THREE.Uniform: Type parameter is no longer needed.' );
43670  value = arguments[ 1 ];
43671 
43672  }
43673 
43674  this.value = value;
43675 
43676  }
43677 
43678  Uniform.prototype.clone = function () {
43679 
43680  return new Uniform( this.value.clone === undefined ? this.value : this.value.clone() );
43681 
43682  };
43683 
43688  function InstancedBufferGeometry() {
43689 
43690  BufferGeometry.call( this );
43691 
43692  this.type = 'InstancedBufferGeometry';
43693  this.maxInstancedCount = undefined;
43694 
43695  }
43696 
43697  InstancedBufferGeometry.prototype = Object.assign( Object.create( BufferGeometry.prototype ), {
43698 
43699  constructor: InstancedBufferGeometry,
43700 
43701  isInstancedBufferGeometry: true,
43702 
43703  copy: function ( source ) {
43704 
43705  BufferGeometry.prototype.copy.call( this, source );
43706 
43707  this.maxInstancedCount = source.maxInstancedCount;
43708 
43709  return this;
43710 
43711  },
43712 
43713  clone: function () {
43714 
43715  return new this.constructor().copy( this );
43716 
43717  }
43718 
43719  } );
43720 
43725  function InstancedInterleavedBuffer( array, stride, meshPerAttribute ) {
43726 
43727  InterleavedBuffer.call( this, array, stride );
43728 
43729  this.meshPerAttribute = meshPerAttribute || 1;
43730 
43731  }
43732 
43733  InstancedInterleavedBuffer.prototype = Object.assign( Object.create( InterleavedBuffer.prototype ), {
43734 
43735  constructor: InstancedInterleavedBuffer,
43736 
43737  isInstancedInterleavedBuffer: true,
43738 
43739  copy: function ( source ) {
43740 
43741  InterleavedBuffer.prototype.copy.call( this, source );
43742 
43743  this.meshPerAttribute = source.meshPerAttribute;
43744 
43745  return this;
43746 
43747  }
43748 
43749  } );
43750 
43755  function InstancedBufferAttribute( array, itemSize, normalized, meshPerAttribute ) {
43756 
43757  if ( typeof ( normalized ) === 'number' ) {
43758 
43759  meshPerAttribute = normalized;
43760 
43761  normalized = false;
43762 
43763  console.error( 'THREE.InstancedBufferAttribute: The constructor now expects normalized as the third argument.' );
43764 
43765  }
43766 
43767  BufferAttribute.call( this, array, itemSize, normalized );
43768 
43769  this.meshPerAttribute = meshPerAttribute || 1;
43770 
43771  }
43772 
43773  InstancedBufferAttribute.prototype = Object.assign( Object.create( BufferAttribute.prototype ), {
43774 
43775  constructor: InstancedBufferAttribute,
43776 
43777  isInstancedBufferAttribute: true,
43778 
43779  copy: function ( source ) {
43780 
43781  BufferAttribute.prototype.copy.call( this, source );
43782 
43783  this.meshPerAttribute = source.meshPerAttribute;
43784 
43785  return this;
43786 
43787  }
43788 
43789  } );
43790 
43797  function Raycaster( origin, direction, near, far ) {
43798 
43799  this.ray = new Ray( origin, direction );
43800  // direction is assumed to be normalized (for accurate distance calculations)
43801 
43802  this.near = near || 0;
43803  this.far = far || Infinity;
43804 
43805  this.params = {
43806  Mesh: {},
43807  Line: {},
43808  LOD: {},
43809  Points: { threshold: 1 },
43810  Sprite: {}
43811  };
43812 
43813  Object.defineProperties( this.params, {
43814  PointCloud: {
43815  get: function () {
43816 
43817  console.warn( 'THREE.Raycaster: params.PointCloud has been renamed to params.Points.' );
43818  return this.Points;
43819 
43820  }
43821  }
43822  } );
43823 
43824  }
43825 
43826  function ascSort( a, b ) {
43827 
43828  return a.distance - b.distance;
43829 
43830  }
43831 
43832  function intersectObject( object, raycaster, intersects, recursive ) {
43833 
43834  if ( object.visible === false ) return;
43835 
43836  object.raycast( raycaster, intersects );
43837 
43838  if ( recursive === true ) {
43839 
43840  var children = object.children;
43841 
43842  for ( var i = 0, l = children.length; i < l; i ++ ) {
43843 
43844  intersectObject( children[ i ], raycaster, intersects, true );
43845 
43846  }
43847 
43848  }
43849 
43850  }
43851 
43852  Object.assign( Raycaster.prototype, {
43853 
43854  linePrecision: 1,
43855 
43856  set: function ( origin, direction ) {
43857 
43858  // direction is assumed to be normalized (for accurate distance calculations)
43859 
43860  this.ray.set( origin, direction );
43861 
43862  },
43863 
43864  setFromCamera: function ( coords, camera ) {
43865 
43866  if ( ( camera && camera.isPerspectiveCamera ) ) {
43867 
43868  this.ray.origin.setFromMatrixPosition( camera.matrixWorld );
43869  this.ray.direction.set( coords.x, coords.y, 0.5 ).unproject( camera ).sub( this.ray.origin ).normalize();
43870 
43871  } else if ( ( camera && camera.isOrthographicCamera ) ) {
43872 
43873  this.ray.origin.set( coords.x, coords.y, ( camera.near + camera.far ) / ( camera.near - camera.far ) ).unproject( camera ); // set origin in plane of camera
43874  this.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld );
43875 
43876  } else {
43877 
43878  console.error( 'THREE.Raycaster: Unsupported camera type.' );
43879 
43880  }
43881 
43882  },
43883 
43884  intersectObject: function ( object, recursive, optionalTarget ) {
43885 
43886  var intersects = optionalTarget || [];
43887 
43888  intersectObject( object, this, intersects, recursive );
43889 
43890  intersects.sort( ascSort );
43891 
43892  return intersects;
43893 
43894  },
43895 
43896  intersectObjects: function ( objects, recursive, optionalTarget ) {
43897 
43898  var intersects = optionalTarget || [];
43899 
43900  if ( Array.isArray( objects ) === false ) {
43901 
43902  console.warn( 'THREE.Raycaster.intersectObjects: objects is not an Array.' );
43903  return intersects;
43904 
43905  }
43906 
43907  for ( var i = 0, l = objects.length; i < l; i ++ ) {
43908 
43909  intersectObject( objects[ i ], this, intersects, recursive );
43910 
43911  }
43912 
43913  intersects.sort( ascSort );
43914 
43915  return intersects;
43916 
43917  }
43918 
43919  } );
43920 
43931  function Spherical( radius, phi, theta ) {
43932 
43933  this.radius = ( radius !== undefined ) ? radius : 1.0;
43934  this.phi = ( phi !== undefined ) ? phi : 0; // polar angle
43935  this.theta = ( theta !== undefined ) ? theta : 0; // azimuthal angle
43936 
43937  return this;
43938 
43939  }
43940 
43941  Object.assign( Spherical.prototype, {
43942 
43943  set: function ( radius, phi, theta ) {
43944 
43945  this.radius = radius;
43946  this.phi = phi;
43947  this.theta = theta;
43948 
43949  return this;
43950 
43951  },
43952 
43953  clone: function () {
43954 
43955  return new this.constructor().copy( this );
43956 
43957  },
43958 
43959  copy: function ( other ) {
43960 
43961  this.radius = other.radius;
43962  this.phi = other.phi;
43963  this.theta = other.theta;
43964 
43965  return this;
43966 
43967  },
43968 
43969  // restrict phi to be betwee EPS and PI-EPS
43970  makeSafe: function () {
43971 
43972  var EPS = 0.000001;
43973  this.phi = Math.max( EPS, Math.min( Math.PI - EPS, this.phi ) );
43974 
43975  return this;
43976 
43977  },
43978 
43979  setFromVector3: function ( v ) {
43980 
43981  return this.setFromCartesianCoords( v.x, v.y, v.z );
43982 
43983  },
43984 
43985  setFromCartesianCoords: function ( x, y, z ) {
43986 
43987  this.radius = Math.sqrt( x * x + y * y + z * z );
43988 
43989  if ( this.radius === 0 ) {
43990 
43991  this.theta = 0;
43992  this.phi = 0;
43993 
43994  } else {
43995 
43996  this.theta = Math.atan2( x, z );
43997  this.phi = Math.acos( _Math.clamp( y / this.radius, - 1, 1 ) );
43998 
43999  }
44000 
44001  return this;
44002 
44003  }
44004 
44005  } );
44006 
44014  function Cylindrical( radius, theta, y ) {
44015 
44016  this.radius = ( radius !== undefined ) ? radius : 1.0; // distance from the origin to a point in the x-z plane
44017  this.theta = ( theta !== undefined ) ? theta : 0; // counterclockwise angle in the x-z plane measured in radians from the positive z-axis
44018  this.y = ( y !== undefined ) ? y : 0; // height above the x-z plane
44019 
44020  return this;
44021 
44022  }
44023 
44024  Object.assign( Cylindrical.prototype, {
44025 
44026  set: function ( radius, theta, y ) {
44027 
44028  this.radius = radius;
44029  this.theta = theta;
44030  this.y = y;
44031 
44032  return this;
44033 
44034  },
44035 
44036  clone: function () {
44037 
44038  return new this.constructor().copy( this );
44039 
44040  },
44041 
44042  copy: function ( other ) {
44043 
44044  this.radius = other.radius;
44045  this.theta = other.theta;
44046  this.y = other.y;
44047 
44048  return this;
44049 
44050  },
44051 
44052  setFromVector3: function ( v ) {
44053 
44054  return this.setFromCartesianCoords( v.x, v.y, v.z );
44055 
44056  },
44057 
44058  setFromCartesianCoords: function ( x, y, z ) {
44059 
44060  this.radius = Math.sqrt( x * x + z * z );
44061  this.theta = Math.atan2( x, z );
44062  this.y = y;
44063 
44064  return this;
44065 
44066  }
44067 
44068  } );
44069 
44074  function Box2( min, max ) {
44075 
44076  this.min = ( min !== undefined ) ? min : new Vector2( + Infinity, + Infinity );
44077  this.max = ( max !== undefined ) ? max : new Vector2( - Infinity, - Infinity );
44078 
44079  }
44080 
44081  Object.assign( Box2.prototype, {
44082 
44083  set: function ( min, max ) {
44084 
44085  this.min.copy( min );
44086  this.max.copy( max );
44087 
44088  return this;
44089 
44090  },
44091 
44092  setFromPoints: function ( points ) {
44093 
44094  this.makeEmpty();
44095 
44096  for ( var i = 0, il = points.length; i < il; i ++ ) {
44097 
44098  this.expandByPoint( points[ i ] );
44099 
44100  }
44101 
44102  return this;
44103 
44104  },
44105 
44106  setFromCenterAndSize: function () {
44107 
44108  var v1 = new Vector2();
44109 
44110  return function setFromCenterAndSize( center, size ) {
44111 
44112  var halfSize = v1.copy( size ).multiplyScalar( 0.5 );
44113  this.min.copy( center ).sub( halfSize );
44114  this.max.copy( center ).add( halfSize );
44115 
44116  return this;
44117 
44118  };
44119 
44120  }(),
44121 
44122  clone: function () {
44123 
44124  return new this.constructor().copy( this );
44125 
44126  },
44127 
44128  copy: function ( box ) {
44129 
44130  this.min.copy( box.min );
44131  this.max.copy( box.max );
44132 
44133  return this;
44134 
44135  },
44136 
44137  makeEmpty: function () {
44138 
44139  this.min.x = this.min.y = + Infinity;
44140  this.max.x = this.max.y = - Infinity;
44141 
44142  return this;
44143 
44144  },
44145 
44146  isEmpty: function () {
44147 
44148  // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
44149 
44150  return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y );
44151 
44152  },
44153 
44154  getCenter: function ( target ) {
44155 
44156  if ( target === undefined ) {
44157 
44158  console.warn( 'THREE.Box2: .getCenter() target is now required' );
44159  target = new Vector2();
44160 
44161  }
44162 
44163  return this.isEmpty() ? target.set( 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 );
44164 
44165  },
44166 
44167  getSize: function ( target ) {
44168 
44169  if ( target === undefined ) {
44170 
44171  console.warn( 'THREE.Box2: .getSize() target is now required' );
44172  target = new Vector2();
44173 
44174  }
44175 
44176  return this.isEmpty() ? target.set( 0, 0 ) : target.subVectors( this.max, this.min );
44177 
44178  },
44179 
44180  expandByPoint: function ( point ) {
44181 
44182  this.min.min( point );
44183  this.max.max( point );
44184 
44185  return this;
44186 
44187  },
44188 
44189  expandByVector: function ( vector ) {
44190 
44191  this.min.sub( vector );
44192  this.max.add( vector );
44193 
44194  return this;
44195 
44196  },
44197 
44198  expandByScalar: function ( scalar ) {
44199 
44200  this.min.addScalar( - scalar );
44201  this.max.addScalar( scalar );
44202 
44203  return this;
44204 
44205  },
44206 
44207  containsPoint: function ( point ) {
44208 
44209  return point.x < this.min.x || point.x > this.max.x ||
44210  point.y < this.min.y || point.y > this.max.y ? false : true;
44211 
44212  },
44213 
44214  containsBox: function ( box ) {
44215 
44216  return this.min.x <= box.min.x && box.max.x <= this.max.x &&
44217  this.min.y <= box.min.y && box.max.y <= this.max.y;
44218 
44219  },
44220 
44221  getParameter: function ( point, target ) {
44222 
44223  // This can potentially have a divide by zero if the box
44224  // has a size dimension of 0.
44225 
44226  if ( target === undefined ) {
44227 
44228  console.warn( 'THREE.Box2: .getParameter() target is now required' );
44229  target = new Vector2();
44230 
44231  }
44232 
44233  return target.set(
44234  ( point.x - this.min.x ) / ( this.max.x - this.min.x ),
44235  ( point.y - this.min.y ) / ( this.max.y - this.min.y )
44236  );
44237 
44238  },
44239 
44240  intersectsBox: function ( box ) {
44241 
44242  // using 4 splitting planes to rule out intersections
44243 
44244  return box.max.x < this.min.x || box.min.x > this.max.x ||
44245  box.max.y < this.min.y || box.min.y > this.max.y ? false : true;
44246 
44247  },
44248 
44249  clampPoint: function ( point, target ) {
44250 
44251  if ( target === undefined ) {
44252 
44253  console.warn( 'THREE.Box2: .clampPoint() target is now required' );
44254  target = new Vector2();
44255 
44256  }
44257 
44258  return target.copy( point ).clamp( this.min, this.max );
44259 
44260  },
44261 
44262  distanceToPoint: function () {
44263 
44264  var v1 = new Vector2();
44265 
44266  return function distanceToPoint( point ) {
44267 
44268  var clampedPoint = v1.copy( point ).clamp( this.min, this.max );
44269  return clampedPoint.sub( point ).length();
44270 
44271  };
44272 
44273  }(),
44274 
44275  intersect: function ( box ) {
44276 
44277  this.min.max( box.min );
44278  this.max.min( box.max );
44279 
44280  return this;
44281 
44282  },
44283 
44284  union: function ( box ) {
44285 
44286  this.min.min( box.min );
44287  this.max.max( box.max );
44288 
44289  return this;
44290 
44291  },
44292 
44293  translate: function ( offset ) {
44294 
44295  this.min.add( offset );
44296  this.max.add( offset );
44297 
44298  return this;
44299 
44300  },
44301 
44302  equals: function ( box ) {
44303 
44304  return box.min.equals( this.min ) && box.max.equals( this.max );
44305 
44306  }
44307 
44308  } );
44309 
44314  function Line3( start, end ) {
44315 
44316  this.start = ( start !== undefined ) ? start : new Vector3();
44317  this.end = ( end !== undefined ) ? end : new Vector3();
44318 
44319  }
44320 
44321  Object.assign( Line3.prototype, {
44322 
44323  set: function ( start, end ) {
44324 
44325  this.start.copy( start );
44326  this.end.copy( end );
44327 
44328  return this;
44329 
44330  },
44331 
44332  clone: function () {
44333 
44334  return new this.constructor().copy( this );
44335 
44336  },
44337 
44338  copy: function ( line ) {
44339 
44340  this.start.copy( line.start );
44341  this.end.copy( line.end );
44342 
44343  return this;
44344 
44345  },
44346 
44347  getCenter: function ( target ) {
44348 
44349  if ( target === undefined ) {
44350 
44351  console.warn( 'THREE.Line3: .getCenter() target is now required' );
44352  target = new Vector3();
44353 
44354  }
44355 
44356  return target.addVectors( this.start, this.end ).multiplyScalar( 0.5 );
44357 
44358  },
44359 
44360  delta: function ( target ) {
44361 
44362  if ( target === undefined ) {
44363 
44364  console.warn( 'THREE.Line3: .delta() target is now required' );
44365  target = new Vector3();
44366 
44367  }
44368 
44369  return target.subVectors( this.end, this.start );
44370 
44371  },
44372 
44373  distanceSq: function () {
44374 
44375  return this.start.distanceToSquared( this.end );
44376 
44377  },
44378 
44379  distance: function () {
44380 
44381  return this.start.distanceTo( this.end );
44382 
44383  },
44384 
44385  at: function ( t, target ) {
44386 
44387  if ( target === undefined ) {
44388 
44389  console.warn( 'THREE.Line3: .at() target is now required' );
44390  target = new Vector3();
44391 
44392  }
44393 
44394  return this.delta( target ).multiplyScalar( t ).add( this.start );
44395 
44396  },
44397 
44398  closestPointToPointParameter: function () {
44399 
44400  var startP = new Vector3();
44401  var startEnd = new Vector3();
44402 
44403  return function closestPointToPointParameter( point, clampToLine ) {
44404 
44405  startP.subVectors( point, this.start );
44406  startEnd.subVectors( this.end, this.start );
44407 
44408  var startEnd2 = startEnd.dot( startEnd );
44409  var startEnd_startP = startEnd.dot( startP );
44410 
44411  var t = startEnd_startP / startEnd2;
44412 
44413  if ( clampToLine ) {
44414 
44415  t = _Math.clamp( t, 0, 1 );
44416 
44417  }
44418 
44419  return t;
44420 
44421  };
44422 
44423  }(),
44424 
44425  closestPointToPoint: function ( point, clampToLine, target ) {
44426 
44427  var t = this.closestPointToPointParameter( point, clampToLine );
44428 
44429  if ( target === undefined ) {
44430 
44431  console.warn( 'THREE.Line3: .closestPointToPoint() target is now required' );
44432  target = new Vector3();
44433 
44434  }
44435 
44436  return this.delta( target ).multiplyScalar( t ).add( this.start );
44437 
44438  },
44439 
44440  applyMatrix4: function ( matrix ) {
44441 
44442  this.start.applyMatrix4( matrix );
44443  this.end.applyMatrix4( matrix );
44444 
44445  return this;
44446 
44447  },
44448 
44449  equals: function ( line ) {
44450 
44451  return line.start.equals( this.start ) && line.end.equals( this.end );
44452 
44453  }
44454 
44455  } );
44456 
44461  function ImmediateRenderObject( material ) {
44462 
44463  Object3D.call( this );
44464 
44465  this.material = material;
44466  this.render = function ( /* renderCallback */ ) {};
44467 
44468  }
44469 
44470  ImmediateRenderObject.prototype = Object.create( Object3D.prototype );
44471  ImmediateRenderObject.prototype.constructor = ImmediateRenderObject;
44472 
44473  ImmediateRenderObject.prototype.isImmediateRenderObject = true;
44474 
44480  function VertexNormalsHelper( object, size, hex, linewidth ) {
44481 
44482  this.object = object;
44483 
44484  this.size = ( size !== undefined ) ? size : 1;
44485 
44486  var color = ( hex !== undefined ) ? hex : 0xff0000;
44487 
44488  var width = ( linewidth !== undefined ) ? linewidth : 1;
44489 
44490  //
44491 
44492  var nNormals = 0;
44493 
44494  var objGeometry = this.object.geometry;
44495 
44496  if ( objGeometry && objGeometry.isGeometry ) {
44497 
44498  nNormals = objGeometry.faces.length * 3;
44499 
44500  } else if ( objGeometry && objGeometry.isBufferGeometry ) {
44501 
44502  nNormals = objGeometry.attributes.normal.count;
44503 
44504  }
44505 
44506  //
44507 
44508  var geometry = new BufferGeometry();
44509 
44510  var positions = new Float32BufferAttribute( nNormals * 2 * 3, 3 );
44511 
44512  geometry.addAttribute( 'position', positions );
44513 
44514  LineSegments.call( this, geometry, new LineBasicMaterial( { color: color, linewidth: width } ) );
44515 
44516  //
44517 
44518  this.matrixAutoUpdate = false;
44519 
44520  this.update();
44521 
44522  }
44523 
44524  VertexNormalsHelper.prototype = Object.create( LineSegments.prototype );
44525  VertexNormalsHelper.prototype.constructor = VertexNormalsHelper;
44526 
44527  VertexNormalsHelper.prototype.update = ( function () {
44528 
44529  var v1 = new Vector3();
44530  var v2 = new Vector3();
44531  var normalMatrix = new Matrix3();
44532 
44533  return function update() {
44534 
44535  var keys = [ 'a', 'b', 'c' ];
44536 
44537  this.object.updateMatrixWorld( true );
44538 
44539  normalMatrix.getNormalMatrix( this.object.matrixWorld );
44540 
44541  var matrixWorld = this.object.matrixWorld;
44542 
44543  var position = this.geometry.attributes.position;
44544 
44545  //
44546 
44547  var objGeometry = this.object.geometry;
44548 
44549  if ( objGeometry && objGeometry.isGeometry ) {
44550 
44551  var vertices = objGeometry.vertices;
44552 
44553  var faces = objGeometry.faces;
44554 
44555  var idx = 0;
44556 
44557  for ( var i = 0, l = faces.length; i < l; i ++ ) {
44558 
44559  var face = faces[ i ];
44560 
44561  for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {
44562 
44563  var vertex = vertices[ face[ keys[ j ] ] ];
44564 
44565  var normal = face.vertexNormals[ j ];
44566 
44567  v1.copy( vertex ).applyMatrix4( matrixWorld );
44568 
44569  v2.copy( normal ).applyMatrix3( normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 );
44570 
44571  position.setXYZ( idx, v1.x, v1.y, v1.z );
44572 
44573  idx = idx + 1;
44574 
44575  position.setXYZ( idx, v2.x, v2.y, v2.z );
44576 
44577  idx = idx + 1;
44578 
44579  }
44580 
44581  }
44582 
44583  } else if ( objGeometry && objGeometry.isBufferGeometry ) {
44584 
44585  var objPos = objGeometry.attributes.position;
44586 
44587  var objNorm = objGeometry.attributes.normal;
44588 
44589  var idx = 0;
44590 
44591  // for simplicity, ignore index and drawcalls, and render every normal
44592 
44593  for ( var j = 0, jl = objPos.count; j < jl; j ++ ) {
44594 
44595  v1.set( objPos.getX( j ), objPos.getY( j ), objPos.getZ( j ) ).applyMatrix4( matrixWorld );
44596 
44597  v2.set( objNorm.getX( j ), objNorm.getY( j ), objNorm.getZ( j ) );
44598 
44599  v2.applyMatrix3( normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 );
44600 
44601  position.setXYZ( idx, v1.x, v1.y, v1.z );
44602 
44603  idx = idx + 1;
44604 
44605  position.setXYZ( idx, v2.x, v2.y, v2.z );
44606 
44607  idx = idx + 1;
44608 
44609  }
44610 
44611  }
44612 
44613  position.needsUpdate = true;
44614 
44615  };
44616 
44617  }() );
44618 
44625  function SpotLightHelper( light, color ) {
44626 
44627  Object3D.call( this );
44628 
44629  this.light = light;
44630  this.light.updateMatrixWorld();
44631 
44632  this.matrix = light.matrixWorld;
44633  this.matrixAutoUpdate = false;
44634 
44635  this.color = color;
44636 
44637  var geometry = new BufferGeometry();
44638 
44639  var positions = [
44640  0, 0, 0, 0, 0, 1,
44641  0, 0, 0, 1, 0, 1,
44642  0, 0, 0, - 1, 0, 1,
44643  0, 0, 0, 0, 1, 1,
44644  0, 0, 0, 0, - 1, 1
44645  ];
44646 
44647  for ( var i = 0, j = 1, l = 32; i < l; i ++, j ++ ) {
44648 
44649  var p1 = ( i / l ) * Math.PI * 2;
44650  var p2 = ( j / l ) * Math.PI * 2;
44651 
44652  positions.push(
44653  Math.cos( p1 ), Math.sin( p1 ), 1,
44654  Math.cos( p2 ), Math.sin( p2 ), 1
44655  );
44656 
44657  }
44658 
44659  geometry.addAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
44660 
44661  var material = new LineBasicMaterial( { fog: false } );
44662 
44663  this.cone = new LineSegments( geometry, material );
44664  this.add( this.cone );
44665 
44666  this.update();
44667 
44668  }
44669 
44670  SpotLightHelper.prototype = Object.create( Object3D.prototype );
44671  SpotLightHelper.prototype.constructor = SpotLightHelper;
44672 
44673  SpotLightHelper.prototype.dispose = function () {
44674 
44675  this.cone.geometry.dispose();
44676  this.cone.material.dispose();
44677 
44678  };
44679 
44680  SpotLightHelper.prototype.update = function () {
44681 
44682  var vector = new Vector3();
44683 
44684  return function update() {
44685 
44686  this.light.updateMatrixWorld();
44687 
44688  var coneLength = this.light.distance ? this.light.distance : 1000;
44689  var coneWidth = coneLength * Math.tan( this.light.angle );
44690 
44691  this.cone.scale.set( coneWidth, coneWidth, coneLength );
44692 
44693  vector.setFromMatrixPosition( this.light.target.matrixWorld );
44694 
44695  this.cone.lookAt( vector );
44696 
44697  if ( this.color !== undefined ) {
44698 
44699  this.cone.material.color.set( this.color );
44700 
44701  } else {
44702 
44703  this.cone.material.color.copy( this.light.color );
44704 
44705  }
44706 
44707  };
44708 
44709  }();
44710 
44719  function getBoneList( object ) {
44720 
44721  var boneList = [];
44722 
44723  if ( object && object.isBone ) {
44724 
44725  boneList.push( object );
44726 
44727  }
44728 
44729  for ( var i = 0; i < object.children.length; i ++ ) {
44730 
44731  boneList.push.apply( boneList, getBoneList( object.children[ i ] ) );
44732 
44733  }
44734 
44735  return boneList;
44736 
44737  }
44738 
44739  function SkeletonHelper( object ) {
44740 
44741  var bones = getBoneList( object );
44742 
44743  var geometry = new BufferGeometry();
44744 
44745  var vertices = [];
44746  var colors = [];
44747 
44748  var color1 = new Color( 0, 0, 1 );
44749  var color2 = new Color( 0, 1, 0 );
44750 
44751  for ( var i = 0; i < bones.length; i ++ ) {
44752 
44753  var bone = bones[ i ];
44754 
44755  if ( bone.parent && bone.parent.isBone ) {
44756 
44757  vertices.push( 0, 0, 0 );
44758  vertices.push( 0, 0, 0 );
44759  colors.push( color1.r, color1.g, color1.b );
44760  colors.push( color2.r, color2.g, color2.b );
44761 
44762  }
44763 
44764  }
44765 
44766  geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
44767  geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
44768 
44769  var material = new LineBasicMaterial( { vertexColors: VertexColors, depthTest: false, depthWrite: false, transparent: true } );
44770 
44771  LineSegments.call( this, geometry, material );
44772 
44773  this.root = object;
44774  this.bones = bones;
44775 
44776  this.matrix = object.matrixWorld;
44777  this.matrixAutoUpdate = false;
44778 
44779  }
44780 
44781  SkeletonHelper.prototype = Object.create( LineSegments.prototype );
44782  SkeletonHelper.prototype.constructor = SkeletonHelper;
44783 
44784  SkeletonHelper.prototype.updateMatrixWorld = function () {
44785 
44786  var vector = new Vector3();
44787 
44788  var boneMatrix = new Matrix4();
44789  var matrixWorldInv = new Matrix4();
44790 
44791  return function updateMatrixWorld( force ) {
44792 
44793  var bones = this.bones;
44794 
44795  var geometry = this.geometry;
44796  var position = geometry.getAttribute( 'position' );
44797 
44798  matrixWorldInv.getInverse( this.root.matrixWorld );
44799 
44800  for ( var i = 0, j = 0; i < bones.length; i ++ ) {
44801 
44802  var bone = bones[ i ];
44803 
44804  if ( bone.parent && bone.parent.isBone ) {
44805 
44806  boneMatrix.multiplyMatrices( matrixWorldInv, bone.matrixWorld );
44807  vector.setFromMatrixPosition( boneMatrix );
44808  position.setXYZ( j, vector.x, vector.y, vector.z );
44809 
44810  boneMatrix.multiplyMatrices( matrixWorldInv, bone.parent.matrixWorld );
44811  vector.setFromMatrixPosition( boneMatrix );
44812  position.setXYZ( j + 1, vector.x, vector.y, vector.z );
44813 
44814  j += 2;
44815 
44816  }
44817 
44818  }
44819 
44820  geometry.getAttribute( 'position' ).needsUpdate = true;
44821 
44822  Object3D.prototype.updateMatrixWorld.call( this, force );
44823 
44824  };
44825 
44826  }();
44827 
44833  function PointLightHelper( light, sphereSize, color ) {
44834 
44835  this.light = light;
44836  this.light.updateMatrixWorld();
44837 
44838  this.color = color;
44839 
44840  var geometry = new SphereBufferGeometry( sphereSize, 4, 2 );
44841  var material = new MeshBasicMaterial( { wireframe: true, fog: false } );
44842 
44843  Mesh.call( this, geometry, material );
44844 
44845  this.matrix = this.light.matrixWorld;
44846  this.matrixAutoUpdate = false;
44847 
44848  this.update();
44849 
44850 
44851  /*
44852  var distanceGeometry = new THREE.IcosahedronBufferGeometry( 1, 2 );
44853  var distanceMaterial = new THREE.MeshBasicMaterial( { color: hexColor, fog: false, wireframe: true, opacity: 0.1, transparent: true } );
44854 
44855  this.lightSphere = new THREE.Mesh( bulbGeometry, bulbMaterial );
44856  this.lightDistance = new THREE.Mesh( distanceGeometry, distanceMaterial );
44857 
44858  var d = light.distance;
44859 
44860  if ( d === 0.0 ) {
44861 
44862  this.lightDistance.visible = false;
44863 
44864  } else {
44865 
44866  this.lightDistance.scale.set( d, d, d );
44867 
44868  }
44869 
44870  this.add( this.lightDistance );
44871  */
44872 
44873  }
44874 
44875  PointLightHelper.prototype = Object.create( Mesh.prototype );
44876  PointLightHelper.prototype.constructor = PointLightHelper;
44877 
44878  PointLightHelper.prototype.dispose = function () {
44879 
44880  this.geometry.dispose();
44881  this.material.dispose();
44882 
44883  };
44884 
44885  PointLightHelper.prototype.update = function () {
44886 
44887  if ( this.color !== undefined ) {
44888 
44889  this.material.color.set( this.color );
44890 
44891  } else {
44892 
44893  this.material.color.copy( this.light.color );
44894 
44895  }
44896 
44897  /*
44898  var d = this.light.distance;
44899 
44900  if ( d === 0.0 ) {
44901 
44902  this.lightDistance.visible = false;
44903 
44904  } else {
44905 
44906  this.lightDistance.visible = true;
44907  this.lightDistance.scale.set( d, d, d );
44908 
44909  }
44910  */
44911 
44912  };
44913 
44922  function RectAreaLightHelper( light, color ) {
44923 
44924  this.type = 'RectAreaLightHelper';
44925 
44926  this.light = light;
44927 
44928  this.color = color; // optional hardwired color for the helper
44929 
44930  var positions = [ 1, 1, 0, - 1, 1, 0, - 1, - 1, 0, 1, - 1, 0, 1, 1, 0 ];
44931 
44932  var geometry = new BufferGeometry();
44933  geometry.addAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
44934  geometry.computeBoundingSphere();
44935 
44936  var material = new LineBasicMaterial( { fog: false } );
44937 
44938  Line.call( this, geometry, material );
44939 
44940  //
44941 
44942  var positions2 = [ 1, 1, 0, - 1, 1, 0, - 1, - 1, 0, 1, 1, 0, - 1, - 1, 0, 1, - 1, 0 ];
44943 
44944  var geometry2 = new BufferGeometry();
44945  geometry2.addAttribute( 'position', new Float32BufferAttribute( positions2, 3 ) );
44946  geometry2.computeBoundingSphere();
44947 
44948  this.add( new Mesh( geometry2, new MeshBasicMaterial( { side: BackSide, fog: false } ) ) );
44949 
44950  this.update();
44951 
44952  }
44953 
44954  RectAreaLightHelper.prototype = Object.create( Line.prototype );
44955  RectAreaLightHelper.prototype.constructor = RectAreaLightHelper;
44956 
44957  RectAreaLightHelper.prototype.update = function () {
44958 
44959  this.scale.set( 0.5 * this.light.width, 0.5 * this.light.height, 1 );
44960 
44961  if ( this.color !== undefined ) {
44962 
44963  this.material.color.set( this.color );
44964  this.children[ 0 ].material.color.set( this.color );
44965 
44966  } else {
44967 
44968  this.material.color.copy( this.light.color ).multiplyScalar( this.light.intensity );
44969 
44970  // prevent hue shift
44971  var c = this.material.color;
44972  var max = Math.max( c.r, c.g, c.b );
44973  if ( max > 1 ) c.multiplyScalar( 1 / max );
44974 
44975  this.children[ 0 ].material.color.copy( this.material.color );
44976 
44977  }
44978 
44979  };
44980 
44981  RectAreaLightHelper.prototype.dispose = function () {
44982 
44983  this.geometry.dispose();
44984  this.material.dispose();
44985  this.children[ 0 ].geometry.dispose();
44986  this.children[ 0 ].material.dispose();
44987 
44988  };
44989 
44996  function HemisphereLightHelper( light, size, color ) {
44997 
44998  Object3D.call( this );
44999 
45000  this.light = light;
45001  this.light.updateMatrixWorld();
45002 
45003  this.matrix = light.matrixWorld;
45004  this.matrixAutoUpdate = false;
45005 
45006  this.color = color;
45007 
45008  var geometry = new OctahedronBufferGeometry( size );
45009  geometry.rotateY( Math.PI * 0.5 );
45010 
45011  this.material = new MeshBasicMaterial( { wireframe: true, fog: false } );
45012  if ( this.color === undefined ) this.material.vertexColors = VertexColors;
45013 
45014  var position = geometry.getAttribute( 'position' );
45015  var colors = new Float32Array( position.count * 3 );
45016 
45017  geometry.addAttribute( 'color', new BufferAttribute( colors, 3 ) );
45018 
45019  this.add( new Mesh( geometry, this.material ) );
45020 
45021  this.update();
45022 
45023  }
45024 
45025  HemisphereLightHelper.prototype = Object.create( Object3D.prototype );
45026  HemisphereLightHelper.prototype.constructor = HemisphereLightHelper;
45027 
45028  HemisphereLightHelper.prototype.dispose = function () {
45029 
45030  this.children[ 0 ].geometry.dispose();
45031  this.children[ 0 ].material.dispose();
45032 
45033  };
45034 
45035  HemisphereLightHelper.prototype.update = function () {
45036 
45037  var vector = new Vector3();
45038 
45039  var color1 = new Color();
45040  var color2 = new Color();
45041 
45042  return function update() {
45043 
45044  var mesh = this.children[ 0 ];
45045 
45046  if ( this.color !== undefined ) {
45047 
45048  this.material.color.set( this.color );
45049 
45050  } else {
45051 
45052  var colors = mesh.geometry.getAttribute( 'color' );
45053 
45054  color1.copy( this.light.color );
45055  color2.copy( this.light.groundColor );
45056 
45057  for ( var i = 0, l = colors.count; i < l; i ++ ) {
45058 
45059  var color = ( i < ( l / 2 ) ) ? color1 : color2;
45060 
45061  colors.setXYZ( i, color.r, color.g, color.b );
45062 
45063  }
45064 
45065  colors.needsUpdate = true;
45066 
45067  }
45068 
45069  mesh.lookAt( vector.setFromMatrixPosition( this.light.matrixWorld ).negate() );
45070 
45071  };
45072 
45073  }();
45074 
45079  function GridHelper( size, divisions, color1, color2 ) {
45080 
45081  size = size || 10;
45082  divisions = divisions || 10;
45083  color1 = new Color( color1 !== undefined ? color1 : 0x444444 );
45084  color2 = new Color( color2 !== undefined ? color2 : 0x888888 );
45085 
45086  var center = divisions / 2;
45087  var step = size / divisions;
45088  var halfSize = size / 2;
45089 
45090  var vertices = [], colors = [];
45091 
45092  for ( var i = 0, j = 0, k = - halfSize; i <= divisions; i ++, k += step ) {
45093 
45094  vertices.push( - halfSize, 0, k, halfSize, 0, k );
45095  vertices.push( k, 0, - halfSize, k, 0, halfSize );
45096 
45097  var color = i === center ? color1 : color2;
45098 
45099  color.toArray( colors, j ); j += 3;
45100  color.toArray( colors, j ); j += 3;
45101  color.toArray( colors, j ); j += 3;
45102  color.toArray( colors, j ); j += 3;
45103 
45104  }
45105 
45106  var geometry = new BufferGeometry();
45107  geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
45108  geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
45109 
45110  var material = new LineBasicMaterial( { vertexColors: VertexColors } );
45111 
45112  LineSegments.call( this, geometry, material );
45113 
45114  }
45115 
45116  GridHelper.prototype = Object.create( LineSegments.prototype );
45117  GridHelper.prototype.constructor = GridHelper;
45118 
45125  function PolarGridHelper( radius, radials, circles, divisions, color1, color2 ) {
45126 
45127  radius = radius || 10;
45128  radials = radials || 16;
45129  circles = circles || 8;
45130  divisions = divisions || 64;
45131  color1 = new Color( color1 !== undefined ? color1 : 0x444444 );
45132  color2 = new Color( color2 !== undefined ? color2 : 0x888888 );
45133 
45134  var vertices = [];
45135  var colors = [];
45136 
45137  var x, z;
45138  var v, i, j, r, color;
45139 
45140  // create the radials
45141 
45142  for ( i = 0; i <= radials; i ++ ) {
45143 
45144  v = ( i / radials ) * ( Math.PI * 2 );
45145 
45146  x = Math.sin( v ) * radius;
45147  z = Math.cos( v ) * radius;
45148 
45149  vertices.push( 0, 0, 0 );
45150  vertices.push( x, 0, z );
45151 
45152  color = ( i & 1 ) ? color1 : color2;
45153 
45154  colors.push( color.r, color.g, color.b );
45155  colors.push( color.r, color.g, color.b );
45156 
45157  }
45158 
45159  // create the circles
45160 
45161  for ( i = 0; i <= circles; i ++ ) {
45162 
45163  color = ( i & 1 ) ? color1 : color2;
45164 
45165  r = radius - ( radius / circles * i );
45166 
45167  for ( j = 0; j < divisions; j ++ ) {
45168 
45169  // first vertex
45170 
45171  v = ( j / divisions ) * ( Math.PI * 2 );
45172 
45173  x = Math.sin( v ) * r;
45174  z = Math.cos( v ) * r;
45175 
45176  vertices.push( x, 0, z );
45177  colors.push( color.r, color.g, color.b );
45178 
45179  // second vertex
45180 
45181  v = ( ( j + 1 ) / divisions ) * ( Math.PI * 2 );
45182 
45183  x = Math.sin( v ) * r;
45184  z = Math.cos( v ) * r;
45185 
45186  vertices.push( x, 0, z );
45187  colors.push( color.r, color.g, color.b );
45188 
45189  }
45190 
45191  }
45192 
45193  var geometry = new BufferGeometry();
45194  geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
45195  geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
45196 
45197  var material = new LineBasicMaterial( { vertexColors: VertexColors } );
45198 
45199  LineSegments.call( this, geometry, material );
45200 
45201  }
45202 
45203  PolarGridHelper.prototype = Object.create( LineSegments.prototype );
45204  PolarGridHelper.prototype.constructor = PolarGridHelper;
45205 
45210  function PositionalAudioHelper( audio, range, divisionsInnerAngle, divisionsOuterAngle ) {
45211 
45212  this.audio = audio;
45213  this.range = range || 1;
45214  this.divisionsInnerAngle = divisionsInnerAngle || 16;
45215  this.divisionsOuterAngle = divisionsOuterAngle || 2;
45216 
45217  var geometry = new BufferGeometry();
45218  var divisions = this.divisionsInnerAngle + this.divisionsOuterAngle * 2;
45219  var positions = new Float32Array( ( divisions * 3 + 3 ) * 3 );
45220  geometry.addAttribute( 'position', new BufferAttribute( positions, 3 ) );
45221 
45222  var materialInnerAngle = new LineBasicMaterial( { color: 0x00ff00 } );
45223  var materialOuterAngle = new LineBasicMaterial( { color: 0xffff00 } );
45224 
45225  Line.call( this, geometry, [ materialOuterAngle, materialInnerAngle ] );
45226 
45227  this.update();
45228 
45229  }
45230 
45231  PositionalAudioHelper.prototype = Object.create( Line.prototype );
45232  PositionalAudioHelper.prototype.constructor = PositionalAudioHelper;
45233 
45234  PositionalAudioHelper.prototype.update = function () {
45235 
45236  var audio = this.audio;
45237  var range = this.range;
45238  var divisionsInnerAngle = this.divisionsInnerAngle;
45239  var divisionsOuterAngle = this.divisionsOuterAngle;
45240 
45241  var coneInnerAngle = _Math.degToRad( audio.panner.coneInnerAngle );
45242  var coneOuterAngle = _Math.degToRad( audio.panner.coneOuterAngle );
45243 
45244  var halfConeInnerAngle = coneInnerAngle / 2;
45245  var halfConeOuterAngle = coneOuterAngle / 2;
45246 
45247  var start = 0;
45248  var count = 0;
45249  var i, stride;
45250 
45251  var geometry = this.geometry;
45252  var positionAttribute = geometry.attributes.position;
45253 
45254  geometry.clearGroups();
45255 
45256  //
45257 
45258  function generateSegment( from, to, divisions, materialIndex ) {
45259 
45260  var step = ( to - from ) / divisions;
45261 
45262  positionAttribute.setXYZ( start, 0, 0, 0 );
45263  count ++;
45264 
45265  for ( i = from; i < to; i += step ) {
45266 
45267  stride = start + count;
45268 
45269  positionAttribute.setXYZ( stride, Math.sin( i ) * range, 0, Math.cos( i ) * range );
45270  positionAttribute.setXYZ( stride + 1, Math.sin( Math.min( i + step, to ) ) * range, 0, Math.cos( Math.min( i + step, to ) ) * range );
45271  positionAttribute.setXYZ( stride + 2, 0, 0, 0 );
45272 
45273  count += 3;
45274 
45275  }
45276 
45277  geometry.addGroup( start, count, materialIndex );
45278 
45279  start += count;
45280  count = 0;
45281 
45282  }
45283 
45284  //
45285 
45286  generateSegment( - halfConeOuterAngle, - halfConeInnerAngle, divisionsOuterAngle, 0 );
45287  generateSegment( - halfConeInnerAngle, halfConeInnerAngle, divisionsInnerAngle, 1 );
45288  generateSegment( halfConeInnerAngle, halfConeOuterAngle, divisionsOuterAngle, 0 );
45289 
45290  //
45291 
45292  positionAttribute.needsUpdate = true;
45293 
45294  if ( coneInnerAngle === coneOuterAngle ) this.material[ 0 ].visible = false;
45295 
45296  };
45297 
45298  PositionalAudioHelper.prototype.dispose = function () {
45299 
45300  this.geometry.dispose();
45301  this.material[ 0 ].dispose();
45302  this.material[ 1 ].dispose();
45303 
45304  };
45305 
45311  function FaceNormalsHelper( object, size, hex, linewidth ) {
45312 
45313  // FaceNormalsHelper only supports THREE.Geometry
45314 
45315  this.object = object;
45316 
45317  this.size = ( size !== undefined ) ? size : 1;
45318 
45319  var color = ( hex !== undefined ) ? hex : 0xffff00;
45320 
45321  var width = ( linewidth !== undefined ) ? linewidth : 1;
45322 
45323  //
45324 
45325  var nNormals = 0;
45326 
45327  var objGeometry = this.object.geometry;
45328 
45329  if ( objGeometry && objGeometry.isGeometry ) {
45330 
45331  nNormals = objGeometry.faces.length;
45332 
45333  } else {
45334 
45335  console.warn( 'THREE.FaceNormalsHelper: only THREE.Geometry is supported. Use THREE.VertexNormalsHelper, instead.' );
45336 
45337  }
45338 
45339  //
45340 
45341  var geometry = new BufferGeometry();
45342 
45343  var positions = new Float32BufferAttribute( nNormals * 2 * 3, 3 );
45344 
45345  geometry.addAttribute( 'position', positions );
45346 
45347  LineSegments.call( this, geometry, new LineBasicMaterial( { color: color, linewidth: width } ) );
45348 
45349  //
45350 
45351  this.matrixAutoUpdate = false;
45352  this.update();
45353 
45354  }
45355 
45356  FaceNormalsHelper.prototype = Object.create( LineSegments.prototype );
45357  FaceNormalsHelper.prototype.constructor = FaceNormalsHelper;
45358 
45359  FaceNormalsHelper.prototype.update = ( function () {
45360 
45361  var v1 = new Vector3();
45362  var v2 = new Vector3();
45363  var normalMatrix = new Matrix3();
45364 
45365  return function update() {
45366 
45367  this.object.updateMatrixWorld( true );
45368 
45369  normalMatrix.getNormalMatrix( this.object.matrixWorld );
45370 
45371  var matrixWorld = this.object.matrixWorld;
45372 
45373  var position = this.geometry.attributes.position;
45374 
45375  //
45376 
45377  var objGeometry = this.object.geometry;
45378 
45379  var vertices = objGeometry.vertices;
45380 
45381  var faces = objGeometry.faces;
45382 
45383  var idx = 0;
45384 
45385  for ( var i = 0, l = faces.length; i < l; i ++ ) {
45386 
45387  var face = faces[ i ];
45388 
45389  var normal = face.normal;
45390 
45391  v1.copy( vertices[ face.a ] )
45392  .add( vertices[ face.b ] )
45393  .add( vertices[ face.c ] )
45394  .divideScalar( 3 )
45395  .applyMatrix4( matrixWorld );
45396 
45397  v2.copy( normal ).applyMatrix3( normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 );
45398 
45399  position.setXYZ( idx, v1.x, v1.y, v1.z );
45400 
45401  idx = idx + 1;
45402 
45403  position.setXYZ( idx, v2.x, v2.y, v2.z );
45404 
45405  idx = idx + 1;
45406 
45407  }
45408 
45409  position.needsUpdate = true;
45410 
45411  };
45412 
45413  }() );
45414 
45421  function DirectionalLightHelper( light, size, color ) {
45422 
45423  Object3D.call( this );
45424 
45425  this.light = light;
45426  this.light.updateMatrixWorld();
45427 
45428  this.matrix = light.matrixWorld;
45429  this.matrixAutoUpdate = false;
45430 
45431  this.color = color;
45432 
45433  if ( size === undefined ) size = 1;
45434 
45435  var geometry = new BufferGeometry();
45436  geometry.addAttribute( 'position', new Float32BufferAttribute( [
45437  - size, size, 0,
45438  size, size, 0,
45439  size, - size, 0,
45440  - size, - size, 0,
45441  - size, size, 0
45442  ], 3 ) );
45443 
45444  var material = new LineBasicMaterial( { fog: false } );
45445 
45446  this.lightPlane = new Line( geometry, material );
45447  this.add( this.lightPlane );
45448 
45449  geometry = new BufferGeometry();
45450  geometry.addAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 0, 1 ], 3 ) );
45451 
45452  this.targetLine = new Line( geometry, material );
45453  this.add( this.targetLine );
45454 
45455  this.update();
45456 
45457  }
45458 
45459  DirectionalLightHelper.prototype = Object.create( Object3D.prototype );
45460  DirectionalLightHelper.prototype.constructor = DirectionalLightHelper;
45461 
45462  DirectionalLightHelper.prototype.dispose = function () {
45463 
45464  this.lightPlane.geometry.dispose();
45465  this.lightPlane.material.dispose();
45466  this.targetLine.geometry.dispose();
45467  this.targetLine.material.dispose();
45468 
45469  };
45470 
45471  DirectionalLightHelper.prototype.update = function () {
45472 
45473  var v1 = new Vector3();
45474  var v2 = new Vector3();
45475  var v3 = new Vector3();
45476 
45477  return function update() {
45478 
45479  v1.setFromMatrixPosition( this.light.matrixWorld );
45480  v2.setFromMatrixPosition( this.light.target.matrixWorld );
45481  v3.subVectors( v2, v1 );
45482 
45483  this.lightPlane.lookAt( v2 );
45484 
45485  if ( this.color !== undefined ) {
45486 
45487  this.lightPlane.material.color.set( this.color );
45488  this.targetLine.material.color.set( this.color );
45489 
45490  } else {
45491 
45492  this.lightPlane.material.color.copy( this.light.color );
45493  this.targetLine.material.color.copy( this.light.color );
45494 
45495  }
45496 
45497  this.targetLine.lookAt( v2 );
45498  this.targetLine.scale.z = v3.length();
45499 
45500  };
45501 
45502  }();
45503 
45514  function CameraHelper( camera ) {
45515 
45516  var geometry = new BufferGeometry();
45517  var material = new LineBasicMaterial( { color: 0xffffff, vertexColors: FaceColors } );
45518 
45519  var vertices = [];
45520  var colors = [];
45521 
45522  var pointMap = {};
45523 
45524  // colors
45525 
45526  var colorFrustum = new Color( 0xffaa00 );
45527  var colorCone = new Color( 0xff0000 );
45528  var colorUp = new Color( 0x00aaff );
45529  var colorTarget = new Color( 0xffffff );
45530  var colorCross = new Color( 0x333333 );
45531 
45532  // near
45533 
45534  addLine( 'n1', 'n2', colorFrustum );
45535  addLine( 'n2', 'n4', colorFrustum );
45536  addLine( 'n4', 'n3', colorFrustum );
45537  addLine( 'n3', 'n1', colorFrustum );
45538 
45539  // far
45540 
45541  addLine( 'f1', 'f2', colorFrustum );
45542  addLine( 'f2', 'f4', colorFrustum );
45543  addLine( 'f4', 'f3', colorFrustum );
45544  addLine( 'f3', 'f1', colorFrustum );
45545 
45546  // sides
45547 
45548  addLine( 'n1', 'f1', colorFrustum );
45549  addLine( 'n2', 'f2', colorFrustum );
45550  addLine( 'n3', 'f3', colorFrustum );
45551  addLine( 'n4', 'f4', colorFrustum );
45552 
45553  // cone
45554 
45555  addLine( 'p', 'n1', colorCone );
45556  addLine( 'p', 'n2', colorCone );
45557  addLine( 'p', 'n3', colorCone );
45558  addLine( 'p', 'n4', colorCone );
45559 
45560  // up
45561 
45562  addLine( 'u1', 'u2', colorUp );
45563  addLine( 'u2', 'u3', colorUp );
45564  addLine( 'u3', 'u1', colorUp );
45565 
45566  // target
45567 
45568  addLine( 'c', 't', colorTarget );
45569  addLine( 'p', 'c', colorCross );
45570 
45571  // cross
45572 
45573  addLine( 'cn1', 'cn2', colorCross );
45574  addLine( 'cn3', 'cn4', colorCross );
45575 
45576  addLine( 'cf1', 'cf2', colorCross );
45577  addLine( 'cf3', 'cf4', colorCross );
45578 
45579  function addLine( a, b, color ) {
45580 
45581  addPoint( a, color );
45582  addPoint( b, color );
45583 
45584  }
45585 
45586  function addPoint( id, color ) {
45587 
45588  vertices.push( 0, 0, 0 );
45589  colors.push( color.r, color.g, color.b );
45590 
45591  if ( pointMap[ id ] === undefined ) {
45592 
45593  pointMap[ id ] = [];
45594 
45595  }
45596 
45597  pointMap[ id ].push( ( vertices.length / 3 ) - 1 );
45598 
45599  }
45600 
45601  geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
45602  geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
45603 
45604  LineSegments.call( this, geometry, material );
45605 
45606  this.camera = camera;
45607  if ( this.camera.updateProjectionMatrix ) this.camera.updateProjectionMatrix();
45608 
45609  this.matrix = camera.matrixWorld;
45610  this.matrixAutoUpdate = false;
45611 
45612  this.pointMap = pointMap;
45613 
45614  this.update();
45615 
45616  }
45617 
45618  CameraHelper.prototype = Object.create( LineSegments.prototype );
45619  CameraHelper.prototype.constructor = CameraHelper;
45620 
45621  CameraHelper.prototype.update = function () {
45622 
45623  var geometry, pointMap;
45624 
45625  var vector = new Vector3();
45626  var camera = new Camera();
45627 
45628  function setPoint( point, x, y, z ) {
45629 
45630  vector.set( x, y, z ).unproject( camera );
45631 
45632  var points = pointMap[ point ];
45633 
45634  if ( points !== undefined ) {
45635 
45636  var position = geometry.getAttribute( 'position' );
45637 
45638  for ( var i = 0, l = points.length; i < l; i ++ ) {
45639 
45640  position.setXYZ( points[ i ], vector.x, vector.y, vector.z );
45641 
45642  }
45643 
45644  }
45645 
45646  }
45647 
45648  return function update() {
45649 
45650  geometry = this.geometry;
45651  pointMap = this.pointMap;
45652 
45653  var w = 1, h = 1;
45654 
45655  // we need just camera projection matrix
45656  // world matrix must be identity
45657 
45658  camera.projectionMatrix.copy( this.camera.projectionMatrix );
45659 
45660  // center / target
45661 
45662  setPoint( 'c', 0, 0, - 1 );
45663  setPoint( 't', 0, 0, 1 );
45664 
45665  // near
45666 
45667  setPoint( 'n1', - w, - h, - 1 );
45668  setPoint( 'n2', w, - h, - 1 );
45669  setPoint( 'n3', - w, h, - 1 );
45670  setPoint( 'n4', w, h, - 1 );
45671 
45672  // far
45673 
45674  setPoint( 'f1', - w, - h, 1 );
45675  setPoint( 'f2', w, - h, 1 );
45676  setPoint( 'f3', - w, h, 1 );
45677  setPoint( 'f4', w, h, 1 );
45678 
45679  // up
45680 
45681  setPoint( 'u1', w * 0.7, h * 1.1, - 1 );
45682  setPoint( 'u2', - w * 0.7, h * 1.1, - 1 );
45683  setPoint( 'u3', 0, h * 2, - 1 );
45684 
45685  // cross
45686 
45687  setPoint( 'cf1', - w, 0, 1 );
45688  setPoint( 'cf2', w, 0, 1 );
45689  setPoint( 'cf3', 0, - h, 1 );
45690  setPoint( 'cf4', 0, h, 1 );
45691 
45692  setPoint( 'cn1', - w, 0, - 1 );
45693  setPoint( 'cn2', w, 0, - 1 );
45694  setPoint( 'cn3', 0, - h, - 1 );
45695  setPoint( 'cn4', 0, h, - 1 );
45696 
45697  geometry.getAttribute( 'position' ).needsUpdate = true;
45698 
45699  };
45700 
45701  }();
45702 
45708  function BoxHelper( object, color ) {
45709 
45710  this.object = object;
45711 
45712  if ( color === undefined ) color = 0xffff00;
45713 
45714  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 ] );
45715  var positions = new Float32Array( 8 * 3 );
45716 
45717  var geometry = new BufferGeometry();
45718  geometry.setIndex( new BufferAttribute( indices, 1 ) );
45719  geometry.addAttribute( 'position', new BufferAttribute( positions, 3 ) );
45720 
45721  LineSegments.call( this, geometry, new LineBasicMaterial( { color: color } ) );
45722 
45723  this.matrixAutoUpdate = false;
45724 
45725  this.update();
45726 
45727  }
45728 
45729  BoxHelper.prototype = Object.create( LineSegments.prototype );
45730  BoxHelper.prototype.constructor = BoxHelper;
45731 
45732  BoxHelper.prototype.update = ( function () {
45733 
45734  var box = new Box3();
45735 
45736  return function update( object ) {
45737 
45738  if ( object !== undefined ) {
45739 
45740  console.warn( 'THREE.BoxHelper: .update() has no longer arguments.' );
45741 
45742  }
45743 
45744  if ( this.object !== undefined ) {
45745 
45746  box.setFromObject( this.object );
45747 
45748  }
45749 
45750  if ( box.isEmpty() ) return;
45751 
45752  var min = box.min;
45753  var max = box.max;
45754 
45755  /*
45756  5____4
45757  1/___0/|
45758  | 6__|_7
45759  2/___3/
45760 
45761  0: max.x, max.y, max.z
45762  1: min.x, max.y, max.z
45763  2: min.x, min.y, max.z
45764  3: max.x, min.y, max.z
45765  4: max.x, max.y, min.z
45766  5: min.x, max.y, min.z
45767  6: min.x, min.y, min.z
45768  7: max.x, min.y, min.z
45769  */
45770 
45771  var position = this.geometry.attributes.position;
45772  var array = position.array;
45773 
45774  array[ 0 ] = max.x; array[ 1 ] = max.y; array[ 2 ] = max.z;
45775  array[ 3 ] = min.x; array[ 4 ] = max.y; array[ 5 ] = max.z;
45776  array[ 6 ] = min.x; array[ 7 ] = min.y; array[ 8 ] = max.z;
45777  array[ 9 ] = max.x; array[ 10 ] = min.y; array[ 11 ] = max.z;
45778  array[ 12 ] = max.x; array[ 13 ] = max.y; array[ 14 ] = min.z;
45779  array[ 15 ] = min.x; array[ 16 ] = max.y; array[ 17 ] = min.z;
45780  array[ 18 ] = min.x; array[ 19 ] = min.y; array[ 20 ] = min.z;
45781  array[ 21 ] = max.x; array[ 22 ] = min.y; array[ 23 ] = min.z;
45782 
45783  position.needsUpdate = true;
45784 
45785  this.geometry.computeBoundingSphere();
45786 
45787  };
45788 
45789  } )();
45790 
45791  BoxHelper.prototype.setFromObject = function ( object ) {
45792 
45793  this.object = object;
45794  this.update();
45795 
45796  return this;
45797 
45798  };
45799 
45800  BoxHelper.prototype.copy = function ( source ) {
45801 
45802  LineSegments.prototype.copy.call( this, source );
45803 
45804  this.object = source.object;
45805 
45806  return this;
45807 
45808  };
45809 
45810  BoxHelper.prototype.clone = function () {
45811 
45812  return new this.constructor().copy( this );
45813 
45814  };
45815 
45820  function Box3Helper( box, hex ) {
45821 
45822  this.type = 'Box3Helper';
45823 
45824  this.box = box;
45825 
45826  var color = ( hex !== undefined ) ? hex : 0xffff00;
45827 
45828  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 ] );
45829 
45830  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 ];
45831 
45832  var geometry = new BufferGeometry();
45833 
45834  geometry.setIndex( new BufferAttribute( indices, 1 ) );
45835 
45836  geometry.addAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
45837 
45838  LineSegments.call( this, geometry, new LineBasicMaterial( { color: color } ) );
45839 
45840  this.geometry.computeBoundingSphere();
45841 
45842  }
45843 
45844  Box3Helper.prototype = Object.create( LineSegments.prototype );
45845  Box3Helper.prototype.constructor = Box3Helper;
45846 
45847  Box3Helper.prototype.updateMatrixWorld = function ( force ) {
45848 
45849  var box = this.box;
45850 
45851  if ( box.isEmpty() ) return;
45852 
45853  box.getCenter( this.position );
45854 
45855  box.getSize( this.scale );
45856 
45857  this.scale.multiplyScalar( 0.5 );
45858 
45859  Object3D.prototype.updateMatrixWorld.call( this, force );
45860 
45861  };
45862 
45867  function PlaneHelper( plane, size, hex ) {
45868 
45869  this.type = 'PlaneHelper';
45870 
45871  this.plane = plane;
45872 
45873  this.size = ( size === undefined ) ? 1 : size;
45874 
45875  var color = ( hex !== undefined ) ? hex : 0xffff00;
45876 
45877  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 ];
45878 
45879  var geometry = new BufferGeometry();
45880  geometry.addAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
45881  geometry.computeBoundingSphere();
45882 
45883  Line.call( this, geometry, new LineBasicMaterial( { color: color } ) );
45884 
45885  //
45886 
45887  var positions2 = [ 1, 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, 1, 1, - 1, - 1, 1, 1, - 1, 1 ];
45888 
45889  var geometry2 = new BufferGeometry();
45890  geometry2.addAttribute( 'position', new Float32BufferAttribute( positions2, 3 ) );
45891  geometry2.computeBoundingSphere();
45892 
45893  this.add( new Mesh( geometry2, new MeshBasicMaterial( { color: color, opacity: 0.2, transparent: true, depthWrite: false } ) ) );
45894 
45895  }
45896 
45897  PlaneHelper.prototype = Object.create( Line.prototype );
45898  PlaneHelper.prototype.constructor = PlaneHelper;
45899 
45900  PlaneHelper.prototype.updateMatrixWorld = function ( force ) {
45901 
45902  var scale = - this.plane.constant;
45903 
45904  if ( Math.abs( scale ) < 1e-8 ) scale = 1e-8; // sign does not matter
45905 
45906  this.scale.set( 0.5 * this.size, 0.5 * this.size, scale );
45907 
45908  this.children[ 0 ].material.side = ( scale < 0 ) ? BackSide : FrontSide; // renderer flips side when determinant < 0; flipping not wanted here
45909 
45910  this.lookAt( this.plane.normal );
45911 
45912  Object3D.prototype.updateMatrixWorld.call( this, force );
45913 
45914  };
45915 
45932  var lineGeometry, coneGeometry;
45933 
45934  function ArrowHelper( dir, origin, length, color, headLength, headWidth ) {
45935 
45936  // dir is assumed to be normalized
45937 
45938  Object3D.call( this );
45939 
45940  if ( dir === undefined ) dir = new Vector3( 0, 0, 1 );
45941  if ( origin === undefined ) origin = new Vector3( 0, 0, 0 );
45942  if ( length === undefined ) length = 1;
45943  if ( color === undefined ) color = 0xffff00;
45944  if ( headLength === undefined ) headLength = 0.2 * length;
45945  if ( headWidth === undefined ) headWidth = 0.2 * headLength;
45946 
45947  if ( lineGeometry === undefined ) {
45948 
45949  lineGeometry = new BufferGeometry();
45950  lineGeometry.addAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 1, 0 ], 3 ) );
45951 
45952  coneGeometry = new CylinderBufferGeometry( 0, 0.5, 1, 5, 1 );
45953  coneGeometry.translate( 0, - 0.5, 0 );
45954 
45955  }
45956 
45957  this.position.copy( origin );
45958 
45959  this.line = new Line( lineGeometry, new LineBasicMaterial( { color: color } ) );
45960  this.line.matrixAutoUpdate = false;
45961  this.add( this.line );
45962 
45963  this.cone = new Mesh( coneGeometry, new MeshBasicMaterial( { color: color } ) );
45964  this.cone.matrixAutoUpdate = false;
45965  this.add( this.cone );
45966 
45967  this.setDirection( dir );
45968  this.setLength( length, headLength, headWidth );
45969 
45970  }
45971 
45972  ArrowHelper.prototype = Object.create( Object3D.prototype );
45973  ArrowHelper.prototype.constructor = ArrowHelper;
45974 
45975  ArrowHelper.prototype.setDirection = ( function () {
45976 
45977  var axis = new Vector3();
45978  var radians;
45979 
45980  return function setDirection( dir ) {
45981 
45982  // dir is assumed to be normalized
45983 
45984  if ( dir.y > 0.99999 ) {
45985 
45986  this.quaternion.set( 0, 0, 0, 1 );
45987 
45988  } else if ( dir.y < - 0.99999 ) {
45989 
45990  this.quaternion.set( 1, 0, 0, 0 );
45991 
45992  } else {
45993 
45994  axis.set( dir.z, 0, - dir.x ).normalize();
45995 
45996  radians = Math.acos( dir.y );
45997 
45998  this.quaternion.setFromAxisAngle( axis, radians );
45999 
46000  }
46001 
46002  };
46003 
46004  }() );
46005 
46006  ArrowHelper.prototype.setLength = function ( length, headLength, headWidth ) {
46007 
46008  if ( headLength === undefined ) headLength = 0.2 * length;
46009  if ( headWidth === undefined ) headWidth = 0.2 * headLength;
46010 
46011  this.line.scale.set( 1, Math.max( 0, length - headLength ), 1 );
46012  this.line.updateMatrix();
46013 
46014  this.cone.scale.set( headWidth, headLength, headWidth );
46015  this.cone.position.y = length;
46016  this.cone.updateMatrix();
46017 
46018  };
46019 
46020  ArrowHelper.prototype.setColor = function ( color ) {
46021 
46022  this.line.material.color.copy( color );
46023  this.cone.material.color.copy( color );
46024 
46025  };
46026 
46027  ArrowHelper.prototype.copy = function ( source ) {
46028 
46029  Object3D.prototype.copy.call( this, source, false );
46030 
46031  this.line.copy( source.line );
46032  this.cone.copy( source.cone );
46033 
46034  return this;
46035 
46036  };
46037 
46038  ArrowHelper.prototype.clone = function () {
46039 
46040  return new this.constructor().copy( this );
46041 
46042  };
46043 
46049  function AxesHelper( size ) {
46050 
46051  size = size || 1;
46052 
46053  var vertices = [
46054  0, 0, 0, size, 0, 0,
46055  0, 0, 0, 0, size, 0,
46056  0, 0, 0, 0, 0, size
46057  ];
46058 
46059  var colors = [
46060  1, 0, 0, 1, 0.6, 0,
46061  0, 1, 0, 0.6, 1, 0,
46062  0, 0, 1, 0, 0.6, 1
46063  ];
46064 
46065  var geometry = new BufferGeometry();
46066  geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
46067  geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
46068 
46069  var material = new LineBasicMaterial( { vertexColors: VertexColors } );
46070 
46071  LineSegments.call( this, geometry, material );
46072 
46073  }
46074 
46075  AxesHelper.prototype = Object.create( LineSegments.prototype );
46076  AxesHelper.prototype.constructor = AxesHelper;
46077 
46082  function Face4( a, b, c, d, normal, color, materialIndex ) {
46083 
46084  console.warn( 'THREE.Face4 has been removed. A THREE.Face3 will be created instead.' );
46085  return new Face3( a, b, c, normal, color, materialIndex );
46086 
46087  }
46088 
46089  var LineStrip = 0;
46090 
46091  var LinePieces = 1;
46092 
46093  function MeshFaceMaterial( materials ) {
46094 
46095  console.warn( 'THREE.MeshFaceMaterial has been removed. Use an Array instead.' );
46096  return materials;
46097 
46098  }
46099 
46100  function MultiMaterial( materials ) {
46101 
46102  if ( materials === undefined ) materials = [];
46103 
46104  console.warn( 'THREE.MultiMaterial has been removed. Use an Array instead.' );
46105  materials.isMultiMaterial = true;
46106  materials.materials = materials;
46107  materials.clone = function () {
46108 
46109  return materials.slice();
46110 
46111  };
46112  return materials;
46113 
46114  }
46115 
46116  function PointCloud( geometry, material ) {
46117 
46118  console.warn( 'THREE.PointCloud has been renamed to THREE.Points.' );
46119  return new Points( geometry, material );
46120 
46121  }
46122 
46123  function Particle( material ) {
46124 
46125  console.warn( 'THREE.Particle has been renamed to THREE.Sprite.' );
46126  return new Sprite( material );
46127 
46128  }
46129 
46130  function ParticleSystem( geometry, material ) {
46131 
46132  console.warn( 'THREE.ParticleSystem has been renamed to THREE.Points.' );
46133  return new Points( geometry, material );
46134 
46135  }
46136 
46137  function PointCloudMaterial( parameters ) {
46138 
46139  console.warn( 'THREE.PointCloudMaterial has been renamed to THREE.PointsMaterial.' );
46140  return new PointsMaterial( parameters );
46141 
46142  }
46143 
46144  function ParticleBasicMaterial( parameters ) {
46145 
46146  console.warn( 'THREE.ParticleBasicMaterial has been renamed to THREE.PointsMaterial.' );
46147  return new PointsMaterial( parameters );
46148 
46149  }
46150 
46151  function ParticleSystemMaterial( parameters ) {
46152 
46153  console.warn( 'THREE.ParticleSystemMaterial has been renamed to THREE.PointsMaterial.' );
46154  return new PointsMaterial( parameters );
46155 
46156  }
46157 
46158  function Vertex( x, y, z ) {
46159 
46160  console.warn( 'THREE.Vertex has been removed. Use THREE.Vector3 instead.' );
46161  return new Vector3( x, y, z );
46162 
46163  }
46164 
46165  //
46166 
46167  function DynamicBufferAttribute( array, itemSize ) {
46168 
46169  console.warn( 'THREE.DynamicBufferAttribute has been removed. Use new THREE.BufferAttribute().setDynamic( true ) instead.' );
46170  return new BufferAttribute( array, itemSize ).setDynamic( true );
46171 
46172  }
46173 
46174  function Int8Attribute( array, itemSize ) {
46175 
46176  console.warn( 'THREE.Int8Attribute has been removed. Use new THREE.Int8BufferAttribute() instead.' );
46177  return new Int8BufferAttribute( array, itemSize );
46178 
46179  }
46180 
46181  function Uint8Attribute( array, itemSize ) {
46182 
46183  console.warn( 'THREE.Uint8Attribute has been removed. Use new THREE.Uint8BufferAttribute() instead.' );
46184  return new Uint8BufferAttribute( array, itemSize );
46185 
46186  }
46187 
46188  function Uint8ClampedAttribute( array, itemSize ) {
46189 
46190  console.warn( 'THREE.Uint8ClampedAttribute has been removed. Use new THREE.Uint8ClampedBufferAttribute() instead.' );
46191  return new Uint8ClampedBufferAttribute( array, itemSize );
46192 
46193  }
46194 
46195  function Int16Attribute( array, itemSize ) {
46196 
46197  console.warn( 'THREE.Int16Attribute has been removed. Use new THREE.Int16BufferAttribute() instead.' );
46198  return new Int16BufferAttribute( array, itemSize );
46199 
46200  }
46201 
46202  function Uint16Attribute( array, itemSize ) {
46203 
46204  console.warn( 'THREE.Uint16Attribute has been removed. Use new THREE.Uint16BufferAttribute() instead.' );
46205  return new Uint16BufferAttribute( array, itemSize );
46206 
46207  }
46208 
46209  function Int32Attribute( array, itemSize ) {
46210 
46211  console.warn( 'THREE.Int32Attribute has been removed. Use new THREE.Int32BufferAttribute() instead.' );
46212  return new Int32BufferAttribute( array, itemSize );
46213 
46214  }
46215 
46216  function Uint32Attribute( array, itemSize ) {
46217 
46218  console.warn( 'THREE.Uint32Attribute has been removed. Use new THREE.Uint32BufferAttribute() instead.' );
46219  return new Uint32BufferAttribute( array, itemSize );
46220 
46221  }
46222 
46223  function Float32Attribute( array, itemSize ) {
46224 
46225  console.warn( 'THREE.Float32Attribute has been removed. Use new THREE.Float32BufferAttribute() instead.' );
46226  return new Float32BufferAttribute( array, itemSize );
46227 
46228  }
46229 
46230  function Float64Attribute( array, itemSize ) {
46231 
46232  console.warn( 'THREE.Float64Attribute has been removed. Use new THREE.Float64BufferAttribute() instead.' );
46233  return new Float64BufferAttribute( array, itemSize );
46234 
46235  }
46236 
46237  //
46238 
46239  Curve.create = function ( construct, getPoint ) {
46240 
46241  console.log( 'THREE.Curve.create() has been deprecated' );
46242 
46243  construct.prototype = Object.create( Curve.prototype );
46244  construct.prototype.constructor = construct;
46245  construct.prototype.getPoint = getPoint;
46246 
46247  return construct;
46248 
46249  };
46250 
46251  //
46252 
46253  Object.assign( CurvePath.prototype, {
46254 
46255  createPointsGeometry: function ( divisions ) {
46256 
46257  console.warn( 'THREE.CurvePath: .createPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' );
46258 
46259  // generate geometry from path points (for Line or Points objects)
46260 
46261  var pts = this.getPoints( divisions );
46262  return this.createGeometry( pts );
46263 
46264  },
46265 
46266  createSpacedPointsGeometry: function ( divisions ) {
46267 
46268  console.warn( 'THREE.CurvePath: .createSpacedPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' );
46269 
46270  // generate geometry from equidistant sampling along the path
46271 
46272  var pts = this.getSpacedPoints( divisions );
46273  return this.createGeometry( pts );
46274 
46275  },
46276 
46277  createGeometry: function ( points ) {
46278 
46279  console.warn( 'THREE.CurvePath: .createGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' );
46280 
46281  var geometry = new Geometry();
46282 
46283  for ( var i = 0, l = points.length; i < l; i ++ ) {
46284 
46285  var point = points[ i ];
46286  geometry.vertices.push( new Vector3( point.x, point.y, point.z || 0 ) );
46287 
46288  }
46289 
46290  return geometry;
46291 
46292  }
46293 
46294  } );
46295 
46296  //
46297 
46298  Object.assign( Path.prototype, {
46299 
46300  fromPoints: function ( points ) {
46301 
46302  console.warn( 'THREE.Path: .fromPoints() has been renamed to .setFromPoints().' );
46303  this.setFromPoints( points );
46304 
46305  }
46306 
46307  } );
46308 
46309  //
46310 
46311  function ClosedSplineCurve3( points ) {
46312 
46313  console.warn( 'THREE.ClosedSplineCurve3 has been deprecated. Use THREE.CatmullRomCurve3 instead.' );
46314 
46315  CatmullRomCurve3.call( this, points );
46316  this.type = 'catmullrom';
46317  this.closed = true;
46318 
46319  }
46320 
46321  ClosedSplineCurve3.prototype = Object.create( CatmullRomCurve3.prototype );
46322 
46323  //
46324 
46325  function SplineCurve3( points ) {
46326 
46327  console.warn( 'THREE.SplineCurve3 has been deprecated. Use THREE.CatmullRomCurve3 instead.' );
46328 
46329  CatmullRomCurve3.call( this, points );
46330  this.type = 'catmullrom';
46331 
46332  }
46333 
46334  SplineCurve3.prototype = Object.create( CatmullRomCurve3.prototype );
46335 
46336  //
46337 
46338  function Spline( points ) {
46339 
46340  console.warn( 'THREE.Spline has been removed. Use THREE.CatmullRomCurve3 instead.' );
46341 
46342  CatmullRomCurve3.call( this, points );
46343  this.type = 'catmullrom';
46344 
46345  }
46346 
46347  Spline.prototype = Object.create( CatmullRomCurve3.prototype );
46348 
46349  Object.assign( Spline.prototype, {
46350 
46351  initFromArray: function ( /* a */ ) {
46352 
46353  console.error( 'THREE.Spline: .initFromArray() has been removed.' );
46354 
46355  },
46356  getControlPointsArray: function ( /* optionalTarget */ ) {
46357 
46358  console.error( 'THREE.Spline: .getControlPointsArray() has been removed.' );
46359 
46360  },
46361  reparametrizeByArcLength: function ( /* samplingCoef */ ) {
46362 
46363  console.error( 'THREE.Spline: .reparametrizeByArcLength() has been removed.' );
46364 
46365  }
46366 
46367  } );
46368 
46369  //
46370 
46371  function AxisHelper( size ) {
46372 
46373  console.warn( 'THREE.AxisHelper has been renamed to THREE.AxesHelper.' );
46374  return new AxesHelper( size );
46375 
46376  }
46377 
46378  function BoundingBoxHelper( object, color ) {
46379 
46380  console.warn( 'THREE.BoundingBoxHelper has been deprecated. Creating a THREE.BoxHelper instead.' );
46381  return new BoxHelper( object, color );
46382 
46383  }
46384 
46385  function EdgesHelper( object, hex ) {
46386 
46387  console.warn( 'THREE.EdgesHelper has been removed. Use THREE.EdgesGeometry instead.' );
46388  return new LineSegments( new EdgesGeometry( object.geometry ), new LineBasicMaterial( { color: hex !== undefined ? hex : 0xffffff } ) );
46389 
46390  }
46391 
46392  GridHelper.prototype.setColors = function () {
46393 
46394  console.error( 'THREE.GridHelper: setColors() has been deprecated, pass them in the constructor instead.' );
46395 
46396  };
46397 
46398  SkeletonHelper.prototype.update = function () {
46399 
46400  console.error( 'THREE.SkeletonHelper: update() no longer needs to be called.' );
46401 
46402  };
46403 
46404  function WireframeHelper( object, hex ) {
46405 
46406  console.warn( 'THREE.WireframeHelper has been removed. Use THREE.WireframeGeometry instead.' );
46407  return new LineSegments( new WireframeGeometry( object.geometry ), new LineBasicMaterial( { color: hex !== undefined ? hex : 0xffffff } ) );
46408 
46409  }
46410 
46411  //
46412 
46413  Object.assign( Loader.prototype, {
46414 
46415  extractUrlBase: function ( url ) {
46416 
46417  console.warn( 'THREE.Loader: .extractUrlBase() has been deprecated. Use THREE.LoaderUtils.extractUrlBase() instead.' );
46418  return LoaderUtils.extractUrlBase( url );
46419 
46420  }
46421 
46422  } );
46423 
46424  function XHRLoader( manager ) {
46425 
46426  console.warn( 'THREE.XHRLoader has been renamed to THREE.FileLoader.' );
46427  return new FileLoader( manager );
46428 
46429  }
46430 
46431  function BinaryTextureLoader( manager ) {
46432 
46433  console.warn( 'THREE.BinaryTextureLoader has been renamed to THREE.DataTextureLoader.' );
46434  return new DataTextureLoader( manager );
46435 
46436  }
46437 
46438  Object.assign( ObjectLoader.prototype, {
46439 
46440  setTexturePath: function ( value ) {
46441 
46442  console.warn( 'THREE.ObjectLoader: .setTexturePath() has been renamed to .setResourcePath().' );
46443  return this.setResourcePath( value );
46444 
46445  }
46446 
46447  } );
46448 
46449  //
46450 
46451  Object.assign( Box2.prototype, {
46452 
46453  center: function ( optionalTarget ) {
46454 
46455  console.warn( 'THREE.Box2: .center() has been renamed to .getCenter().' );
46456  return this.getCenter( optionalTarget );
46457 
46458  },
46459  empty: function () {
46460 
46461  console.warn( 'THREE.Box2: .empty() has been renamed to .isEmpty().' );
46462  return this.isEmpty();
46463 
46464  },
46465  isIntersectionBox: function ( box ) {
46466 
46467  console.warn( 'THREE.Box2: .isIntersectionBox() has been renamed to .intersectsBox().' );
46468  return this.intersectsBox( box );
46469 
46470  },
46471  size: function ( optionalTarget ) {
46472 
46473  console.warn( 'THREE.Box2: .size() has been renamed to .getSize().' );
46474  return this.getSize( optionalTarget );
46475 
46476  }
46477  } );
46478 
46479  Object.assign( Box3.prototype, {
46480 
46481  center: function ( optionalTarget ) {
46482 
46483  console.warn( 'THREE.Box3: .center() has been renamed to .getCenter().' );
46484  return this.getCenter( optionalTarget );
46485 
46486  },
46487  empty: function () {
46488 
46489  console.warn( 'THREE.Box3: .empty() has been renamed to .isEmpty().' );
46490  return this.isEmpty();
46491 
46492  },
46493  isIntersectionBox: function ( box ) {
46494 
46495  console.warn( 'THREE.Box3: .isIntersectionBox() has been renamed to .intersectsBox().' );
46496  return this.intersectsBox( box );
46497 
46498  },
46499  isIntersectionSphere: function ( sphere ) {
46500 
46501  console.warn( 'THREE.Box3: .isIntersectionSphere() has been renamed to .intersectsSphere().' );
46502  return this.intersectsSphere( sphere );
46503 
46504  },
46505  size: function ( optionalTarget ) {
46506 
46507  console.warn( 'THREE.Box3: .size() has been renamed to .getSize().' );
46508  return this.getSize( optionalTarget );
46509 
46510  }
46511  } );
46512 
46513  Line3.prototype.center = function ( optionalTarget ) {
46514 
46515  console.warn( 'THREE.Line3: .center() has been renamed to .getCenter().' );
46516  return this.getCenter( optionalTarget );
46517 
46518  };
46519 
46520  Object.assign( _Math, {
46521 
46522  random16: function () {
46523 
46524  console.warn( 'THREE.Math: .random16() has been deprecated. Use Math.random() instead.' );
46525  return Math.random();
46526 
46527  },
46528 
46529  nearestPowerOfTwo: function ( value ) {
46530 
46531  console.warn( 'THREE.Math: .nearestPowerOfTwo() has been renamed to .floorPowerOfTwo().' );
46532  return _Math.floorPowerOfTwo( value );
46533 
46534  },
46535 
46536  nextPowerOfTwo: function ( value ) {
46537 
46538  console.warn( 'THREE.Math: .nextPowerOfTwo() has been renamed to .ceilPowerOfTwo().' );
46539  return _Math.ceilPowerOfTwo( value );
46540 
46541  }
46542 
46543  } );
46544 
46545  Object.assign( Matrix3.prototype, {
46546 
46547  flattenToArrayOffset: function ( array, offset ) {
46548 
46549  console.warn( "THREE.Matrix3: .flattenToArrayOffset() has been deprecated. Use .toArray() instead." );
46550  return this.toArray( array, offset );
46551 
46552  },
46553  multiplyVector3: function ( vector ) {
46554 
46555  console.warn( 'THREE.Matrix3: .multiplyVector3() has been removed. Use vector.applyMatrix3( matrix ) instead.' );
46556  return vector.applyMatrix3( this );
46557 
46558  },
46559  multiplyVector3Array: function ( /* a */ ) {
46560 
46561  console.error( 'THREE.Matrix3: .multiplyVector3Array() has been removed.' );
46562 
46563  },
46564  applyToBuffer: function ( buffer /*, offset, length */ ) {
46565 
46566  console.warn( 'THREE.Matrix3: .applyToBuffer() has been removed. Use matrix.applyToBufferAttribute( attribute ) instead.' );
46567  return this.applyToBufferAttribute( buffer );
46568 
46569  },
46570  applyToVector3Array: function ( /* array, offset, length */ ) {
46571 
46572  console.error( 'THREE.Matrix3: .applyToVector3Array() has been removed.' );
46573 
46574  }
46575 
46576  } );
46577 
46578  Object.assign( Matrix4.prototype, {
46579 
46580  extractPosition: function ( m ) {
46581 
46582  console.warn( 'THREE.Matrix4: .extractPosition() has been renamed to .copyPosition().' );
46583  return this.copyPosition( m );
46584 
46585  },
46586  flattenToArrayOffset: function ( array, offset ) {
46587 
46588  console.warn( "THREE.Matrix4: .flattenToArrayOffset() has been deprecated. Use .toArray() instead." );
46589  return this.toArray( array, offset );
46590 
46591  },
46592  getPosition: function () {
46593 
46594  var v1;
46595 
46596  return function getPosition() {
46597 
46598  if ( v1 === undefined ) v1 = new Vector3();
46599  console.warn( 'THREE.Matrix4: .getPosition() has been removed. Use Vector3.setFromMatrixPosition( matrix ) instead.' );
46600  return v1.setFromMatrixColumn( this, 3 );
46601 
46602  };
46603 
46604  }(),
46605  setRotationFromQuaternion: function ( q ) {
46606 
46607  console.warn( 'THREE.Matrix4: .setRotationFromQuaternion() has been renamed to .makeRotationFromQuaternion().' );
46608  return this.makeRotationFromQuaternion( q );
46609 
46610  },
46611  multiplyToArray: function () {
46612 
46613  console.warn( 'THREE.Matrix4: .multiplyToArray() has been removed.' );
46614 
46615  },
46616  multiplyVector3: function ( vector ) {
46617 
46618  console.warn( 'THREE.Matrix4: .multiplyVector3() has been removed. Use vector.applyMatrix4( matrix ) instead.' );
46619  return vector.applyMatrix4( this );
46620 
46621  },
46622  multiplyVector4: function ( vector ) {
46623 
46624  console.warn( 'THREE.Matrix4: .multiplyVector4() has been removed. Use vector.applyMatrix4( matrix ) instead.' );
46625  return vector.applyMatrix4( this );
46626 
46627  },
46628  multiplyVector3Array: function ( /* a */ ) {
46629 
46630  console.error( 'THREE.Matrix4: .multiplyVector3Array() has been removed.' );
46631 
46632  },
46633  rotateAxis: function ( v ) {
46634 
46635  console.warn( 'THREE.Matrix4: .rotateAxis() has been removed. Use Vector3.transformDirection( matrix ) instead.' );
46636  v.transformDirection( this );
46637 
46638  },
46639  crossVector: function ( vector ) {
46640 
46641  console.warn( 'THREE.Matrix4: .crossVector() has been removed. Use vector.applyMatrix4( matrix ) instead.' );
46642  return vector.applyMatrix4( this );
46643 
46644  },
46645  translate: function () {
46646 
46647  console.error( 'THREE.Matrix4: .translate() has been removed.' );
46648 
46649  },
46650  rotateX: function () {
46651 
46652  console.error( 'THREE.Matrix4: .rotateX() has been removed.' );
46653 
46654  },
46655  rotateY: function () {
46656 
46657  console.error( 'THREE.Matrix4: .rotateY() has been removed.' );
46658 
46659  },
46660  rotateZ: function () {
46661 
46662  console.error( 'THREE.Matrix4: .rotateZ() has been removed.' );
46663 
46664  },
46665  rotateByAxis: function () {
46666 
46667  console.error( 'THREE.Matrix4: .rotateByAxis() has been removed.' );
46668 
46669  },
46670  applyToBuffer: function ( buffer /*, offset, length */ ) {
46671 
46672  console.warn( 'THREE.Matrix4: .applyToBuffer() has been removed. Use matrix.applyToBufferAttribute( attribute ) instead.' );
46673  return this.applyToBufferAttribute( buffer );
46674 
46675  },
46676  applyToVector3Array: function ( /* array, offset, length */ ) {
46677 
46678  console.error( 'THREE.Matrix4: .applyToVector3Array() has been removed.' );
46679 
46680  },
46681  makeFrustum: function ( left, right, bottom, top, near, far ) {
46682 
46683  console.warn( 'THREE.Matrix4: .makeFrustum() has been removed. Use .makePerspective( left, right, top, bottom, near, far ) instead.' );
46684  return this.makePerspective( left, right, top, bottom, near, far );
46685 
46686  }
46687 
46688  } );
46689 
46690  Plane.prototype.isIntersectionLine = function ( line ) {
46691 
46692  console.warn( 'THREE.Plane: .isIntersectionLine() has been renamed to .intersectsLine().' );
46693  return this.intersectsLine( line );
46694 
46695  };
46696 
46697  Quaternion.prototype.multiplyVector3 = function ( vector ) {
46698 
46699  console.warn( 'THREE.Quaternion: .multiplyVector3() has been removed. Use is now vector.applyQuaternion( quaternion ) instead.' );
46700  return vector.applyQuaternion( this );
46701 
46702  };
46703 
46704  Object.assign( Ray.prototype, {
46705 
46706  isIntersectionBox: function ( box ) {
46707 
46708  console.warn( 'THREE.Ray: .isIntersectionBox() has been renamed to .intersectsBox().' );
46709  return this.intersectsBox( box );
46710 
46711  },
46712  isIntersectionPlane: function ( plane ) {
46713 
46714  console.warn( 'THREE.Ray: .isIntersectionPlane() has been renamed to .intersectsPlane().' );
46715  return this.intersectsPlane( plane );
46716 
46717  },
46718  isIntersectionSphere: function ( sphere ) {
46719 
46720  console.warn( 'THREE.Ray: .isIntersectionSphere() has been renamed to .intersectsSphere().' );
46721  return this.intersectsSphere( sphere );
46722 
46723  }
46724 
46725  } );
46726 
46727  Object.assign( Triangle.prototype, {
46728 
46729  area: function () {
46730 
46731  console.warn( 'THREE.Triangle: .area() has been renamed to .getArea().' );
46732  return this.getArea();
46733 
46734  },
46735  barycoordFromPoint: function ( point, target ) {
46736 
46737  console.warn( 'THREE.Triangle: .barycoordFromPoint() has been renamed to .getBarycoord().' );
46738  return this.getBarycoord( point, target );
46739 
46740  },
46741  midpoint: function ( target ) {
46742 
46743  console.warn( 'THREE.Triangle: .midpoint() has been renamed to .getMidpoint().' );
46744  return this.getMidpoint( target );
46745 
46746  },
46747  normal: function ( target ) {
46748 
46749  console.warn( 'THREE.Triangle: .normal() has been renamed to .getNormal().' );
46750  return this.getNormal( target );
46751 
46752  },
46753  plane: function ( target ) {
46754 
46755  console.warn( 'THREE.Triangle: .plane() has been renamed to .getPlane().' );
46756  return this.getPlane( target );
46757 
46758  }
46759 
46760  } );
46761 
46762  Object.assign( Triangle, {
46763 
46764  barycoordFromPoint: function ( point, a, b, c, target ) {
46765 
46766  console.warn( 'THREE.Triangle: .barycoordFromPoint() has been renamed to .getBarycoord().' );
46767  return Triangle.getBarycoord( point, a, b, c, target );
46768 
46769  },
46770  normal: function ( a, b, c, target ) {
46771 
46772  console.warn( 'THREE.Triangle: .normal() has been renamed to .getNormal().' );
46773  return Triangle.getNormal( a, b, c, target );
46774 
46775  }
46776 
46777  } );
46778 
46779  Object.assign( Shape.prototype, {
46780 
46781  extractAllPoints: function ( divisions ) {
46782 
46783  console.warn( 'THREE.Shape: .extractAllPoints() has been removed. Use .extractPoints() instead.' );
46784  return this.extractPoints( divisions );
46785 
46786  },
46787  extrude: function ( options ) {
46788 
46789  console.warn( 'THREE.Shape: .extrude() has been removed. Use ExtrudeGeometry() instead.' );
46790  return new ExtrudeGeometry( this, options );
46791 
46792  },
46793  makeGeometry: function ( options ) {
46794 
46795  console.warn( 'THREE.Shape: .makeGeometry() has been removed. Use ShapeGeometry() instead.' );
46796  return new ShapeGeometry( this, options );
46797 
46798  }
46799 
46800  } );
46801 
46802  Object.assign( Vector2.prototype, {
46803 
46804  fromAttribute: function ( attribute, index, offset ) {
46805 
46806  console.warn( 'THREE.Vector2: .fromAttribute() has been renamed to .fromBufferAttribute().' );
46807  return this.fromBufferAttribute( attribute, index, offset );
46808 
46809  },
46810  distanceToManhattan: function ( v ) {
46811 
46812  console.warn( 'THREE.Vector2: .distanceToManhattan() has been renamed to .manhattanDistanceTo().' );
46813  return this.manhattanDistanceTo( v );
46814 
46815  },
46816  lengthManhattan: function () {
46817 
46818  console.warn( 'THREE.Vector2: .lengthManhattan() has been renamed to .manhattanLength().' );
46819  return this.manhattanLength();
46820 
46821  }
46822 
46823  } );
46824 
46825  Object.assign( Vector3.prototype, {
46826 
46827  setEulerFromRotationMatrix: function () {
46828 
46829  console.error( 'THREE.Vector3: .setEulerFromRotationMatrix() has been removed. Use Euler.setFromRotationMatrix() instead.' );
46830 
46831  },
46832  setEulerFromQuaternion: function () {
46833 
46834  console.error( 'THREE.Vector3: .setEulerFromQuaternion() has been removed. Use Euler.setFromQuaternion() instead.' );
46835 
46836  },
46837  getPositionFromMatrix: function ( m ) {
46838 
46839  console.warn( 'THREE.Vector3: .getPositionFromMatrix() has been renamed to .setFromMatrixPosition().' );
46840  return this.setFromMatrixPosition( m );
46841 
46842  },
46843  getScaleFromMatrix: function ( m ) {
46844 
46845  console.warn( 'THREE.Vector3: .getScaleFromMatrix() has been renamed to .setFromMatrixScale().' );
46846  return this.setFromMatrixScale( m );
46847 
46848  },
46849  getColumnFromMatrix: function ( index, matrix ) {
46850 
46851  console.warn( 'THREE.Vector3: .getColumnFromMatrix() has been renamed to .setFromMatrixColumn().' );
46852  return this.setFromMatrixColumn( matrix, index );
46853 
46854  },
46855  applyProjection: function ( m ) {
46856 
46857  console.warn( 'THREE.Vector3: .applyProjection() has been removed. Use .applyMatrix4( m ) instead.' );
46858  return this.applyMatrix4( m );
46859 
46860  },
46861  fromAttribute: function ( attribute, index, offset ) {
46862 
46863  console.warn( 'THREE.Vector3: .fromAttribute() has been renamed to .fromBufferAttribute().' );
46864  return this.fromBufferAttribute( attribute, index, offset );
46865 
46866  },
46867  distanceToManhattan: function ( v ) {
46868 
46869  console.warn( 'THREE.Vector3: .distanceToManhattan() has been renamed to .manhattanDistanceTo().' );
46870  return this.manhattanDistanceTo( v );
46871 
46872  },
46873  lengthManhattan: function () {
46874 
46875  console.warn( 'THREE.Vector3: .lengthManhattan() has been renamed to .manhattanLength().' );
46876  return this.manhattanLength();
46877 
46878  }
46879 
46880  } );
46881 
46882  Object.assign( Vector4.prototype, {
46883 
46884  fromAttribute: function ( attribute, index, offset ) {
46885 
46886  console.warn( 'THREE.Vector4: .fromAttribute() has been renamed to .fromBufferAttribute().' );
46887  return this.fromBufferAttribute( attribute, index, offset );
46888 
46889  },
46890  lengthManhattan: function () {
46891 
46892  console.warn( 'THREE.Vector4: .lengthManhattan() has been renamed to .manhattanLength().' );
46893  return this.manhattanLength();
46894 
46895  }
46896 
46897  } );
46898 
46899  //
46900 
46901  Object.assign( Geometry.prototype, {
46902 
46903  computeTangents: function () {
46904 
46905  console.error( 'THREE.Geometry: .computeTangents() has been removed.' );
46906 
46907  },
46908  computeLineDistances: function () {
46909 
46910  console.error( 'THREE.Geometry: .computeLineDistances() has been removed. Use THREE.Line.computeLineDistances() instead.' );
46911 
46912  }
46913 
46914  } );
46915 
46916  Object.assign( Object3D.prototype, {
46917 
46918  getChildByName: function ( name ) {
46919 
46920  console.warn( 'THREE.Object3D: .getChildByName() has been renamed to .getObjectByName().' );
46921  return this.getObjectByName( name );
46922 
46923  },
46924  renderDepth: function () {
46925 
46926  console.warn( 'THREE.Object3D: .renderDepth has been removed. Use .renderOrder, instead.' );
46927 
46928  },
46929  translate: function ( distance, axis ) {
46930 
46931  console.warn( 'THREE.Object3D: .translate() has been removed. Use .translateOnAxis( axis, distance ) instead.' );
46932  return this.translateOnAxis( axis, distance );
46933 
46934  },
46935  getWorldRotation: function () {
46936 
46937  console.error( 'THREE.Object3D: .getWorldRotation() has been removed. Use THREE.Object3D.getWorldQuaternion( target ) instead.' );
46938 
46939  }
46940 
46941  } );
46942 
46943  Object.defineProperties( Object3D.prototype, {
46944 
46945  eulerOrder: {
46946  get: function () {
46947 
46948  console.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' );
46949  return this.rotation.order;
46950 
46951  },
46952  set: function ( value ) {
46953 
46954  console.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' );
46955  this.rotation.order = value;
46956 
46957  }
46958  },
46959  useQuaternion: {
46960  get: function () {
46961 
46962  console.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' );
46963 
46964  },
46965  set: function () {
46966 
46967  console.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' );
46968 
46969  }
46970  }
46971 
46972  } );
46973 
46974  Object.defineProperties( LOD.prototype, {
46975 
46976  objects: {
46977  get: function () {
46978 
46979  console.warn( 'THREE.LOD: .objects has been renamed to .levels.' );
46980  return this.levels;
46981 
46982  }
46983  }
46984 
46985  } );
46986 
46987  Object.defineProperty( Skeleton.prototype, 'useVertexTexture', {
46988 
46989  get: function () {
46990 
46991  console.warn( 'THREE.Skeleton: useVertexTexture has been removed.' );
46992 
46993  },
46994  set: function () {
46995 
46996  console.warn( 'THREE.Skeleton: useVertexTexture has been removed.' );
46997 
46998  }
46999 
47000  } );
47001 
47002  SkinnedMesh.prototype.initBones = function () {
47003 
47004  console.error( 'THREE.SkinnedMesh: initBones() has been removed.' );
47005 
47006  };
47007 
47008  Object.defineProperty( Curve.prototype, '__arcLengthDivisions', {
47009 
47010  get: function () {
47011 
47012  console.warn( 'THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.' );
47013  return this.arcLengthDivisions;
47014 
47015  },
47016  set: function ( value ) {
47017 
47018  console.warn( 'THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.' );
47019  this.arcLengthDivisions = value;
47020 
47021  }
47022 
47023  } );
47024 
47025  //
47026 
47027  PerspectiveCamera.prototype.setLens = function ( focalLength, filmGauge ) {
47028 
47029  console.warn( "THREE.PerspectiveCamera.setLens is deprecated. " +
47030  "Use .setFocalLength and .filmGauge for a photographic setup." );
47031 
47032  if ( filmGauge !== undefined ) this.filmGauge = filmGauge;
47033  this.setFocalLength( focalLength );
47034 
47035  };
47036 
47037  //
47038 
47039  Object.defineProperties( Light.prototype, {
47040  onlyShadow: {
47041  set: function () {
47042 
47043  console.warn( 'THREE.Light: .onlyShadow has been removed.' );
47044 
47045  }
47046  },
47047  shadowCameraFov: {
47048  set: function ( value ) {
47049 
47050  console.warn( 'THREE.Light: .shadowCameraFov is now .shadow.camera.fov.' );
47051  this.shadow.camera.fov = value;
47052 
47053  }
47054  },
47055  shadowCameraLeft: {
47056  set: function ( value ) {
47057 
47058  console.warn( 'THREE.Light: .shadowCameraLeft is now .shadow.camera.left.' );
47059  this.shadow.camera.left = value;
47060 
47061  }
47062  },
47063  shadowCameraRight: {
47064  set: function ( value ) {
47065 
47066  console.warn( 'THREE.Light: .shadowCameraRight is now .shadow.camera.right.' );
47067  this.shadow.camera.right = value;
47068 
47069  }
47070  },
47071  shadowCameraTop: {
47072  set: function ( value ) {
47073 
47074  console.warn( 'THREE.Light: .shadowCameraTop is now .shadow.camera.top.' );
47075  this.shadow.camera.top = value;
47076 
47077  }
47078  },
47079  shadowCameraBottom: {
47080  set: function ( value ) {
47081 
47082  console.warn( 'THREE.Light: .shadowCameraBottom is now .shadow.camera.bottom.' );
47083  this.shadow.camera.bottom = value;
47084 
47085  }
47086  },
47087  shadowCameraNear: {
47088  set: function ( value ) {
47089 
47090  console.warn( 'THREE.Light: .shadowCameraNear is now .shadow.camera.near.' );
47091  this.shadow.camera.near = value;
47092 
47093  }
47094  },
47095  shadowCameraFar: {
47096  set: function ( value ) {
47097 
47098  console.warn( 'THREE.Light: .shadowCameraFar is now .shadow.camera.far.' );
47099  this.shadow.camera.far = value;
47100 
47101  }
47102  },
47103  shadowCameraVisible: {
47104  set: function () {
47105 
47106  console.warn( 'THREE.Light: .shadowCameraVisible has been removed. Use new THREE.CameraHelper( light.shadow.camera ) instead.' );
47107 
47108  }
47109  },
47110  shadowBias: {
47111  set: function ( value ) {
47112 
47113  console.warn( 'THREE.Light: .shadowBias is now .shadow.bias.' );
47114  this.shadow.bias = value;
47115 
47116  }
47117  },
47118  shadowDarkness: {
47119  set: function () {
47120 
47121  console.warn( 'THREE.Light: .shadowDarkness has been removed.' );
47122 
47123  }
47124  },
47125  shadowMapWidth: {
47126  set: function ( value ) {
47127 
47128  console.warn( 'THREE.Light: .shadowMapWidth is now .shadow.mapSize.width.' );
47129  this.shadow.mapSize.width = value;
47130 
47131  }
47132  },
47133  shadowMapHeight: {
47134  set: function ( value ) {
47135 
47136  console.warn( 'THREE.Light: .shadowMapHeight is now .shadow.mapSize.height.' );
47137  this.shadow.mapSize.height = value;
47138 
47139  }
47140  }
47141  } );
47142 
47143  //
47144 
47145  Object.defineProperties( BufferAttribute.prototype, {
47146 
47147  length: {
47148  get: function () {
47149 
47150  console.warn( 'THREE.BufferAttribute: .length has been deprecated. Use .count instead.' );
47151  return this.array.length;
47152 
47153  }
47154  },
47155  copyIndicesArray: function ( /* indices */ ) {
47156 
47157  console.error( 'THREE.BufferAttribute: .copyIndicesArray() has been removed.' );
47158 
47159  }
47160 
47161  } );
47162 
47163  Object.assign( BufferGeometry.prototype, {
47164 
47165  addIndex: function ( index ) {
47166 
47167  console.warn( 'THREE.BufferGeometry: .addIndex() has been renamed to .setIndex().' );
47168  this.setIndex( index );
47169 
47170  },
47171  addDrawCall: function ( start, count, indexOffset ) {
47172 
47173  if ( indexOffset !== undefined ) {
47174 
47175  console.warn( 'THREE.BufferGeometry: .addDrawCall() no longer supports indexOffset.' );
47176 
47177  }
47178  console.warn( 'THREE.BufferGeometry: .addDrawCall() is now .addGroup().' );
47179  this.addGroup( start, count );
47180 
47181  },
47182  clearDrawCalls: function () {
47183 
47184  console.warn( 'THREE.BufferGeometry: .clearDrawCalls() is now .clearGroups().' );
47185  this.clearGroups();
47186 
47187  },
47188  computeTangents: function () {
47189 
47190  console.warn( 'THREE.BufferGeometry: .computeTangents() has been removed.' );
47191 
47192  },
47193  computeOffsets: function () {
47194 
47195  console.warn( 'THREE.BufferGeometry: .computeOffsets() has been removed.' );
47196 
47197  }
47198 
47199  } );
47200 
47201  Object.defineProperties( BufferGeometry.prototype, {
47202 
47203  drawcalls: {
47204  get: function () {
47205 
47206  console.error( 'THREE.BufferGeometry: .drawcalls has been renamed to .groups.' );
47207  return this.groups;
47208 
47209  }
47210  },
47211  offsets: {
47212  get: function () {
47213 
47214  console.warn( 'THREE.BufferGeometry: .offsets has been renamed to .groups.' );
47215  return this.groups;
47216 
47217  }
47218  }
47219 
47220  } );
47221 
47222  //
47223 
47224  Object.assign( ExtrudeBufferGeometry.prototype, {
47225 
47226  getArrays: function () {
47227 
47228  console.error( 'THREE.ExtrudeBufferGeometry: .getArrays() has been removed.' );
47229 
47230  },
47231 
47232  addShapeList: function () {
47233 
47234  console.error( 'THREE.ExtrudeBufferGeometry: .addShapeList() has been removed.' );
47235 
47236  },
47237 
47238  addShape: function () {
47239 
47240  console.error( 'THREE.ExtrudeBufferGeometry: .addShape() has been removed.' );
47241 
47242  }
47243 
47244  } );
47245 
47246  //
47247 
47248  Object.defineProperties( Uniform.prototype, {
47249 
47250  dynamic: {
47251  set: function () {
47252 
47253  console.warn( 'THREE.Uniform: .dynamic has been removed. Use object.onBeforeRender() instead.' );
47254 
47255  }
47256  },
47257  onUpdate: {
47258  value: function () {
47259 
47260  console.warn( 'THREE.Uniform: .onUpdate() has been removed. Use object.onBeforeRender() instead.' );
47261  return this;
47262 
47263  }
47264  }
47265 
47266  } );
47267 
47268  //
47269 
47270  Object.defineProperties( Material.prototype, {
47271 
47272  wrapAround: {
47273  get: function () {
47274 
47275  console.warn( 'THREE.Material: .wrapAround has been removed.' );
47276 
47277  },
47278  set: function () {
47279 
47280  console.warn( 'THREE.Material: .wrapAround has been removed.' );
47281 
47282  }
47283  },
47284 
47285  overdraw: {
47286  get: function () {
47287 
47288  console.warn( 'THREE.Material: .overdraw has been removed.' );
47289 
47290  },
47291  set: function () {
47292 
47293  console.warn( 'THREE.Material: .overdraw has been removed.' );
47294 
47295  }
47296  },
47297 
47298  wrapRGB: {
47299  get: function () {
47300 
47301  console.warn( 'THREE.Material: .wrapRGB has been removed.' );
47302  return new Color();
47303 
47304  }
47305  },
47306 
47307  shading: {
47308  get: function () {
47309 
47310  console.error( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );
47311 
47312  },
47313  set: function ( value ) {
47314 
47315  console.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );
47316  this.flatShading = ( value === FlatShading );
47317 
47318  }
47319  }
47320 
47321  } );
47322 
47323  Object.defineProperties( MeshPhongMaterial.prototype, {
47324 
47325  metal: {
47326  get: function () {
47327 
47328  console.warn( 'THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead.' );
47329  return false;
47330 
47331  },
47332  set: function () {
47333 
47334  console.warn( 'THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead' );
47335 
47336  }
47337  }
47338 
47339  } );
47340 
47341  Object.defineProperties( ShaderMaterial.prototype, {
47342 
47343  derivatives: {
47344  get: function () {
47345 
47346  console.warn( 'THREE.ShaderMaterial: .derivatives has been moved to .extensions.derivatives.' );
47347  return this.extensions.derivatives;
47348 
47349  },
47350  set: function ( value ) {
47351 
47352  console.warn( 'THREE. ShaderMaterial: .derivatives has been moved to .extensions.derivatives.' );
47353  this.extensions.derivatives = value;
47354 
47355  }
47356  }
47357 
47358  } );
47359 
47360  //
47361 
47362  Object.assign( WebGLRenderer.prototype, {
47363 
47364  clearTarget: function ( renderTarget, color, depth, stencil ) {
47365 
47366  console.warn( 'THREE.WebGLRenderer: .clearTarget() has been deprecated. Use .setRenderTarget() and .clear() instead.' );
47367  this.setRenderTarget( renderTarget );
47368  this.clear( color, depth, stencil );
47369 
47370  },
47371 
47372  animate: function ( callback ) {
47373 
47374  console.warn( 'THREE.WebGLRenderer: .animate() is now .setAnimationLoop().' );
47375  this.setAnimationLoop( callback );
47376 
47377  },
47378 
47379  getCurrentRenderTarget: function () {
47380 
47381  console.warn( 'THREE.WebGLRenderer: .getCurrentRenderTarget() is now .getRenderTarget().' );
47382  return this.getRenderTarget();
47383 
47384  },
47385 
47386  getMaxAnisotropy: function () {
47387 
47388  console.warn( 'THREE.WebGLRenderer: .getMaxAnisotropy() is now .capabilities.getMaxAnisotropy().' );
47389  return this.capabilities.getMaxAnisotropy();
47390 
47391  },
47392 
47393  getPrecision: function () {
47394 
47395  console.warn( 'THREE.WebGLRenderer: .getPrecision() is now .capabilities.precision.' );
47396  return this.capabilities.precision;
47397 
47398  },
47399 
47400  resetGLState: function () {
47401 
47402  console.warn( 'THREE.WebGLRenderer: .resetGLState() is now .state.reset().' );
47403  return this.state.reset();
47404 
47405  },
47406 
47407  supportsFloatTextures: function () {
47408 
47409  console.warn( 'THREE.WebGLRenderer: .supportsFloatTextures() is now .extensions.get( \'OES_texture_float\' ).' );
47410  return this.extensions.get( 'OES_texture_float' );
47411 
47412  },
47413  supportsHalfFloatTextures: function () {
47414 
47415  console.warn( 'THREE.WebGLRenderer: .supportsHalfFloatTextures() is now .extensions.get( \'OES_texture_half_float\' ).' );
47416  return this.extensions.get( 'OES_texture_half_float' );
47417 
47418  },
47419  supportsStandardDerivatives: function () {
47420 
47421  console.warn( 'THREE.WebGLRenderer: .supportsStandardDerivatives() is now .extensions.get( \'OES_standard_derivatives\' ).' );
47422  return this.extensions.get( 'OES_standard_derivatives' );
47423 
47424  },
47425  supportsCompressedTextureS3TC: function () {
47426 
47427  console.warn( 'THREE.WebGLRenderer: .supportsCompressedTextureS3TC() is now .extensions.get( \'WEBGL_compressed_texture_s3tc\' ).' );
47428  return this.extensions.get( 'WEBGL_compressed_texture_s3tc' );
47429 
47430  },
47431  supportsCompressedTexturePVRTC: function () {
47432 
47433  console.warn( 'THREE.WebGLRenderer: .supportsCompressedTexturePVRTC() is now .extensions.get( \'WEBGL_compressed_texture_pvrtc\' ).' );
47434  return this.extensions.get( 'WEBGL_compressed_texture_pvrtc' );
47435 
47436  },
47437  supportsBlendMinMax: function () {
47438 
47439  console.warn( 'THREE.WebGLRenderer: .supportsBlendMinMax() is now .extensions.get( \'EXT_blend_minmax\' ).' );
47440  return this.extensions.get( 'EXT_blend_minmax' );
47441 
47442  },
47443  supportsVertexTextures: function () {
47444 
47445  console.warn( 'THREE.WebGLRenderer: .supportsVertexTextures() is now .capabilities.vertexTextures.' );
47446  return this.capabilities.vertexTextures;
47447 
47448  },
47449  supportsInstancedArrays: function () {
47450 
47451  console.warn( 'THREE.WebGLRenderer: .supportsInstancedArrays() is now .extensions.get( \'ANGLE_instanced_arrays\' ).' );
47452  return this.extensions.get( 'ANGLE_instanced_arrays' );
47453 
47454  },
47455  enableScissorTest: function ( boolean ) {
47456 
47457  console.warn( 'THREE.WebGLRenderer: .enableScissorTest() is now .setScissorTest().' );
47458  this.setScissorTest( boolean );
47459 
47460  },
47461  initMaterial: function () {
47462 
47463  console.warn( 'THREE.WebGLRenderer: .initMaterial() has been removed.' );
47464 
47465  },
47466  addPrePlugin: function () {
47467 
47468  console.warn( 'THREE.WebGLRenderer: .addPrePlugin() has been removed.' );
47469 
47470  },
47471  addPostPlugin: function () {
47472 
47473  console.warn( 'THREE.WebGLRenderer: .addPostPlugin() has been removed.' );
47474 
47475  },
47476  updateShadowMap: function () {
47477 
47478  console.warn( 'THREE.WebGLRenderer: .updateShadowMap() has been removed.' );
47479 
47480  },
47481  setFaceCulling: function () {
47482 
47483  console.warn( 'THREE.WebGLRenderer: .setFaceCulling() has been removed.' );
47484 
47485  }
47486 
47487  } );
47488 
47489  Object.defineProperties( WebGLRenderer.prototype, {
47490 
47491  shadowMapEnabled: {
47492  get: function () {
47493 
47494  return this.shadowMap.enabled;
47495 
47496  },
47497  set: function ( value ) {
47498 
47499  console.warn( 'THREE.WebGLRenderer: .shadowMapEnabled is now .shadowMap.enabled.' );
47500  this.shadowMap.enabled = value;
47501 
47502  }
47503  },
47504  shadowMapType: {
47505  get: function () {
47506 
47507  return this.shadowMap.type;
47508 
47509  },
47510  set: function ( value ) {
47511 
47512  console.warn( 'THREE.WebGLRenderer: .shadowMapType is now .shadowMap.type.' );
47513  this.shadowMap.type = value;
47514 
47515  }
47516  },
47517  shadowMapCullFace: {
47518  get: function () {
47519 
47520  console.warn( 'THREE.WebGLRenderer: .shadowMapCullFace has been removed. Set Material.shadowSide instead.' );
47521  return undefined;
47522 
47523  },
47524  set: function ( /* value */ ) {
47525 
47526  console.warn( 'THREE.WebGLRenderer: .shadowMapCullFace has been removed. Set Material.shadowSide instead.' );
47527 
47528  }
47529  }
47530  } );
47531 
47532  Object.defineProperties( WebGLShadowMap.prototype, {
47533 
47534  cullFace: {
47535  get: function () {
47536 
47537  console.warn( 'THREE.WebGLRenderer: .shadowMap.cullFace has been removed. Set Material.shadowSide instead.' );
47538  return undefined;
47539 
47540  },
47541  set: function ( /* cullFace */ ) {
47542 
47543  console.warn( 'THREE.WebGLRenderer: .shadowMap.cullFace has been removed. Set Material.shadowSide instead.' );
47544 
47545  }
47546  },
47547  renderReverseSided: {
47548  get: function () {
47549 
47550  console.warn( 'THREE.WebGLRenderer: .shadowMap.renderReverseSided has been removed. Set Material.shadowSide instead.' );
47551  return undefined;
47552 
47553  },
47554  set: function () {
47555 
47556  console.warn( 'THREE.WebGLRenderer: .shadowMap.renderReverseSided has been removed. Set Material.shadowSide instead.' );
47557 
47558  }
47559  },
47560  renderSingleSided: {
47561  get: function () {
47562 
47563  console.warn( 'THREE.WebGLRenderer: .shadowMap.renderSingleSided has been removed. Set Material.shadowSide instead.' );
47564  return undefined;
47565 
47566  },
47567  set: function () {
47568 
47569  console.warn( 'THREE.WebGLRenderer: .shadowMap.renderSingleSided has been removed. Set Material.shadowSide instead.' );
47570 
47571  }
47572  }
47573 
47574  } );
47575 
47576  //
47577 
47578  Object.defineProperties( WebGLRenderTargetCube.prototype, {
47579 
47580  activeCubeFace: {
47581  set: function ( /* value */ ) {
47582 
47583  console.warn( 'THREE.WebGLRenderTargetCube: .activeCubeFace has been removed. It is now the second parameter of WebGLRenderer.setRenderTarget().' );
47584 
47585  }
47586  },
47587  activeMipMapLevel: {
47588  set: function ( /* value */ ) {
47589 
47590  console.warn( 'THREE.WebGLRenderTargetCube: .activeMipMapLevel has been removed. It is now the third parameter of WebGLRenderer.setRenderTarget().' );
47591 
47592  }
47593  }
47594 
47595  } );
47596 
47597  //
47598 
47599  Object.defineProperties( WebGLRenderTarget.prototype, {
47600 
47601  wrapS: {
47602  get: function () {
47603 
47604  console.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' );
47605  return this.texture.wrapS;
47606 
47607  },
47608  set: function ( value ) {
47609 
47610  console.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' );
47611  this.texture.wrapS = value;
47612 
47613  }
47614  },
47615  wrapT: {
47616  get: function () {
47617 
47618  console.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' );
47619  return this.texture.wrapT;
47620 
47621  },
47622  set: function ( value ) {
47623 
47624  console.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' );
47625  this.texture.wrapT = value;
47626 
47627  }
47628  },
47629  magFilter: {
47630  get: function () {
47631 
47632  console.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' );
47633  return this.texture.magFilter;
47634 
47635  },
47636  set: function ( value ) {
47637 
47638  console.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' );
47639  this.texture.magFilter = value;
47640 
47641  }
47642  },
47643  minFilter: {
47644  get: function () {
47645 
47646  console.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' );
47647  return this.texture.minFilter;
47648 
47649  },
47650  set: function ( value ) {
47651 
47652  console.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' );
47653  this.texture.minFilter = value;
47654 
47655  }
47656  },
47657  anisotropy: {
47658  get: function () {
47659 
47660  console.warn( 'THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.' );
47661  return this.texture.anisotropy;
47662 
47663  },
47664  set: function ( value ) {
47665 
47666  console.warn( 'THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.' );
47667  this.texture.anisotropy = value;
47668 
47669  }
47670  },
47671  offset: {
47672  get: function () {
47673 
47674  console.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' );
47675  return this.texture.offset;
47676 
47677  },
47678  set: function ( value ) {
47679 
47680  console.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' );
47681  this.texture.offset = value;
47682 
47683  }
47684  },
47685  repeat: {
47686  get: function () {
47687 
47688  console.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' );
47689  return this.texture.repeat;
47690 
47691  },
47692  set: function ( value ) {
47693 
47694  console.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' );
47695  this.texture.repeat = value;
47696 
47697  }
47698  },
47699  format: {
47700  get: function () {
47701 
47702  console.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' );
47703  return this.texture.format;
47704 
47705  },
47706  set: function ( value ) {
47707 
47708  console.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' );
47709  this.texture.format = value;
47710 
47711  }
47712  },
47713  type: {
47714  get: function () {
47715 
47716  console.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' );
47717  return this.texture.type;
47718 
47719  },
47720  set: function ( value ) {
47721 
47722  console.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' );
47723  this.texture.type = value;
47724 
47725  }
47726  },
47727  generateMipmaps: {
47728  get: function () {
47729 
47730  console.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' );
47731  return this.texture.generateMipmaps;
47732 
47733  },
47734  set: function ( value ) {
47735 
47736  console.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' );
47737  this.texture.generateMipmaps = value;
47738 
47739  }
47740  }
47741 
47742  } );
47743 
47744  //
47745 
47746  Object.defineProperties( WebVRManager.prototype, {
47747 
47748  standing: {
47749  set: function ( /* value */ ) {
47750 
47751  console.warn( 'THREE.WebVRManager: .standing has been removed.' );
47752 
47753  }
47754  },
47755  userHeight: {
47756  set: function ( /* value */ ) {
47757 
47758  console.warn( 'THREE.WebVRManager: .userHeight has been removed.' );
47759 
47760  }
47761  }
47762 
47763  } );
47764 
47765  //
47766 
47767  Audio.prototype.load = function ( file ) {
47768 
47769  console.warn( 'THREE.Audio: .load has been deprecated. Use THREE.AudioLoader instead.' );
47770  var scope = this;
47771  var audioLoader = new AudioLoader();
47772  audioLoader.load( file, function ( buffer ) {
47773 
47774  scope.setBuffer( buffer );
47775 
47776  } );
47777  return this;
47778 
47779  };
47780 
47781  AudioAnalyser.prototype.getData = function () {
47782 
47783  console.warn( 'THREE.AudioAnalyser: .getData() is now .getFrequencyData().' );
47784  return this.getFrequencyData();
47785 
47786  };
47787 
47788  //
47789 
47790  CubeCamera.prototype.updateCubeMap = function ( renderer, scene ) {
47791 
47792  console.warn( 'THREE.CubeCamera: .updateCubeMap() is now .update().' );
47793  return this.update( renderer, scene );
47794 
47795  };
47796 
47797  //
47798 
47799  var GeometryUtils = {
47800 
47801  merge: function ( geometry1, geometry2, materialIndexOffset ) {
47802 
47803  console.warn( 'THREE.GeometryUtils: .merge() has been moved to Geometry. Use geometry.merge( geometry2, matrix, materialIndexOffset ) instead.' );
47804  var matrix;
47805 
47806  if ( geometry2.isMesh ) {
47807 
47808  geometry2.matrixAutoUpdate && geometry2.updateMatrix();
47809 
47810  matrix = geometry2.matrix;
47811  geometry2 = geometry2.geometry;
47812 
47813  }
47814 
47815  geometry1.merge( geometry2, matrix, materialIndexOffset );
47816 
47817  },
47818 
47819  center: function ( geometry ) {
47820 
47821  console.warn( 'THREE.GeometryUtils: .center() has been moved to Geometry. Use geometry.center() instead.' );
47822  return geometry.center();
47823 
47824  }
47825 
47826  };
47827 
47828  ImageUtils.crossOrigin = undefined;
47829 
47830  ImageUtils.loadTexture = function ( url, mapping, onLoad, onError ) {
47831 
47832  console.warn( 'THREE.ImageUtils.loadTexture has been deprecated. Use THREE.TextureLoader() instead.' );
47833 
47834  var loader = new TextureLoader();
47835  loader.setCrossOrigin( this.crossOrigin );
47836 
47837  var texture = loader.load( url, onLoad, undefined, onError );
47838 
47839  if ( mapping ) texture.mapping = mapping;
47840 
47841  return texture;
47842 
47843  };
47844 
47845  ImageUtils.loadTextureCube = function ( urls, mapping, onLoad, onError ) {
47846 
47847  console.warn( 'THREE.ImageUtils.loadTextureCube has been deprecated. Use THREE.CubeTextureLoader() instead.' );
47848 
47849  var loader = new CubeTextureLoader();
47850  loader.setCrossOrigin( this.crossOrigin );
47851 
47852  var texture = loader.load( urls, onLoad, undefined, onError );
47853 
47854  if ( mapping ) texture.mapping = mapping;
47855 
47856  return texture;
47857 
47858  };
47859 
47860  ImageUtils.loadCompressedTexture = function () {
47861 
47862  console.error( 'THREE.ImageUtils.loadCompressedTexture has been removed. Use THREE.DDSLoader instead.' );
47863 
47864  };
47865 
47866  ImageUtils.loadCompressedTextureCube = function () {
47867 
47868  console.error( 'THREE.ImageUtils.loadCompressedTextureCube has been removed. Use THREE.DDSLoader instead.' );
47869 
47870  };
47871 
47872  //
47873 
47874  function Projector() {
47875 
47876  console.error( 'THREE.Projector has been moved to /examples/js/renderers/Projector.js.' );
47877 
47878  this.projectVector = function ( vector, camera ) {
47879 
47880  console.warn( 'THREE.Projector: .projectVector() is now vector.project().' );
47881  vector.project( camera );
47882 
47883  };
47884 
47885  this.unprojectVector = function ( vector, camera ) {
47886 
47887  console.warn( 'THREE.Projector: .unprojectVector() is now vector.unproject().' );
47888  vector.unproject( camera );
47889 
47890  };
47891 
47892  this.pickingRay = function () {
47893 
47894  console.error( 'THREE.Projector: .pickingRay() is now raycaster.setFromCamera().' );
47895 
47896  };
47897 
47898  }
47899 
47900  //
47901 
47902  function CanvasRenderer() {
47903 
47904  console.error( 'THREE.CanvasRenderer has been removed' );
47905 
47906  }
47907 
47908  //
47909 
47910  function JSONLoader() {
47911 
47912  console.error( 'THREE.JSONLoader has been removed.' );
47913 
47914  }
47915 
47916  //
47917 
47918  var SceneUtils = {
47919 
47920  createMultiMaterialObject: function ( /* geometry, materials */ ) {
47921 
47922  console.error( 'THREE.SceneUtils has been moved to /examples/js/utils/SceneUtils.js' );
47923 
47924  },
47925 
47926  detach: function ( /* child, parent, scene */ ) {
47927 
47928  console.error( 'THREE.SceneUtils has been moved to /examples/js/utils/SceneUtils.js' );
47929 
47930  },
47931 
47932  attach: function ( /* child, scene, parent */ ) {
47933 
47934  console.error( 'THREE.SceneUtils has been moved to /examples/js/utils/SceneUtils.js' );
47935 
47936  }
47937 
47938  };
47939 
47940  //
47941 
47942  function LensFlare() {
47943 
47944  console.error( 'THREE.LensFlare has been moved to /examples/js/objects/Lensflare.js' );
47945 
47946  }
47947 
47948  exports.WebGLMultisampleRenderTarget = WebGLMultisampleRenderTarget;
47949  exports.WebGLRenderTargetCube = WebGLRenderTargetCube;
47950  exports.WebGLRenderTarget = WebGLRenderTarget;
47951  exports.WebGLRenderer = WebGLRenderer;
47952  exports.ShaderLib = ShaderLib;
47953  exports.UniformsLib = UniformsLib;
47954  exports.UniformsUtils = UniformsUtils;
47955  exports.ShaderChunk = ShaderChunk;
47956  exports.FogExp2 = FogExp2;
47957  exports.Fog = Fog;
47958  exports.Scene = Scene;
47959  exports.Sprite = Sprite;
47960  exports.LOD = LOD;
47961  exports.SkinnedMesh = SkinnedMesh;
47962  exports.Skeleton = Skeleton;
47963  exports.Bone = Bone;
47964  exports.Mesh = Mesh;
47965  exports.LineSegments = LineSegments;
47966  exports.LineLoop = LineLoop;
47967  exports.Line = Line;
47968  exports.Points = Points;
47969  exports.Group = Group;
47970  exports.VideoTexture = VideoTexture;
47971  exports.DataTexture = DataTexture;
47972  exports.DataTexture3D = DataTexture3D;
47973  exports.CompressedTexture = CompressedTexture;
47974  exports.CubeTexture = CubeTexture;
47975  exports.CanvasTexture = CanvasTexture;
47976  exports.DepthTexture = DepthTexture;
47977  exports.Texture = Texture;
47978  exports.AnimationLoader = AnimationLoader;
47979  exports.CompressedTextureLoader = CompressedTextureLoader;
47980  exports.DataTextureLoader = DataTextureLoader;
47981  exports.CubeTextureLoader = CubeTextureLoader;
47982  exports.TextureLoader = TextureLoader;
47983  exports.ObjectLoader = ObjectLoader;
47984  exports.MaterialLoader = MaterialLoader;
47985  exports.BufferGeometryLoader = BufferGeometryLoader;
47986  exports.DefaultLoadingManager = DefaultLoadingManager;
47987  exports.LoadingManager = LoadingManager;
47988  exports.ImageLoader = ImageLoader;
47989  exports.ImageBitmapLoader = ImageBitmapLoader;
47990  exports.FontLoader = FontLoader;
47991  exports.FileLoader = FileLoader;
47992  exports.Loader = Loader;
47993  exports.LoaderUtils = LoaderUtils;
47994  exports.Cache = Cache;
47995  exports.AudioLoader = AudioLoader;
47996  exports.SpotLightShadow = SpotLightShadow;
47997  exports.SpotLight = SpotLight;
47998  exports.PointLight = PointLight;
47999  exports.RectAreaLight = RectAreaLight;
48000  exports.HemisphereLight = HemisphereLight;
48001  exports.DirectionalLightShadow = DirectionalLightShadow;
48002  exports.DirectionalLight = DirectionalLight;
48003  exports.AmbientLight = AmbientLight;
48004  exports.LightShadow = LightShadow;
48005  exports.Light = Light;
48006  exports.StereoCamera = StereoCamera;
48007  exports.PerspectiveCamera = PerspectiveCamera;
48008  exports.OrthographicCamera = OrthographicCamera;
48009  exports.CubeCamera = CubeCamera;
48010  exports.ArrayCamera = ArrayCamera;
48011  exports.Camera = Camera;
48012  exports.AudioListener = AudioListener;
48013  exports.PositionalAudio = PositionalAudio;
48014  exports.AudioContext = AudioContext;
48015  exports.AudioAnalyser = AudioAnalyser;
48016  exports.Audio = Audio;
48017  exports.VectorKeyframeTrack = VectorKeyframeTrack;
48018  exports.StringKeyframeTrack = StringKeyframeTrack;
48019  exports.QuaternionKeyframeTrack = QuaternionKeyframeTrack;
48020  exports.NumberKeyframeTrack = NumberKeyframeTrack;
48021  exports.ColorKeyframeTrack = ColorKeyframeTrack;
48022  exports.BooleanKeyframeTrack = BooleanKeyframeTrack;
48023  exports.PropertyMixer = PropertyMixer;
48024  exports.PropertyBinding = PropertyBinding;
48025  exports.KeyframeTrack = KeyframeTrack;
48026  exports.AnimationUtils = AnimationUtils;
48027  exports.AnimationObjectGroup = AnimationObjectGroup;
48028  exports.AnimationMixer = AnimationMixer;
48029  exports.AnimationClip = AnimationClip;
48030  exports.Uniform = Uniform;
48031  exports.InstancedBufferGeometry = InstancedBufferGeometry;
48032  exports.BufferGeometry = BufferGeometry;
48033  exports.Geometry = Geometry;
48034  exports.InterleavedBufferAttribute = InterleavedBufferAttribute;
48035  exports.InstancedInterleavedBuffer = InstancedInterleavedBuffer;
48036  exports.InterleavedBuffer = InterleavedBuffer;
48037  exports.InstancedBufferAttribute = InstancedBufferAttribute;
48038  exports.Face3 = Face3;
48039  exports.Object3D = Object3D;
48040  exports.Raycaster = Raycaster;
48041  exports.Layers = Layers;
48042  exports.EventDispatcher = EventDispatcher;
48043  exports.Clock = Clock;
48044  exports.QuaternionLinearInterpolant = QuaternionLinearInterpolant;
48045  exports.LinearInterpolant = LinearInterpolant;
48046  exports.DiscreteInterpolant = DiscreteInterpolant;
48047  exports.CubicInterpolant = CubicInterpolant;
48048  exports.Interpolant = Interpolant;
48049  exports.Triangle = Triangle;
48050  exports.Math = _Math;
48051  exports.Spherical = Spherical;
48052  exports.Cylindrical = Cylindrical;
48053  exports.Plane = Plane;
48054  exports.Frustum = Frustum;
48055  exports.Sphere = Sphere;
48056  exports.Ray = Ray;
48057  exports.Matrix4 = Matrix4;
48058  exports.Matrix3 = Matrix3;
48059  exports.Box3 = Box3;
48060  exports.Box2 = Box2;
48061  exports.Line3 = Line3;
48062  exports.Euler = Euler;
48063  exports.Vector4 = Vector4;
48064  exports.Vector3 = Vector3;
48065  exports.Vector2 = Vector2;
48066  exports.Quaternion = Quaternion;
48067  exports.Color = Color;
48068  exports.ImmediateRenderObject = ImmediateRenderObject;
48069  exports.VertexNormalsHelper = VertexNormalsHelper;
48070  exports.SpotLightHelper = SpotLightHelper;
48071  exports.SkeletonHelper = SkeletonHelper;
48072  exports.PointLightHelper = PointLightHelper;
48073  exports.RectAreaLightHelper = RectAreaLightHelper;
48074  exports.HemisphereLightHelper = HemisphereLightHelper;
48075  exports.GridHelper = GridHelper;
48076  exports.PolarGridHelper = PolarGridHelper;
48077  exports.PositionalAudioHelper = PositionalAudioHelper;
48078  exports.FaceNormalsHelper = FaceNormalsHelper;
48079  exports.DirectionalLightHelper = DirectionalLightHelper;
48080  exports.CameraHelper = CameraHelper;
48081  exports.BoxHelper = BoxHelper;
48082  exports.Box3Helper = Box3Helper;
48083  exports.PlaneHelper = PlaneHelper;
48084  exports.ArrowHelper = ArrowHelper;
48085  exports.AxesHelper = AxesHelper;
48086  exports.Shape = Shape;
48087  exports.Path = Path;
48088  exports.ShapePath = ShapePath;
48089  exports.Font = Font;
48090  exports.CurvePath = CurvePath;
48091  exports.Curve = Curve;
48092  exports.ImageUtils = ImageUtils;
48093  exports.ShapeUtils = ShapeUtils;
48094  exports.WebGLUtils = WebGLUtils;
48095  exports.WireframeGeometry = WireframeGeometry;
48096  exports.ParametricGeometry = ParametricGeometry;
48097  exports.ParametricBufferGeometry = ParametricBufferGeometry;
48098  exports.TetrahedronGeometry = TetrahedronGeometry;
48099  exports.TetrahedronBufferGeometry = TetrahedronBufferGeometry;
48100  exports.OctahedronGeometry = OctahedronGeometry;
48101  exports.OctahedronBufferGeometry = OctahedronBufferGeometry;
48102  exports.IcosahedronGeometry = IcosahedronGeometry;
48103  exports.IcosahedronBufferGeometry = IcosahedronBufferGeometry;
48104  exports.DodecahedronGeometry = DodecahedronGeometry;
48105  exports.DodecahedronBufferGeometry = DodecahedronBufferGeometry;
48106  exports.PolyhedronGeometry = PolyhedronGeometry;
48107  exports.PolyhedronBufferGeometry = PolyhedronBufferGeometry;
48108  exports.TubeGeometry = TubeGeometry;
48109  exports.TubeBufferGeometry = TubeBufferGeometry;
48110  exports.TorusKnotGeometry = TorusKnotGeometry;
48111  exports.TorusKnotBufferGeometry = TorusKnotBufferGeometry;
48112  exports.TorusGeometry = TorusGeometry;
48113  exports.TorusBufferGeometry = TorusBufferGeometry;
48114  exports.TextGeometry = TextGeometry;
48115  exports.TextBufferGeometry = TextBufferGeometry;
48116  exports.SphereGeometry = SphereGeometry;
48117  exports.SphereBufferGeometry = SphereBufferGeometry;
48118  exports.RingGeometry = RingGeometry;
48119  exports.RingBufferGeometry = RingBufferGeometry;
48120  exports.PlaneGeometry = PlaneGeometry;
48121  exports.PlaneBufferGeometry = PlaneBufferGeometry;
48122  exports.LatheGeometry = LatheGeometry;
48123  exports.LatheBufferGeometry = LatheBufferGeometry;
48124  exports.ShapeGeometry = ShapeGeometry;
48125  exports.ShapeBufferGeometry = ShapeBufferGeometry;
48126  exports.ExtrudeGeometry = ExtrudeGeometry;
48127  exports.ExtrudeBufferGeometry = ExtrudeBufferGeometry;
48128  exports.EdgesGeometry = EdgesGeometry;
48129  exports.ConeGeometry = ConeGeometry;
48130  exports.ConeBufferGeometry = ConeBufferGeometry;
48131  exports.CylinderGeometry = CylinderGeometry;
48132  exports.CylinderBufferGeometry = CylinderBufferGeometry;
48133  exports.CircleGeometry = CircleGeometry;
48134  exports.CircleBufferGeometry = CircleBufferGeometry;
48135  exports.BoxGeometry = BoxGeometry;
48136  exports.CubeGeometry = BoxGeometry;
48137  exports.BoxBufferGeometry = BoxBufferGeometry;
48138  exports.ShadowMaterial = ShadowMaterial;
48139  exports.SpriteMaterial = SpriteMaterial;
48140  exports.RawShaderMaterial = RawShaderMaterial;
48141  exports.ShaderMaterial = ShaderMaterial;
48142  exports.PointsMaterial = PointsMaterial;
48143  exports.MeshPhysicalMaterial = MeshPhysicalMaterial;
48144  exports.MeshStandardMaterial = MeshStandardMaterial;
48145  exports.MeshPhongMaterial = MeshPhongMaterial;
48146  exports.MeshToonMaterial = MeshToonMaterial;
48147  exports.MeshNormalMaterial = MeshNormalMaterial;
48148  exports.MeshLambertMaterial = MeshLambertMaterial;
48149  exports.MeshDepthMaterial = MeshDepthMaterial;
48150  exports.MeshDistanceMaterial = MeshDistanceMaterial;
48151  exports.MeshBasicMaterial = MeshBasicMaterial;
48152  exports.MeshMatcapMaterial = MeshMatcapMaterial;
48153  exports.LineDashedMaterial = LineDashedMaterial;
48154  exports.LineBasicMaterial = LineBasicMaterial;
48155  exports.Material = Material;
48156  exports.Float64BufferAttribute = Float64BufferAttribute;
48157  exports.Float32BufferAttribute = Float32BufferAttribute;
48158  exports.Uint32BufferAttribute = Uint32BufferAttribute;
48159  exports.Int32BufferAttribute = Int32BufferAttribute;
48160  exports.Uint16BufferAttribute = Uint16BufferAttribute;
48161  exports.Int16BufferAttribute = Int16BufferAttribute;
48162  exports.Uint8ClampedBufferAttribute = Uint8ClampedBufferAttribute;
48163  exports.Uint8BufferAttribute = Uint8BufferAttribute;
48164  exports.Int8BufferAttribute = Int8BufferAttribute;
48165  exports.BufferAttribute = BufferAttribute;
48166  exports.ArcCurve = ArcCurve;
48167  exports.CatmullRomCurve3 = CatmullRomCurve3;
48168  exports.CubicBezierCurve = CubicBezierCurve;
48169  exports.CubicBezierCurve3 = CubicBezierCurve3;
48170  exports.EllipseCurve = EllipseCurve;
48171  exports.LineCurve = LineCurve;
48172  exports.LineCurve3 = LineCurve3;
48173  exports.QuadraticBezierCurve = QuadraticBezierCurve;
48174  exports.QuadraticBezierCurve3 = QuadraticBezierCurve3;
48175  exports.SplineCurve = SplineCurve;
48176  exports.REVISION = REVISION;
48177  exports.MOUSE = MOUSE;
48178  exports.CullFaceNone = CullFaceNone;
48179  exports.CullFaceBack = CullFaceBack;
48180  exports.CullFaceFront = CullFaceFront;
48181  exports.CullFaceFrontBack = CullFaceFrontBack;
48182  exports.FrontFaceDirectionCW = FrontFaceDirectionCW;
48183  exports.FrontFaceDirectionCCW = FrontFaceDirectionCCW;
48184  exports.BasicShadowMap = BasicShadowMap;
48185  exports.PCFShadowMap = PCFShadowMap;
48186  exports.PCFSoftShadowMap = PCFSoftShadowMap;
48187  exports.FrontSide = FrontSide;
48188  exports.BackSide = BackSide;
48189  exports.DoubleSide = DoubleSide;
48190  exports.FlatShading = FlatShading;
48191  exports.SmoothShading = SmoothShading;
48192  exports.NoColors = NoColors;
48193  exports.FaceColors = FaceColors;
48194  exports.VertexColors = VertexColors;
48195  exports.NoBlending = NoBlending;
48196  exports.NormalBlending = NormalBlending;
48197  exports.AdditiveBlending = AdditiveBlending;
48198  exports.SubtractiveBlending = SubtractiveBlending;
48199  exports.MultiplyBlending = MultiplyBlending;
48200  exports.CustomBlending = CustomBlending;
48201  exports.AddEquation = AddEquation;
48202  exports.SubtractEquation = SubtractEquation;
48203  exports.ReverseSubtractEquation = ReverseSubtractEquation;
48204  exports.MinEquation = MinEquation;
48205  exports.MaxEquation = MaxEquation;
48206  exports.ZeroFactor = ZeroFactor;
48207  exports.OneFactor = OneFactor;
48208  exports.SrcColorFactor = SrcColorFactor;
48209  exports.OneMinusSrcColorFactor = OneMinusSrcColorFactor;
48210  exports.SrcAlphaFactor = SrcAlphaFactor;
48211  exports.OneMinusSrcAlphaFactor = OneMinusSrcAlphaFactor;
48212  exports.DstAlphaFactor = DstAlphaFactor;
48213  exports.OneMinusDstAlphaFactor = OneMinusDstAlphaFactor;
48214  exports.DstColorFactor = DstColorFactor;
48215  exports.OneMinusDstColorFactor = OneMinusDstColorFactor;
48216  exports.SrcAlphaSaturateFactor = SrcAlphaSaturateFactor;
48217  exports.NeverDepth = NeverDepth;
48218  exports.AlwaysDepth = AlwaysDepth;
48219  exports.LessDepth = LessDepth;
48220  exports.LessEqualDepth = LessEqualDepth;
48221  exports.EqualDepth = EqualDepth;
48222  exports.GreaterEqualDepth = GreaterEqualDepth;
48223  exports.GreaterDepth = GreaterDepth;
48224  exports.NotEqualDepth = NotEqualDepth;
48225  exports.MultiplyOperation = MultiplyOperation;
48226  exports.MixOperation = MixOperation;
48227  exports.AddOperation = AddOperation;
48228  exports.NoToneMapping = NoToneMapping;
48229  exports.LinearToneMapping = LinearToneMapping;
48230  exports.ReinhardToneMapping = ReinhardToneMapping;
48231  exports.Uncharted2ToneMapping = Uncharted2ToneMapping;
48232  exports.CineonToneMapping = CineonToneMapping;
48233  exports.ACESFilmicToneMapping = ACESFilmicToneMapping;
48234  exports.UVMapping = UVMapping;
48235  exports.CubeReflectionMapping = CubeReflectionMapping;
48236  exports.CubeRefractionMapping = CubeRefractionMapping;
48237  exports.EquirectangularReflectionMapping = EquirectangularReflectionMapping;
48238  exports.EquirectangularRefractionMapping = EquirectangularRefractionMapping;
48239  exports.SphericalReflectionMapping = SphericalReflectionMapping;
48240  exports.CubeUVReflectionMapping = CubeUVReflectionMapping;
48241  exports.CubeUVRefractionMapping = CubeUVRefractionMapping;
48242  exports.RepeatWrapping = RepeatWrapping;
48243  exports.ClampToEdgeWrapping = ClampToEdgeWrapping;
48244  exports.MirroredRepeatWrapping = MirroredRepeatWrapping;
48245  exports.NearestFilter = NearestFilter;
48246  exports.NearestMipMapNearestFilter = NearestMipMapNearestFilter;
48247  exports.NearestMipMapLinearFilter = NearestMipMapLinearFilter;
48248  exports.LinearFilter = LinearFilter;
48249  exports.LinearMipMapNearestFilter = LinearMipMapNearestFilter;
48250  exports.LinearMipMapLinearFilter = LinearMipMapLinearFilter;
48251  exports.UnsignedByteType = UnsignedByteType;
48252  exports.ByteType = ByteType;
48253  exports.ShortType = ShortType;
48254  exports.UnsignedShortType = UnsignedShortType;
48255  exports.IntType = IntType;
48256  exports.UnsignedIntType = UnsignedIntType;
48257  exports.FloatType = FloatType;
48258  exports.HalfFloatType = HalfFloatType;
48259  exports.UnsignedShort4444Type = UnsignedShort4444Type;
48260  exports.UnsignedShort5551Type = UnsignedShort5551Type;
48261  exports.UnsignedShort565Type = UnsignedShort565Type;
48262  exports.UnsignedInt248Type = UnsignedInt248Type;
48263  exports.AlphaFormat = AlphaFormat;
48264  exports.RGBFormat = RGBFormat;
48265  exports.RGBAFormat = RGBAFormat;
48266  exports.LuminanceFormat = LuminanceFormat;
48267  exports.LuminanceAlphaFormat = LuminanceAlphaFormat;
48268  exports.RGBEFormat = RGBEFormat;
48269  exports.DepthFormat = DepthFormat;
48270  exports.DepthStencilFormat = DepthStencilFormat;
48271  exports.RedFormat = RedFormat;
48272  exports.RGB_S3TC_DXT1_Format = RGB_S3TC_DXT1_Format;
48273  exports.RGBA_S3TC_DXT1_Format = RGBA_S3TC_DXT1_Format;
48274  exports.RGBA_S3TC_DXT3_Format = RGBA_S3TC_DXT3_Format;
48275  exports.RGBA_S3TC_DXT5_Format = RGBA_S3TC_DXT5_Format;
48276  exports.RGB_PVRTC_4BPPV1_Format = RGB_PVRTC_4BPPV1_Format;
48277  exports.RGB_PVRTC_2BPPV1_Format = RGB_PVRTC_2BPPV1_Format;
48278  exports.RGBA_PVRTC_4BPPV1_Format = RGBA_PVRTC_4BPPV1_Format;
48279  exports.RGBA_PVRTC_2BPPV1_Format = RGBA_PVRTC_2BPPV1_Format;
48280  exports.RGB_ETC1_Format = RGB_ETC1_Format;
48281  exports.RGBA_ASTC_4x4_Format = RGBA_ASTC_4x4_Format;
48282  exports.RGBA_ASTC_5x4_Format = RGBA_ASTC_5x4_Format;
48283  exports.RGBA_ASTC_5x5_Format = RGBA_ASTC_5x5_Format;
48284  exports.RGBA_ASTC_6x5_Format = RGBA_ASTC_6x5_Format;
48285  exports.RGBA_ASTC_6x6_Format = RGBA_ASTC_6x6_Format;
48286  exports.RGBA_ASTC_8x5_Format = RGBA_ASTC_8x5_Format;
48287  exports.RGBA_ASTC_8x6_Format = RGBA_ASTC_8x6_Format;
48288  exports.RGBA_ASTC_8x8_Format = RGBA_ASTC_8x8_Format;
48289  exports.RGBA_ASTC_10x5_Format = RGBA_ASTC_10x5_Format;
48290  exports.RGBA_ASTC_10x6_Format = RGBA_ASTC_10x6_Format;
48291  exports.RGBA_ASTC_10x8_Format = RGBA_ASTC_10x8_Format;
48292  exports.RGBA_ASTC_10x10_Format = RGBA_ASTC_10x10_Format;
48293  exports.RGBA_ASTC_12x10_Format = RGBA_ASTC_12x10_Format;
48294  exports.RGBA_ASTC_12x12_Format = RGBA_ASTC_12x12_Format;
48295  exports.LoopOnce = LoopOnce;
48296  exports.LoopRepeat = LoopRepeat;
48297  exports.LoopPingPong = LoopPingPong;
48298  exports.InterpolateDiscrete = InterpolateDiscrete;
48299  exports.InterpolateLinear = InterpolateLinear;
48300  exports.InterpolateSmooth = InterpolateSmooth;
48301  exports.ZeroCurvatureEnding = ZeroCurvatureEnding;
48302  exports.ZeroSlopeEnding = ZeroSlopeEnding;
48303  exports.WrapAroundEnding = WrapAroundEnding;
48304  exports.TrianglesDrawMode = TrianglesDrawMode;
48305  exports.TriangleStripDrawMode = TriangleStripDrawMode;
48306  exports.TriangleFanDrawMode = TriangleFanDrawMode;
48307  exports.LinearEncoding = LinearEncoding;
48308  exports.sRGBEncoding = sRGBEncoding;
48309  exports.GammaEncoding = GammaEncoding;
48310  exports.RGBEEncoding = RGBEEncoding;
48311  exports.LogLuvEncoding = LogLuvEncoding;
48312  exports.RGBM7Encoding = RGBM7Encoding;
48313  exports.RGBM16Encoding = RGBM16Encoding;
48314  exports.RGBDEncoding = RGBDEncoding;
48315  exports.BasicDepthPacking = BasicDepthPacking;
48316  exports.RGBADepthPacking = RGBADepthPacking;
48317  exports.TangentSpaceNormalMap = TangentSpaceNormalMap;
48318  exports.ObjectSpaceNormalMap = ObjectSpaceNormalMap;
48319  exports.Face4 = Face4;
48320  exports.LineStrip = LineStrip;
48321  exports.LinePieces = LinePieces;
48322  exports.MeshFaceMaterial = MeshFaceMaterial;
48323  exports.MultiMaterial = MultiMaterial;
48324  exports.PointCloud = PointCloud;
48325  exports.Particle = Particle;
48326  exports.ParticleSystem = ParticleSystem;
48327  exports.PointCloudMaterial = PointCloudMaterial;
48328  exports.ParticleBasicMaterial = ParticleBasicMaterial;
48329  exports.ParticleSystemMaterial = ParticleSystemMaterial;
48330  exports.Vertex = Vertex;
48331  exports.DynamicBufferAttribute = DynamicBufferAttribute;
48332  exports.Int8Attribute = Int8Attribute;
48333  exports.Uint8Attribute = Uint8Attribute;
48334  exports.Uint8ClampedAttribute = Uint8ClampedAttribute;
48335  exports.Int16Attribute = Int16Attribute;
48336  exports.Uint16Attribute = Uint16Attribute;
48337  exports.Int32Attribute = Int32Attribute;
48338  exports.Uint32Attribute = Uint32Attribute;
48339  exports.Float32Attribute = Float32Attribute;
48340  exports.Float64Attribute = Float64Attribute;
48341  exports.ClosedSplineCurve3 = ClosedSplineCurve3;
48342  exports.SplineCurve3 = SplineCurve3;
48343  exports.Spline = Spline;
48344  exports.AxisHelper = AxisHelper;
48345  exports.BoundingBoxHelper = BoundingBoxHelper;
48346  exports.EdgesHelper = EdgesHelper;
48347  exports.WireframeHelper = WireframeHelper;
48348  exports.XHRLoader = XHRLoader;
48349  exports.BinaryTextureLoader = BinaryTextureLoader;
48350  exports.GeometryUtils = GeometryUtils;
48351  exports.Projector = Projector;
48352  exports.CanvasRenderer = CanvasRenderer;
48353  exports.JSONLoader = JSONLoader;
48354  exports.SceneUtils = SceneUtils;
48355  exports.LensFlare = LensFlare;
48356 
48357  Object.defineProperty(exports, '__esModule', { value: true });
48358 
48359 }));